diff --git a/ext/gdb-xml/power-core.xml b/ext/gdb-xml/power-core.xml new file mode 100644 index 0000000000..6cf57b1379 --- /dev/null +++ b/ext/gdb-xml/power-core.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/gdb-xml/power-fpu.xml b/ext/gdb-xml/power-fpu.xml new file mode 100644 index 0000000000..145eede7fc --- /dev/null +++ b/ext/gdb-xml/power-fpu.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/gdb-xml/power.xml b/ext/gdb-xml/power.xml deleted file mode 100644 index da5a07ca91..0000000000 --- a/ext/gdb-xml/power.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - powerpc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ext/gdb-xml/power64-core.xml b/ext/gdb-xml/power64-core.xml new file mode 100644 index 0000000000..cd5bc6d0ea --- /dev/null +++ b/ext/gdb-xml/power64-core.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/gdb-xml/powerpc-32.xml b/ext/gdb-xml/powerpc-32.xml new file mode 100644 index 0000000000..a537f927d6 --- /dev/null +++ b/ext/gdb-xml/powerpc-32.xml @@ -0,0 +1,16 @@ + + + + + + + + powerpc:common + + + diff --git a/ext/gdb-xml/powerpc-64.xml b/ext/gdb-xml/powerpc-64.xml new file mode 100644 index 0000000000..a762f8cc25 --- /dev/null +++ b/ext/gdb-xml/powerpc-64.xml @@ -0,0 +1,16 @@ + + + + + + + + powerpc:common64 + + + diff --git a/src/arch/power/SConscript b/src/arch/power/SConscript index 24bf5dbbbd..720455c588 100644 --- a/src/arch/power/SConscript +++ b/src/arch/power/SConscript @@ -59,4 +59,8 @@ if env['TARGET_ISA'] == 'power': ISADesc('isa/main.isa') - GdbXml('power.xml', 'gdb_xml_power') + GdbXml('power-core.xml', 'gdb_xml_power_core') + GdbXml('power64-core.xml', 'gdb_xml_power64_core') + GdbXml('power-fpu.xml', 'gdb_xml_power_fpu') + GdbXml('powerpc-32.xml', 'gdb_xml_powerpc_32') + GdbXml('powerpc-64.xml', 'gdb_xml_powerpc_64') diff --git a/src/arch/power/remote_gdb.cc b/src/arch/power/remote_gdb.cc index 886a8402a3..5536879a6b 100644 --- a/src/arch/power/remote_gdb.cc +++ b/src/arch/power/remote_gdb.cc @@ -136,7 +136,12 @@ #include -#include "blobs/gdb_xml_power.hh" +#include "arch/power/regs/misc.hh" +#include "blobs/gdb_xml_power64_core.hh" +#include "blobs/gdb_xml_power_core.hh" +#include "blobs/gdb_xml_power_fpu.hh" +#include "blobs/gdb_xml_powerpc_32.hh" +#include "blobs/gdb_xml_powerpc_64.hh" #include "cpu/thread_state.hh" #include "debug/GDBAcc.hh" #include "debug/GDBMisc.hh" @@ -149,7 +154,7 @@ namespace gem5 using namespace PowerISA; RemoteGDB::RemoteGDB(System *_system, int _port) - : BaseRemoteGDB(_system, _port), regCache(this) + : BaseRemoteGDB(_system, _port), regCache32(this), regCache64(this) { } @@ -173,22 +178,26 @@ RemoteGDB::PowerGdbRegCache::getRegs(ThreadContext *context) { DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + Msr msr = context->readIntReg(INTREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + // Default order on 32-bit PowerPC: // R0-R31 (32-bit each), F0-F31 (64-bit IEEE754 double), - // PC, MSR, CR, LR, CTR, XER (32-bit each) + // PC, MSR, CR, LR, CTR, XER, FPSCR (32-bit each) for (int i = 0; i < NumIntArchRegs; i++) - r.gpr[i] = htobe((uint32_t)context->readIntReg(i)); + r.gpr[i] = htog((uint32_t)context->readIntReg(i), order); for (int i = 0; i < NumFloatArchRegs; i++) r.fpr[i] = context->readFloatReg(i); - r.pc = htobe((uint32_t)context->pcState().pc()); - r.msr = 0; // Is MSR modeled? - r.cr = htobe((uint32_t)context->readIntReg(INTREG_CR)); - r.lr = htobe((uint32_t)context->readIntReg(INTREG_LR)); - r.ctr = htobe((uint32_t)context->readIntReg(INTREG_CTR)); - r.xer = htobe((uint32_t)context->readIntReg(INTREG_XER)); + r.pc = htog((uint32_t)context->pcState().pc(), order); + r.msr = 0; // MSR is privileged, hence not exposed here + r.cr = htog((uint32_t)context->readIntReg(INTREG_CR), order); + r.lr = htog((uint32_t)context->readIntReg(INTREG_LR), order); + r.ctr = htog((uint32_t)context->readIntReg(INTREG_CTR), order); + r.xer = htog((uint32_t)context->readIntReg(INTREG_XER), order); + r.fpscr = htog((uint32_t)context->readIntReg(INTREG_FPSCR), order); } void @@ -196,24 +205,89 @@ RemoteGDB::PowerGdbRegCache::setRegs(ThreadContext *context) const { DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + Msr msr = context->readIntReg(INTREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + for (int i = 0; i < NumIntArchRegs; i++) - context->setIntReg(i, betoh(r.gpr[i])); + context->setIntReg(i, gtoh(r.gpr[i], order)); for (int i = 0; i < NumFloatArchRegs; i++) context->setFloatReg(i, r.fpr[i]); - context->pcState(betoh(r.pc)); - // Is MSR modeled? - context->setIntReg(INTREG_CR, betoh(r.cr)); - context->setIntReg(INTREG_LR, betoh(r.lr)); - context->setIntReg(INTREG_CTR, betoh(r.ctr)); - context->setIntReg(INTREG_XER, betoh(r.xer)); + auto pc = context->pcState(); + pc.byteOrder(order); + pc.set(gtoh(r.pc, order)); + context->pcState(pc); + // MSR is privileged, hence not modified here + context->setIntReg(INTREG_CR, gtoh(r.cr, order)); + context->setIntReg(INTREG_LR, gtoh(r.lr, order)); + context->setIntReg(INTREG_CTR, gtoh(r.ctr, order)); + context->setIntReg(INTREG_XER, gtoh(r.xer, order)); + context->setIntReg(INTREG_FPSCR, gtoh(r.fpscr, order)); +} + +void +RemoteGDB::Power64GdbRegCache::getRegs(ThreadContext *context) +{ + DPRINTF(GDBAcc, "getRegs in remotegdb \n"); + + Msr msr = context->readIntReg(INTREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + + // Default order on 64-bit PowerPC: + // GPRR0-GPRR31 (64-bit each), FPR0-FPR31 (64-bit IEEE754 double), + // CIA, MSR, CR, LR, CTR, XER, FPSCR (only CR, XER, FPSCR are 32-bit + // each and the rest are 64-bit) + + for (int i = 0; i < NumIntArchRegs; i++) + r.gpr[i] = htog(context->readIntReg(i), order); + + for (int i = 0; i < NumFloatArchRegs; i++) + r.fpr[i] = context->readFloatReg(i); + + r.pc = htog(context->pcState().pc(), order); + r.msr = 0; // MSR is privileged, hence not exposed here + r.cr = htog((uint32_t)context->readIntReg(INTREG_CR), order); + r.lr = htog(context->readIntReg(INTREG_LR), order); + r.ctr = htog(context->readIntReg(INTREG_CTR), order); + r.xer = htog((uint32_t)context->readIntReg(INTREG_XER), order); + r.fpscr = htog((uint32_t)context->readIntReg(INTREG_FPSCR), order); +} + +void +RemoteGDB::Power64GdbRegCache::setRegs(ThreadContext *context) const +{ + DPRINTF(GDBAcc, "setRegs in remotegdb \n"); + + Msr msr = context->readIntReg(INTREG_MSR); + ByteOrder order = (msr.le ? ByteOrder::little : ByteOrder::big); + + for (int i = 0; i < NumIntArchRegs; i++) + context->setIntReg(i, gtoh(r.gpr[i], order)); + + for (int i = 0; i < NumFloatArchRegs; i++) + context->setFloatReg(i, r.fpr[i]); + + auto pc = context->pcState(); + pc.byteOrder(order); + pc.set(gtoh(r.pc, order)); + context->pcState(pc); + // MSR is privileged, hence not modified here + context->setIntReg(INTREG_CR, gtoh(r.cr, order)); + context->setIntReg(INTREG_LR, gtoh(r.lr, order)); + context->setIntReg(INTREG_CTR, gtoh(r.ctr, order)); + context->setIntReg(INTREG_XER, gtoh(r.xer, order)); + context->setIntReg(INTREG_FPSCR, gtoh(r.fpscr, order)); } BaseGdbRegCache* RemoteGDB::gdbRegs() { - return ®Cache; + Msr msr = context()->readIntReg(INTREG_MSR); + if (msr.sf) + return ®Cache64; + else + return ®Cache32; } bool @@ -222,10 +296,20 @@ RemoteGDB::getXferFeaturesRead(const std::string &annex, std::string &output) #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_power), + static const std::map annexMap32{ + GDB_XML("target.xml", gdb_xml_powerpc_32), + GDB_XML("power-core.xml", gdb_xml_power_core), + GDB_XML("power-fpu.xml", gdb_xml_power_fpu) + }; + static const std::map annexMap64{ + GDB_XML("target.xml", gdb_xml_powerpc_64), + GDB_XML("power64-core.xml", gdb_xml_power64_core), + GDB_XML("power-fpu.xml", gdb_xml_power_fpu) }; #undef GDB_XML + + Msr msr = context()->readIntReg(INTREG_MSR); + auto& annexMap = msr.sf ? annexMap64 : annexMap32; auto it = annexMap.find(annex); if (it == annexMap.end()) return false; diff --git a/src/arch/power/remote_gdb.hh b/src/arch/power/remote_gdb.hh index fa21df5123..dc7ae65855 100644 --- a/src/arch/power/remote_gdb.hh +++ b/src/arch/power/remote_gdb.hh @@ -53,7 +53,7 @@ class RemoteGDB : public BaseRemoteGDB { using BaseGdbRegCache::BaseGdbRegCache; private: - struct + struct GEM5_PACKED { uint32_t gpr[NumIntArchRegs]; uint64_t fpr[NumFloatArchRegs]; @@ -63,7 +63,9 @@ class RemoteGDB : public BaseRemoteGDB uint32_t lr; uint32_t ctr; uint32_t xer; + uint32_t fpscr; } r; + public: char *data() const { return (char *)&r; } size_t size() const { return sizeof(r); } @@ -76,16 +78,48 @@ class RemoteGDB : public BaseRemoteGDB } }; - PowerGdbRegCache regCache; + class Power64GdbRegCache : public BaseGdbRegCache + { + using BaseGdbRegCache::BaseGdbRegCache; + private: + struct GEM5_PACKED + { + uint64_t gpr[NumIntArchRegs]; + uint64_t fpr[NumFloatArchRegs]; + uint64_t pc; + uint64_t msr; + uint32_t cr; + uint64_t lr; + uint64_t ctr; + uint32_t xer; + uint32_t fpscr; + } r; + + public: + char *data() const { return (char *)&r; } + size_t size() const { return sizeof(r); } + void getRegs(ThreadContext*); + void setRegs(ThreadContext*) const; + const std::string + name() const + { + return gdb->name() + ".Power64GdbRegCache"; + } + }; + + PowerGdbRegCache regCache32; + Power64GdbRegCache regCache64; public: RemoteGDB(System *_system, int _port); BaseGdbRegCache *gdbRegs(); + std::vector availableFeatures() const { return {"qXfer:features:read+"}; }; + bool getXferFeaturesRead(const std::string &annex, std::string &output); };