arch-riscv: CSR registers support in RISC-V remote GDB.
Note: Some less frequently needed CSR registers (e.g. hpm and pmp registers) are commented out on purpose. Instructions to add them back are described in remote_gdb.hh comments. This is to avoid spamming the remote GDB log when using `info reg all`. Changes: 1. Added GDB XML files to the ext/ directory (mostly from QEMU) 2. Modified RiscvGdbRegCache - struct r: added CSR registers - getRegs, setRegs: reading / setting CSR registers 3. Modified RemoteGDB - availableFeatures: indicate support for XML registers - getXferFeaturesRead: return XML blobs Change-Id: Ica03b63edb3f0c9b6a7789228b995891dbfb26b2 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/38955 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
# Copyright (c) 2013 ARM Limited
|
||||
# Copyright (c) 2014 Sven Karlsson
|
||||
# Copyright (c) 2020 Barkhausen Institut
|
||||
# Copyright (c) 2021 Huawei International
|
||||
# All rights reserved
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
@@ -73,3 +74,8 @@ if env['TARGET_ISA'] == 'riscv':
|
||||
|
||||
# Add in files generated by the ISA description.
|
||||
ISADesc('isa/main.isa')
|
||||
|
||||
GdbXml('riscv.xml', 'gdb_xml_riscv_target')
|
||||
GdbXml('riscv-64bit-cpu.xml', 'gdb_xml_riscv_cpu')
|
||||
GdbXml('riscv-64bit-fpu.xml', 'gdb_xml_riscv_fpu')
|
||||
GdbXml('riscv-64bit-csr.xml', 'gdb_xml_riscv_csr')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei International
|
||||
* Copyright 2015 LabWare
|
||||
* Copyright 2014 Google, Inc.
|
||||
* Copyright (c) 2010 ARM Limited
|
||||
@@ -137,6 +138,11 @@
|
||||
#include "arch/riscv/mmu.hh"
|
||||
#include "arch/riscv/pagetable_walker.hh"
|
||||
#include "arch/riscv/registers.hh"
|
||||
#include "arch/riscv/tlb.hh"
|
||||
#include "blobs/gdb_xml_riscv_cpu.hh"
|
||||
#include "blobs/gdb_xml_riscv_csr.hh"
|
||||
#include "blobs/gdb_xml_riscv_fpu.hh"
|
||||
#include "blobs/gdb_xml_riscv_target.hh"
|
||||
#include "cpu/thread_state.hh"
|
||||
#include "debug/GDBAcc.hh"
|
||||
#include "mem/page_table.hh"
|
||||
@@ -165,7 +171,7 @@ RemoteGDB::acc(Addr va, size_t len)
|
||||
satp.mode != AddrXlateMode::BARE) {
|
||||
Walker *walker = mmu->getDataWalker();
|
||||
Fault fault = walker->startFunctional(
|
||||
context(), paddr, logBytes, BaseTLB::Read);
|
||||
context(), paddr, logBytes, BaseTLB::Read);
|
||||
if (fault != NoFault)
|
||||
return false;
|
||||
}
|
||||
@@ -179,21 +185,304 @@ void
|
||||
RemoteGDB::RiscvGdbRegCache::getRegs(ThreadContext *context)
|
||||
{
|
||||
DPRINTF(GDBAcc, "getregs in remotegdb, size %lu\n", size());
|
||||
|
||||
// General registers
|
||||
for (int i = 0; i < NumIntArchRegs; i++)
|
||||
{
|
||||
r.gpr[i] = context->readIntReg(i);
|
||||
}
|
||||
r.pc = context->pcState().pc();
|
||||
|
||||
// Floating point registers
|
||||
for (int i = 0; i < NumFloatRegs; i++)
|
||||
r.fpu[i] = context->readFloatReg(i);
|
||||
r.fflags = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_FFLAGS).physIndex) & CSRMasks.at(CSR_FFLAGS);
|
||||
r.frm = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_FRM).physIndex) & CSRMasks.at(CSR_FRM);
|
||||
r.fcsr = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_FCSR).physIndex) & CSRMasks.at(CSR_FCSR);
|
||||
|
||||
// CSR registers
|
||||
r.cycle = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_CYCLE).physIndex);
|
||||
r.time = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_TIME).physIndex);
|
||||
|
||||
// U mode CSR
|
||||
r.ustatus = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_USTATUS).physIndex) & CSRMasks.at(CSR_USTATUS);
|
||||
r.uie = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UIE).physIndex) & CSRMasks.at(CSR_UIE);
|
||||
r.utvec = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UTVEC).physIndex);
|
||||
r.uscratch = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_USCRATCH).physIndex);
|
||||
r.uepc = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UEPC).physIndex);
|
||||
r.ucause = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UCAUSE).physIndex);
|
||||
r.utval = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UTVAL).physIndex);
|
||||
r.uip = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UIP).physIndex) & CSRMasks.at(CSR_UIP);
|
||||
|
||||
// S mode CSR
|
||||
r.sstatus = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SSTATUS).physIndex) & CSRMasks.at(CSR_SSTATUS);
|
||||
r.sedeleg = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SEDELEG).physIndex);
|
||||
r.sideleg = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIDELEG).physIndex);
|
||||
r.sie = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIE).physIndex) & CSRMasks.at(CSR_SIE);
|
||||
r.stvec = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_STVEC).physIndex);
|
||||
r.scounteren = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SCOUNTEREN).physIndex);
|
||||
r.sscratch = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SSCRATCH).physIndex);
|
||||
r.sepc = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SEPC).physIndex);
|
||||
r.scause = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SCAUSE).physIndex);
|
||||
r.stval = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_STVAL).physIndex);
|
||||
r.sip = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIP).physIndex) & CSRMasks.at(CSR_SIP);
|
||||
r.satp = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SATP).physIndex);
|
||||
|
||||
// M mode CSR
|
||||
r.mvendorid = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MVENDORID).physIndex);
|
||||
r.marchid = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MARCHID).physIndex);
|
||||
r.mimpid = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIMPID).physIndex);
|
||||
r.mhartid = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MHARTID).physIndex);
|
||||
r.mstatus = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MSTATUS).physIndex) & CSRMasks.at(CSR_MSTATUS);
|
||||
r.misa = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MISA).physIndex) & CSRMasks.at(CSR_MISA);
|
||||
r.medeleg = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MEDELEG).physIndex);
|
||||
r.mideleg = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIDELEG).physIndex);
|
||||
r.mie = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIE).physIndex) & CSRMasks.at(CSR_MIE);
|
||||
r.mtvec = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MTVEC).physIndex);
|
||||
r.mcounteren = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MCOUNTEREN).physIndex);
|
||||
r.mscratch = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MSCRATCH).physIndex);
|
||||
r.mepc = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MEPC).physIndex);
|
||||
r.mcause = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MCAUSE).physIndex);
|
||||
r.mtval = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MTVAL).physIndex);
|
||||
r.mip = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIP).physIndex) & CSRMasks.at(CSR_MIP);
|
||||
|
||||
// H mode CSR (to be implemented)
|
||||
}
|
||||
|
||||
void
|
||||
RemoteGDB::RiscvGdbRegCache::setRegs(ThreadContext *context) const
|
||||
{
|
||||
// NOTE: no error will be reported for attempting to set masked bits.
|
||||
RegVal oldVal;
|
||||
int mask;
|
||||
RegVal newVal;
|
||||
|
||||
DPRINTF(GDBAcc, "setregs in remotegdb \n");
|
||||
for (int i = 0; i < NumIntArchRegs; i++)
|
||||
context->setIntReg(i, r.gpr[i]);
|
||||
context->pcState(r.pc);
|
||||
|
||||
// Floating point registers
|
||||
for (int i = 0; i < NumFloatRegs; i++)
|
||||
context->setFloatReg(i, r.fpu[i]);
|
||||
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_FFLAGS).physIndex);
|
||||
mask = CSRMasks.at(CSR_FFLAGS);
|
||||
newVal = (oldVal & ~mask) | (r.fflags & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_FFLAGS).physIndex, newVal);
|
||||
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_FRM).physIndex);
|
||||
mask = CSRMasks.at(CSR_FRM);
|
||||
newVal = (oldVal & ~mask) | (r.frm & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_FRM).physIndex, newVal);
|
||||
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_FCSR).physIndex);
|
||||
mask = CSRMasks.at(CSR_FCSR);
|
||||
newVal = (oldVal & ~mask) | (r.fcsr & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_FCSR).physIndex, newVal);
|
||||
|
||||
// CSR registers
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_CYCLE).physIndex, r.cycle);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_TIME).physIndex, r.time);
|
||||
|
||||
// U mode CSR
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_USTATUS).physIndex);
|
||||
mask = CSRMasks.at(CSR_USTATUS);
|
||||
newVal = (oldVal & ~mask) | (r.ustatus & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_USTATUS).physIndex, newVal);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UIE).physIndex);
|
||||
mask = CSRMasks.at(CSR_UIE);
|
||||
newVal = (oldVal & ~mask) | (r.uie & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_UIE).physIndex, newVal);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_UTVEC).physIndex, r.utvec);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_USCRATCH).physIndex, r.uscratch);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_UEPC).physIndex, r.uepc);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_UCAUSE).physIndex, r.ucause);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_UTVAL).physIndex, r.utval);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_UIP).physIndex);
|
||||
mask = CSRMasks.at(CSR_UIP);
|
||||
newVal = (oldVal & ~mask) | (r.uip & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_UIP).physIndex, newVal);
|
||||
|
||||
// S mode CSR
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SSTATUS).physIndex);
|
||||
mask = CSRMasks.at(CSR_SSTATUS);
|
||||
newVal = (oldVal & ~mask) | (r.sstatus & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SSTATUS).physIndex, newVal);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SEDELEG).physIndex, r.sedeleg);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIDELEG).physIndex, r.sideleg);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIE).physIndex);
|
||||
mask = CSRMasks.at(CSR_SIE);
|
||||
newVal = (oldVal & ~mask) | (r.sie & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIE).physIndex, newVal);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_STVEC).physIndex, r.stvec);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SCOUNTEREN).physIndex, r.scounteren);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SSCRATCH).physIndex, r.sscratch);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SEPC).physIndex, r.sepc);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SCAUSE).physIndex, r.scause);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_STVAL).physIndex, r.stval);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIP).physIndex);
|
||||
mask = CSRMasks.at(CSR_SIP);
|
||||
newVal = (oldVal & ~mask) | (r.sip & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SIP).physIndex, newVal);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_SATP).physIndex, r.satp);
|
||||
|
||||
// M mode CSR
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MVENDORID).physIndex, r.mvendorid);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MARCHID).physIndex, r.marchid);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIMPID).physIndex, r.mimpid);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MHARTID).physIndex, r.mhartid);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MSTATUS).physIndex);
|
||||
mask = CSRMasks.at(CSR_MSTATUS);
|
||||
newVal = (oldVal & ~mask) | (r.mstatus & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MSTATUS).physIndex, newVal);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MISA).physIndex);
|
||||
mask = CSRMasks.at(CSR_MISA);
|
||||
newVal = (oldVal & ~mask) | (r.misa & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MISA).physIndex, newVal);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MEDELEG).physIndex, r.medeleg);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIDELEG).physIndex, r.mideleg);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIE).physIndex);
|
||||
mask = CSRMasks.at(CSR_MIE);
|
||||
newVal = (oldVal & ~mask) | (r.mie & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIE).physIndex, newVal);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MTVEC).physIndex, r.mtvec);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MCOUNTEREN).physIndex, r.mcounteren);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MSCRATCH).physIndex, r.mscratch);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MEPC).physIndex, r.mepc);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MCAUSE).physIndex, r.mcause);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MTVAL).physIndex, r.mtval);
|
||||
oldVal = context->readMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIP).physIndex);
|
||||
mask = CSRMasks.at(CSR_MIP);
|
||||
newVal = (oldVal & ~mask) | (r.mip & mask);
|
||||
context->setMiscRegNoEffect(
|
||||
CSRData.at(CSR_MIP).physIndex, newVal);
|
||||
|
||||
// H mode CSR (to be implemented)
|
||||
}
|
||||
|
||||
BaseGdbRegCache*
|
||||
bool
|
||||
RemoteGDB::getXferFeaturesRead(const std::string &annex, std::string &output)
|
||||
{
|
||||
/**
|
||||
* Blobs e.g. gdb_xml_riscv_target are generated by adding
|
||||
* GdbXml(<xml_file_name>, <blob_name>) to src/arch/riscv/Sconscript.
|
||||
*
|
||||
* Import using #include blobs/<blob_name>.hh
|
||||
*/
|
||||
#define GDB_XML(x, s) \
|
||||
{ \
|
||||
x, std::string(reinterpret_cast<const char *>(Blobs::s), \
|
||||
Blobs::s##_len) \
|
||||
}
|
||||
static const std::map<std::string, std::string> annexMap{
|
||||
GDB_XML("target.xml", gdb_xml_riscv_target),
|
||||
GDB_XML("riscv-64bit-cpu.xml", gdb_xml_riscv_cpu),
|
||||
GDB_XML("riscv-64bit-fpu.xml", gdb_xml_riscv_fpu),
|
||||
GDB_XML("riscv-64bit-csr.xml", gdb_xml_riscv_csr)};
|
||||
#undef GDB_XML
|
||||
auto it = annexMap.find(annex);
|
||||
if (it == annexMap.end())
|
||||
return false;
|
||||
output = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
BaseGdbRegCache *
|
||||
RemoteGDB::gdbRegs()
|
||||
{
|
||||
return ®Cache;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei International
|
||||
* Copyright (c) 2017 The University of Virginia
|
||||
* Copyright 2015 LabWare
|
||||
* Copyright 2014 Google, Inc.
|
||||
@@ -57,9 +58,71 @@ class RemoteGDB : public BaseRemoteGDB
|
||||
{
|
||||
using BaseGdbRegCache::BaseGdbRegCache;
|
||||
private:
|
||||
/**
|
||||
* RISC-V Register Cache
|
||||
* Order and sizes of registers found in ext/gdb-xml/riscv.xml
|
||||
* To add support for more CSRs:
|
||||
* 1. Uncomment relevant lines in ext/gdb-xml/riscv-64bit-csr.xml
|
||||
* 2. Add register to struct below
|
||||
* 3. Modify RiscvGdbRegCache::getRegs and setRegs
|
||||
*/
|
||||
struct {
|
||||
uint64_t gpr[NumIntArchRegs];
|
||||
uint64_t pc;
|
||||
uint64_t fpu[NumFloatRegs];
|
||||
uint32_t fflags;
|
||||
uint32_t frm;
|
||||
uint32_t fcsr;
|
||||
// Placeholder for byte alignment
|
||||
uint32_t placeholder;
|
||||
uint64_t cycle;
|
||||
uint64_t time;
|
||||
uint64_t ustatus;
|
||||
uint64_t uie;
|
||||
uint64_t utvec;
|
||||
uint64_t uscratch;
|
||||
uint64_t uepc;
|
||||
uint64_t ucause;
|
||||
uint64_t utval;
|
||||
uint64_t uip;
|
||||
uint64_t sstatus;
|
||||
uint64_t sedeleg;
|
||||
uint64_t sideleg;
|
||||
uint64_t sie;
|
||||
uint64_t stvec;
|
||||
uint64_t scounteren;
|
||||
uint64_t sscratch;
|
||||
uint64_t sepc;
|
||||
uint64_t scause;
|
||||
uint64_t stval;
|
||||
uint64_t sip;
|
||||
uint64_t satp;
|
||||
uint64_t mvendorid;
|
||||
uint64_t marchid;
|
||||
uint64_t mimpid;
|
||||
uint64_t mhartid;
|
||||
uint64_t mstatus;
|
||||
uint64_t misa;
|
||||
uint64_t medeleg;
|
||||
uint64_t mideleg;
|
||||
uint64_t mie;
|
||||
uint64_t mtvec;
|
||||
uint64_t mcounteren;
|
||||
uint64_t mscratch;
|
||||
uint64_t mepc;
|
||||
uint64_t mcause;
|
||||
uint64_t mtval;
|
||||
uint64_t mip;
|
||||
uint64_t hstatus;
|
||||
uint64_t hedeleg;
|
||||
uint64_t hideleg;
|
||||
uint64_t hie;
|
||||
uint64_t htvec;
|
||||
uint64_t hscratch;
|
||||
uint64_t hepc;
|
||||
uint64_t hcause;
|
||||
uint64_t hbadaddr;
|
||||
uint64_t hip;
|
||||
} r;
|
||||
public:
|
||||
char *data() const { return (char *)&r; }
|
||||
@@ -79,6 +142,19 @@ class RemoteGDB : public BaseRemoteGDB
|
||||
public:
|
||||
RemoteGDB(System *_system, ThreadContext *tc, int _port);
|
||||
BaseGdbRegCache *gdbRegs() override;
|
||||
/**
|
||||
* Informs GDB remote serial protocol that XML features are supported
|
||||
* GDB then queries for xml blobs using qXfer:features:read:xxx.xml
|
||||
*/
|
||||
std::vector<std::string>
|
||||
availableFeatures() const
|
||||
{
|
||||
return {"qXfer:features:read+"};
|
||||
};
|
||||
/**
|
||||
* Reply to qXfer:features:read:xxx.xml qeuries
|
||||
*/
|
||||
bool getXferFeaturesRead(const std::string &annex, std::string &output);
|
||||
};
|
||||
|
||||
} // namespace RiscvISA
|
||||
|
||||
Reference in New Issue
Block a user