diff --git a/ext/gdb-xml/riscv-64bit-cpu.xml b/ext/gdb-xml/riscv-64bit-cpu.xml
new file mode 100644
index 0000000000..ca59ac307d
--- /dev/null
+++ b/ext/gdb-xml/riscv-64bit-cpu.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ext/gdb-xml/riscv-64bit-csr.xml b/ext/gdb-xml/riscv-64bit-csr.xml
new file mode 100644
index 0000000000..6b2ae790fe
--- /dev/null
+++ b/ext/gdb-xml/riscv-64bit-csr.xml
@@ -0,0 +1,248 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ext/gdb-xml/riscv-64bit-fpu.xml b/ext/gdb-xml/riscv-64bit-fpu.xml
new file mode 100644
index 0000000000..7b68ba4d60
--- /dev/null
+++ b/ext/gdb-xml/riscv-64bit-fpu.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ext/gdb-xml/riscv.xml b/ext/gdb-xml/riscv.xml
new file mode 100644
index 0000000000..cae8bf7abc
--- /dev/null
+++ b/ext/gdb-xml/riscv.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ riscv
+
+
+
+
\ No newline at end of file
diff --git a/src/arch/riscv/SConscript b/src/arch/riscv/SConscript
index 3913be9d14..0179fbcd41 100644
--- a/src/arch/riscv/SConscript
+++ b/src/arch/riscv/SConscript
@@ -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')
diff --git a/src/arch/riscv/remote_gdb.cc b/src/arch/riscv/remote_gdb.cc
index 0e4c544ba2..75f1820e4c 100644
--- a/src/arch/riscv/remote_gdb.cc
+++ b/src/arch/riscv/remote_gdb.cc
@@ -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(, ) to src/arch/riscv/Sconscript.
+ *
+ * Import using #include blobs/.hh
+ */
+#define GDB_XML(x, s) \
+ { \
+ x, std::string(reinterpret_cast(Blobs::s), \
+ Blobs::s##_len) \
+ }
+ static const std::map 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;
diff --git a/src/arch/riscv/remote_gdb.hh b/src/arch/riscv/remote_gdb.hh
index a9d3b0c5cc..545a43c4ab 100644
--- a/src/arch/riscv/remote_gdb.hh
+++ b/src/arch/riscv/remote_gdb.hh
@@ -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
+ 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