summaryrefslogtreecommitdiff
path: root/tools/proxyclient/m1n1/hv/gdbserver
diff options
context:
space:
mode:
Diffstat (limited to 'tools/proxyclient/m1n1/hv/gdbserver')
-rw-r--r--tools/proxyclient/m1n1/hv/gdbserver/__init__.py480
-rw-r--r--tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-core.xml91
-rw-r--r--tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-fpu.xml160
-rw-r--r--tools/proxyclient/m1n1/hv/gdbserver/features/target.xml8
4 files changed, 739 insertions, 0 deletions
diff --git a/tools/proxyclient/m1n1/hv/gdbserver/__init__.py b/tools/proxyclient/m1n1/hv/gdbserver/__init__.py
new file mode 100644
index 0000000..ade807f
--- /dev/null
+++ b/tools/proxyclient/m1n1/hv/gdbserver/__init__.py
@@ -0,0 +1,480 @@
+# SPDX-License-Identifier: MIT
+import errno, io, os, pkgutil, re, selectors, socketserver, threading, traceback
+from construct import Array, BytesInteger, Container, Int32ul, Int64ul, Struct
+
+from ...proxy import *
+from ...sysreg import *
+from ...utils import *
+
+from ..types import *
+
+__all__ = ["GDBServer"]
+
+class GDBServer:
+ __g = Struct(
+ "regs" / Array(32, Int64ul),
+ "pc" / Int64ul,
+ "spsr" / Int32ul,
+ "q" / Array(32, BytesInteger(16, swapped=True)),
+ "fpsr" / Int32ul,
+ "fpcr" / Int32ul,
+ )
+ __seperator = re.compile("[,;:]")
+
+ def __init__(self, hv, address, log):
+ self.__hc = None
+ self.__hg = None
+ self.__hv = hv
+ self.__interrupt_eventfd = os.eventfd(0, flags=os.EFD_CLOEXEC | os.EFD_NONBLOCK)
+ self.__interrupt_selector = selectors.DefaultSelector()
+ self.__request = None
+ self.log = log
+
+ self.__interrupt_selector.register(self.__interrupt_eventfd, selectors.EVENT_READ)
+
+ handle = self.__handle
+
+ class Handler(socketserver.BaseRequestHandler):
+ def handle(self):
+ handle(self.request)
+
+ self.__server = socketserver.UnixStreamServer(address, Handler, False)
+ self.__thread = threading.Thread(target=self.__server.serve_forever,)
+
+ def __add_wp(self, addr, kind, lsc):
+ start = addr & 7
+ if start + kind > 8:
+ return b"E01"
+
+ self.__hv.add_hw_wp(addr & ~7, ((1 << kind) - 1) << start, lsc)
+ return b"OK"
+
+ def __remove_wp(self, addr):
+ self.__hv.remove_hw_wp(addr & ~7)
+ return b"OK"
+
+ def __cpu(self, cpu):
+ if cpu is None:
+ return
+
+ self.__hv.cpu(cpu)
+
+ def __stop_reply(self):
+ self.__hc = None
+ self.__hg = None
+
+ prefix = b"T05thread:"
+
+ if self.__hv.exc_reason == START.EXCEPTION_LOWER:
+ if self.__hv.exc_code == EXC.SYNC:
+ if self.__hv.ctx.esr.EC == ESR_EC.BKPT_LOWER:
+ prefix = b"T05hwbreak:;thread:"
+ elif self.__hv.ctx.esr.EC == ESR_EC.WATCH_LOWER:
+ bas = self.__hv.get_wp_bas(self.__hv.ctx.far)
+ if not bas is None and bas != 0:
+ offset = 0
+ while (bas & (1 << offset)) == 0:
+ offset += 1
+ addr = self.__hv.ctx.far + offset
+ formatted_addr = bytes(format(addr, "x"), "utf-8")
+ prefix = b"T05watch:" + formatted_addr + b";thread:"
+ elif self.__hv.exc_reason == START.HV:
+ if self.__hv.exc_code == HV_EVENT.USER_INTERRUPT:
+ prefix = b"T02thread:"
+
+ return prefix + bytes(format(self.__hv.ctx.cpu_id, "x"), "utf-8") + b";"
+
+ def __wait_shell(self):
+ try:
+ os.eventfd_read(self.__interrupt_eventfd)
+ except BlockingIOError:
+ pass
+
+ while not self.__interrupt_eventfd in (key.fileobj for key, mask in self.__interrupt_selector.select()):
+ recv = self.__request.recv(1)
+ if not recv:
+ break
+
+ for byte in recv:
+ if byte in b"\1\3":
+ self.__hv.interrupt()
+ break
+
+ def __eval(self, data):
+ if self.log:
+ self.log(f"eval: {data}")
+
+ if len(data) < 1:
+ return b""
+
+ if data[0] in b"?":
+ return self.__stop_reply()
+
+ if data[0] in b"c":
+ if len(data) != 1:
+ self.__cpu(self.__hc)
+ self.__hv.ctx.elr = int(data[1:].decode(), 16)
+
+ self.__hv.cont()
+ self.__wait_shell()
+ return self.__stop_reply()
+
+ if data[0] in b"g":
+ self.__cpu(self.__hg)
+ g = Container()
+ g.regs = self.__hv.ctx.regs.copy()
+ g.regs[31] = self.__hv.ctx.sp[1]
+ g.pc = self.__hv.ctx.elr
+ g.spsr = self.__hv.ctx.spsr.value
+ g.q = self.__hv.u.q
+ g.fpsr = self.__hv.u.mrs(FPSR)
+ g.fpcr = self.__hv.u.mrs(FPCR)
+
+ return bytes(GDBServer.__g.build(g).hex(), "utf-8")
+
+ if data[0] in b"G":
+ g = GDBServer.__g.parse(bytes.fromhex(data[1:].decode()))
+ self.__cpu(self.__hg)
+
+ for index in range(31):
+ self.__hv.ctx.regs[index] = g.regs[index]
+
+ self.__hv.ctx.sp[1] = g.regs[31]
+ self.__hv.ctx.elr = g.pc
+ self.__hv.ctx.spsr = g.spsr.value
+
+ q = self.__hv.u.q
+ for index, value in enumerate(g.q):
+ q[index] = value
+ self.__hv.u.push_simd()
+
+ self.__hv.u.msr(FPSR, g.fpsr, silent=True)
+ self.__hv.u.msr(FPCR, g.fpsr, silent=True)
+
+ return b"OK"
+
+ if data[0] in b"H":
+ if len(data) > 1:
+ if data[1] in b"c":
+ cpu_id = int(data[2:].decode(), 16)
+ if cpu_id in self.__hv.started_cpus:
+ self.__hc = cpu_id
+ return b"OK"
+
+ return b"E01"
+
+ if data[1] in b"g":
+ cpu_id = int(data[2:].decode(), 16)
+ if cpu_id in self.__hv.started_cpus:
+ self.__hg = cpu_id
+ return b"OK"
+
+ return b"E01"
+
+ return b""
+
+ if data[0] in b"krR":
+ self.__hv.reboot()
+
+ if data[0] in b"m":
+ split = GDBServer.__seperator.split(data[1:].decode(), maxsplit=1)
+ fields = [int(field, 16) for field in split]
+ return bytes(self.__hv.readmem(fields[0], fields[1]).hex(), "utf-8")
+
+ if data[0] in b"M":
+ split = GDBServer.__seperator.split(data[1:].decode(), maxsplit=2)
+ mem = bytes.fromhex(split[2])[:int(split[1], 16)]
+ if self.__hv.writemem(int(split[0], 16), mem) < len(mem):
+ return "E22"
+
+ return b"OK"
+
+ if data[0] in b"p":
+ number = int(data[1:].decode(), 16)
+ self.__cpu(self.__hg)
+ if number < 31:
+ reg = GDBServer.__g.regs.subcon.subcon.build(self.__hv.ctx.regs[number])
+ elif number == 31:
+ reg = GDBServer.__g.regs.subcon.subcon.build(self.__hv.ctx.sp[1])
+ elif number == 32:
+ reg = GDBServer.__g.pc.build(self.__hv.ctx.elr)
+ elif number == 33:
+ reg = GDBServer.__g.spsr.build(self.__hv.ctx.spsr.value)
+ elif number < 66:
+ reg = GDBServer.__g.q.subcon.subcon.build(self.__hv.u.q[number - 34])
+ elif number == 66:
+ reg = GDBServer.__g.fpsr.build(self.__hv.u.mrs(FPSR))
+ elif number == 67:
+ reg = GDBServer.__g.fpcr.build(self.__hv.u.mrs(FPCR))
+ else:
+ return b"E01"
+
+ return bytes(reg.hex(), "utf-8")
+
+ if data[0] in b"P":
+ partition = data[1:].partition(b"=")
+ number = int(partition[0].decode(), 16)
+ reg = bytes.fromhex(partition[2].decode())
+ self.__cpu(self.__hg)
+ if number < 31:
+ self.__hv.ctx.regs[number] = GDBServer.__g.regs.subcon.subcon.unpack(reg)
+ elif number == 31:
+ self.__hv.ctx.regs[1] = GDBServer.__g.regs.subcon.subcon.unpack(reg)
+ elif number == 32:
+ self.__hv.ctx.elr = GDBServer.__g.pc.parse(reg)
+ elif number == 33:
+ self.__hv.ctx.spsr.value = GDBServer.__g.spsr.parse(reg)
+ elif number < 66:
+ self.__hv.u.q[number - 34] = GDBServer.__g.q.subcon.subcon.parse(reg)
+ self.__hv.u.push_simd()
+ elif number == 66:
+ self.__hv.u.msr(FPSR, GDBServer.__g.fpsr.parse(reg), silent=True)
+ elif number == 67:
+ self.__hv.u.msr(FPCR, GDBServer.__g.fpcr.parse(reg), silent=True)
+ else:
+ return b"E01"
+
+ return b"OK"
+
+ if data[0] in b"q":
+ split = GDBServer.__seperator.split(data[1:].decode(), maxsplit=1)
+ if split[0] == "C":
+ cpu_id = self.__hg or self.__hv.ctx.cpu_id
+ return b"QC" + bytes(format(cpu_id, "x"), "utf-8")
+
+ if split[0] == "fThreadInfo":
+ cpu_ids = b",".join(bytes(format(cpu.cpu_id, "x"), "utf-8") for cpu in self.__hv.adt["cpus"])
+ return b"m" + cpu_ids
+
+ if split[0] == "sThreadInfo":
+ return b"l"
+
+ if split[0] == "Rcmd":
+ self.__cpu(self.__hg)
+ self.__hv.run_code(split[1])
+ return b"OK"
+
+ if split[0] == "Supported":
+ return b"PacketSize=65536;qXfer:features:read+;hwbreak+"
+
+ if split[0] == "ThreadExtraInfo":
+ thread_id = int(split[1], 16)
+ for node in self.__hv.adt["cpus"]:
+ if node.cpu_id == thread_id:
+ return bytes(bytes(str(node), "utf-8").hex(), "utf-8")
+
+ return b""
+
+ if split[0] == "Xfer":
+ xfer = GDBServer.__seperator.split(split[1], maxsplit=4)
+ if xfer[0] == "features" and xfer[1] == "read":
+ resource = os.path.join("features", xfer[2])
+ annex = pkgutil.get_data(__name__, resource)
+ if annex is None:
+ return b"E00"
+
+ request_offset = int(xfer[3], 16)
+ request_len = int(xfer[4], 16)
+ read = annex[request_offset:request_offset + request_len]
+ return (b"l" if len(read) < request_len else b"m") + read
+
+ return b""
+
+ if split[0] == "HostInfo":
+ addressing_bits = bytes(str(64 - self.__hv.pac_mask.bit_count()), "utf-8")
+ return b"cputype:16777228;cpusubtype:2;endian:little;ptrsize:64;watchpoint_exceptions_received:before;addressing_bits:" + addressing_bits + b";"
+
+ return b""
+
+ if data[0] in b"s":
+ self.__cpu(self.__hc)
+
+ if len(data) != 1:
+ self.__hv.ctx.elr = int(data[1:].decode(), 16)
+
+ self.__hv.step()
+ return self.__stop_reply()
+
+ if data[0] in b"T":
+ if int(data[1:].decode(), 16) in self.__hv.started_cpus:
+ return b"OK"
+
+ return b"E01"
+
+ if data[0] in b"X":
+ partition = data[1:].partition(b":")
+ split = GDBServer.__seperator.split(partition[0].decode(), maxsplit=1)
+ mem = partition[2][:int(split[1], 16)]
+ if self.__hv.writemem(int(split[0], 16), mem) < len(mem):
+ return b"E22"
+
+ return b"OK"
+
+ if data[0] in b"z":
+ split = GDBServer.__seperator.split(data[1:].decode(), maxsplit=2)
+ if split[0] == "1":
+ self.__hv.remove_hw_bp(int(split[1], 16))
+ return b"OK"
+
+ if split[0] == "2":
+ return self.__remove_wp(int(split[1], 16))
+
+ if split[0] == "3":
+ return self.__remove_wp(int(split[1], 16))
+
+ if split[0] == "4":
+ return self.__remove_wp(int(split[1], 16))
+
+ return b""
+
+ if data[0] in b"Z":
+ split = GDBServer.__seperator.split(data[1:].decode(), maxsplit=2)
+ if split[0] == "1":
+ self.__hv.add_hw_bp(int(split[1], 16))
+ return b"OK"
+
+ if split[0] == "2":
+ addr = int(split[1], 16)
+ kind = int(split[2], 16)
+ return self.__add_wp(addr, kind, DBGWCR_LSC.S)
+
+ if split[0] == "3":
+ addr = int(split[1], 16)
+ kind = int(split[2], 16)
+ return self.__add_wp(addr, kind, DBGWCR_LSC.L)
+
+ if split[0] == "4":
+ addr = int(split[1], 16)
+ kind = int(split[2], 16)
+ return self.__add_wp(addr, kind, DBGWCR_LSC.S | DBGWCR_LSC.L)
+
+ return b""
+
+ return b""
+
+ def __send(self, prefix, data):
+ with io.BytesIO(prefix) as buffer:
+ buffer.write(prefix)
+
+ last = 0
+ for index, byte in enumerate(data):
+ if not byte in b"#$}*":
+ continue
+
+ buffer.write(data[last:index])
+ buffer.write(b"}")
+ buffer.write(bytes([byte ^ 0x20]))
+ last = index + 1
+
+ buffer.write(data[last:])
+ checksum = (sum(buffer.getvalue()) - sum(prefix)) % 256
+
+ buffer.write(b"#")
+ buffer.write(bytes(format(checksum, "02x"), "utf-8"))
+
+ value = buffer.getvalue()
+
+ if self.log:
+ self.log(f"send: {value}")
+
+ self.__request.send(value)
+
+ def __handle(self, request):
+ self.__request = request
+ input_buffer = b""
+
+ if not self.__hv.in_shell:
+ self.__hv.interrupt()
+ self.__wait_shell()
+
+ self.__interrupt_selector.register(self.__request, selectors.EVENT_READ)
+ try:
+ while True:
+ recv = self.__request.recv(65536)
+ if not recv:
+ break
+
+ input_buffer += recv
+
+ while True:
+ dollar = input_buffer.find(b"$")
+ if dollar < 0:
+ input_buffer = b""
+ break
+
+ sharp = input_buffer.find(b"#", dollar)
+ if sharp < 0 or len(input_buffer) < sharp + 3:
+ input_buffer = input_buffer[dollar:]
+ break
+
+ input_data = input_buffer[dollar + 1:sharp]
+ input_checksum = input_buffer[sharp + 1:sharp + 3]
+ input_buffer = input_buffer[sharp + 3:]
+
+ try:
+ parsed_input_checksum = int(input_checksum.decode(), 16)
+ except ValueError as error:
+ print(error)
+ continue
+
+ if (sum(input_data) % 256) != parsed_input_checksum:
+ self.__request.send(b"-")
+ continue
+
+ self.__request.send(b"+")
+
+ with io.BytesIO() as input_decoded:
+ input_index = 0
+ input_last = 0
+ while input_index < len(input_data):
+ if input_data[input_index] == b"*":
+ input_decoded.write(input_data[input_last:input_index])
+ instance = input_decoded.getvalue()[-1]
+ input_index += 1
+ input_run_len = input_data[input_index] - 29
+ input_run = bytes([instance]) * input_run_len
+ input_decoded.write(input_run)
+ input_index += 1
+ input_last = input_index
+ elif input_data[input_index] == b"}":
+ input_decoded.write(input_data[input_last:input_index])
+ input_index += 1
+ input_decoded.write(bytes([input_data[input_index] ^ 0x20]))
+ input_index += 1
+ input_last = input_index
+ else:
+ input_index += 1
+
+ input_decoded.write(input_data[input_last:])
+
+ try:
+ output_decoded = self.__eval(input_decoded.getvalue())
+ except Exception:
+ output_decoded = b"E." + bytes(traceback.format_exc(), "utf-8")
+
+ self.__send(b"$", output_decoded)
+ finally:
+ self.__interrupt_selector.unregister(self.__request)
+
+ def notify_in_shell(self):
+ os.eventfd_write(self.__interrupt_eventfd, 1)
+
+ def activate(self):
+ try:
+ self.__server.server_bind()
+ except OSError as error:
+ if error.errno != errno.EADDRINUSE:
+ raise
+
+ os.remove(self.__server.server_address)
+ self.__server.server_bind()
+
+ self.__server.server_activate()
+ self.__thread.start()
+
+ def shutdown(self):
+ os.close(self.__interrupt_eventfd)
+ self.__interrupt_selector.close()
+ self.__server.shutdown()
+ self.__server.server_close()
+ self.__thread.join()
diff --git a/tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-core.xml b/tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-core.xml
new file mode 100644
index 0000000..b6d344f
--- /dev/null
+++ b/tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-core.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009-2022 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.core">
+ <reg name="x0" bitsize="64"/>
+ <reg name="x1" bitsize="64"/>
+ <reg name="x2" bitsize="64"/>
+ <reg name="x3" bitsize="64"/>
+ <reg name="x4" bitsize="64"/>
+ <reg name="x5" bitsize="64"/>
+ <reg name="x6" bitsize="64"/>
+ <reg name="x7" bitsize="64"/>
+ <reg name="x8" bitsize="64"/>
+ <reg name="x9" bitsize="64"/>
+ <reg name="x10" bitsize="64"/>
+ <reg name="x11" bitsize="64"/>
+ <reg name="x12" bitsize="64"/>
+ <reg name="x13" bitsize="64"/>
+ <reg name="x14" bitsize="64"/>
+ <reg name="x15" bitsize="64"/>
+ <reg name="x16" bitsize="64"/>
+ <reg name="x17" bitsize="64"/>
+ <reg name="x18" bitsize="64"/>
+ <reg name="x19" bitsize="64"/>
+ <reg name="x20" bitsize="64"/>
+ <reg name="x21" bitsize="64"/>
+ <reg name="x22" bitsize="64"/>
+ <reg name="x23" bitsize="64"/>
+ <reg name="x24" bitsize="64"/>
+ <reg name="x25" bitsize="64"/>
+ <reg name="x26" bitsize="64"/>
+ <reg name="x27" bitsize="64"/>
+ <reg name="x28" bitsize="64"/>
+ <reg name="x29" bitsize="64"/>
+ <reg name="x30" bitsize="64"/>
+ <reg name="sp" bitsize="64" type="data_ptr"/>
+
+ <reg name="pc" bitsize="64" type="code_ptr"/>
+
+ <flags id="cpsr_flags" size="4">
+ <!-- Stack Pointer. -->
+ <field name="SP" start="0" end="0"/>
+
+ <!-- Exception Level. -->
+ <field name="EL" start="2" end="3"/>
+ <!-- Execution state. -->
+ <field name="nRW" start="4" end="4"/>
+
+ <!-- FIQ interrupt mask. -->
+ <field name="F" start="6" end="6"/>
+ <!-- IRQ interrupt mask. -->
+ <field name="I" start="7" end="7"/>
+ <!-- SError interrupt mask. -->
+ <field name="A" start="8" end="8"/>
+ <!-- Debug exception mask. -->
+ <field name="D" start="9" end="9"/>
+
+ <!-- ARMv8.0-A: Speculative Store Bypass. -->
+ <field name="SSBS" start="12" end="12"/>
+
+ <!-- Illegal Execution state. -->
+ <field name="IL" start="20" end="20"/>
+ <!-- Software Step. -->
+ <field name="SS" start="21" end="21"/>
+ <!-- ARMv8.1-A: Privileged Access Never. -->
+ <field name="PAN" start="22" end="22"/>
+ <!-- ARMv8.2-A: User Access Override. -->
+ <field name="UAO" start="23" end="23"/>
+ <!-- ARMv8.4-A: Data Independent Timing. -->
+ <field name="DIT" start="24" end="24"/>
+ <!-- ARMv8.5-A: Tag Check Override. -->
+ <field name="TCO" start="25" end="25"/>
+
+ <!-- Overflow Condition flag. -->
+ <field name="V" start="28" end="28"/>
+ <!-- Carry Condition flag. -->
+ <field name="C" start="29" end="29"/>
+ <!-- Zero Condition flag. -->
+ <field name="Z" start="30" end="30"/>
+ <!-- Negative Condition flag. -->
+ <field name="N" start="31" end="31"/>
+ </flags>
+ <reg name="cpsr" bitsize="32" type="cpsr_flags"/>
+
+</feature>
diff --git a/tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-fpu.xml b/tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-fpu.xml
new file mode 100644
index 0000000..4db5c50
--- /dev/null
+++ b/tools/proxyclient/m1n1/hv/gdbserver/features/aarch64-fpu.xml
@@ -0,0 +1,160 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009-2022 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.fpu">
+ <vector id="v2d" type="ieee_double" count="2"/>
+ <vector id="v2u" type="uint64" count="2"/>
+ <vector id="v2i" type="int64" count="2"/>
+ <vector id="v4f" type="ieee_single" count="4"/>
+ <vector id="v4u" type="uint32" count="4"/>
+ <vector id="v4i" type="int32" count="4"/>
+ <vector id="v8f" type="ieee_half" count="8"/>
+ <vector id="v8u" type="uint16" count="8"/>
+ <vector id="v8i" type="int16" count="8"/>
+ <vector id="v8bf16" type="bfloat16" count="8"/>
+ <vector id="v16u" type="uint8" count="16"/>
+ <vector id="v16i" type="int8" count="16"/>
+ <vector id="v1u" type="uint128" count="1"/>
+ <vector id="v1i" type="int128" count="1"/>
+ <union id="vnd">
+ <field name="f" type="v2d"/>
+ <field name="u" type="v2u"/>
+ <field name="s" type="v2i"/>
+ </union>
+ <union id="vns">
+ <field name="f" type="v4f"/>
+ <field name="u" type="v4u"/>
+ <field name="s" type="v4i"/>
+ </union>
+ <union id="vnh">
+ <field name="bf" type="v8bf16"/>
+ <field name="f" type="v8f"/>
+ <field name="u" type="v8u"/>
+ <field name="s" type="v8i"/>
+ </union>
+ <union id="vnb">
+ <field name="u" type="v16u"/>
+ <field name="s" type="v16i"/>
+ </union>
+ <union id="vnq">
+ <field name="u" type="v1u"/>
+ <field name="s" type="v1i"/>
+ </union>
+ <union id="aarch64v">
+ <field name="d" type="vnd"/>
+ <field name="s" type="vns"/>
+ <field name="h" type="vnh"/>
+ <field name="b" type="vnb"/>
+ <field name="q" type="vnq"/>
+ </union>
+ <reg name="v0" bitsize="128" type="aarch64v" regnum="34"/>
+ <reg name="v1" bitsize="128" type="aarch64v" />
+ <reg name="v2" bitsize="128" type="aarch64v" />
+ <reg name="v3" bitsize="128" type="aarch64v" />
+ <reg name="v4" bitsize="128" type="aarch64v" />
+ <reg name="v5" bitsize="128" type="aarch64v" />
+ <reg name="v6" bitsize="128" type="aarch64v" />
+ <reg name="v7" bitsize="128" type="aarch64v" />
+ <reg name="v8" bitsize="128" type="aarch64v" />
+ <reg name="v9" bitsize="128" type="aarch64v" />
+ <reg name="v10" bitsize="128" type="aarch64v"/>
+ <reg name="v11" bitsize="128" type="aarch64v"/>
+ <reg name="v12" bitsize="128" type="aarch64v"/>
+ <reg name="v13" bitsize="128" type="aarch64v"/>
+ <reg name="v14" bitsize="128" type="aarch64v"/>
+ <reg name="v15" bitsize="128" type="aarch64v"/>
+ <reg name="v16" bitsize="128" type="aarch64v"/>
+ <reg name="v17" bitsize="128" type="aarch64v"/>
+ <reg name="v18" bitsize="128" type="aarch64v"/>
+ <reg name="v19" bitsize="128" type="aarch64v"/>
+ <reg name="v20" bitsize="128" type="aarch64v"/>
+ <reg name="v21" bitsize="128" type="aarch64v"/>
+ <reg name="v22" bitsize="128" type="aarch64v"/>
+ <reg name="v23" bitsize="128" type="aarch64v"/>
+ <reg name="v24" bitsize="128" type="aarch64v"/>
+ <reg name="v25" bitsize="128" type="aarch64v"/>
+ <reg name="v26" bitsize="128" type="aarch64v"/>
+ <reg name="v27" bitsize="128" type="aarch64v"/>
+ <reg name="v28" bitsize="128" type="aarch64v"/>
+ <reg name="v29" bitsize="128" type="aarch64v"/>
+ <reg name="v30" bitsize="128" type="aarch64v"/>
+ <reg name="v31" bitsize="128" type="aarch64v"/>
+
+ <flags id="fpsr_flags" size="4">
+ <!-- Invalid Operation cumulative floating-point exception bit. -->
+ <field name="IOC" start="0" end="0"/>
+ <!-- Divide by Zero cumulative floating-point exception bit. -->
+ <field name="DZC" start="1" end="1"/>
+ <!-- Overflow cumulative floating-point exception bit. -->
+ <field name="OFC" start="2" end="2"/>
+ <!-- Underflow cumulative floating-point exception bit. -->
+ <field name="UFC" start="3" end="3"/>
+ <!-- Inexact cumulative floating-point exception bit.. -->
+ <field name="IXC" start="4" end="4"/>
+ <!-- Input Denormal cumulative floating-point exception bit. -->
+ <field name="IDC" start="7" end="7"/>
+ <!-- Cumulative saturation bit, Advanced SIMD only. -->
+ <field name="QC" start="27" end="27"/>
+ <!-- When AArch32 is supported at any Exception level and AArch32
+ floating-point is implemented: Overflow condition flag for AArch32
+ floating-point comparison operations. -->
+ <field name="V" start="28" end="28"/>
+ <!-- When AArch32 is supported at any Exception level and AArch32
+ floating-point is implemented:
+ Carry condition flag for AArch32 floating-point comparison operations.
+ -->
+ <field name="C" start="29" end="29"/>
+ <!-- When AArch32 is supported at any Exception level and AArch32
+ floating-point is implemented:
+ Zero condition flag for AArch32 floating-point comparison operations.
+ -->
+ <field name="Z" start="30" end="30"/>
+ <!-- When AArch32 is supported at any Exception level and AArch32
+ floating-point is implemented:
+ Negative condition flag for AArch32 floating-point comparison
+ operations. -->
+ <field name="N" start="31" end="31"/>
+ </flags>
+ <reg name="fpsr" bitsize="32" type="fpsr_flags"/>
+
+ <flags id="fpcr_flags" size="4">
+ <!-- Flush Inputs to Zero (part of Armv8.7). -->
+ <field name="FIZ" start="0" end="0"/>
+ <!-- Alternate Handling (part of Armv8.7). -->
+ <field name="AH" start="1" end="1"/>
+ <!-- Controls how the output elements other than the lowest element of the
+ vector are determined for Advanced SIMD scalar instructions (part of
+ Armv8.7). -->
+ <field name="NEP" start="2" end="2"/>
+ <!-- Invalid Operation floating-point exception trap enable. -->
+ <field name="IOE" start="8" end="8"/>
+ <!-- Divide by Zero floating-point exception trap enable. -->
+ <field name="DZE" start="9" end="9"/>
+ <!-- Overflow floating-point exception trap enable. -->
+ <field name="OFE" start="10" end="10"/>
+ <!-- Underflow floating-point exception trap enable. -->
+ <field name="UFE" start="11" end="11"/>
+ <!-- Inexact floating-point exception trap enable. -->
+ <field name="IXE" start="12" end="12"/>
+ <!-- Input Denormal floating-point exception trap enable. -->
+ <field name="IDE" start="15" end="15"/>
+ <!-- Flush-to-zero mode control bit on half-precision data-processing
+ instructions. -->
+ <field name="FZ16" start="19" end="19"/>
+ <!-- Rounding Mode control field. -->
+ <field name="RMode" start="22" end="23"/>
+ <!-- Flush-to-zero mode control bit. -->
+ <field name="FZ" start="24" end="24"/>
+ <!-- Default NaN mode control bit. -->
+ <field name="DN" start="25" end="25"/>
+ <!-- Alternative half-precision control bit. -->
+ <field name="AHP" start="26" end="26"/>
+ </flags>
+ <reg name="fpcr" bitsize="32" type="fpcr_flags"/>
+</feature>
diff --git a/tools/proxyclient/m1n1/hv/gdbserver/features/target.xml b/tools/proxyclient/m1n1/hv/gdbserver/features/target.xml
new file mode 100644
index 0000000..ca0454a
--- /dev/null
+++ b/tools/proxyclient/m1n1/hv/gdbserver/features/target.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<!-- SPDX-License-Identifier: MIT -->
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target version="1.0">
+ <architecture>aarch64</architecture>
+ <xi:include href="aarch64-core.xml" />
+ <xi:include href="aarch64-fpu.xml" />
+</target>