From 2848ef669632c6d8a8863aac8a5d7ee575c3fd1a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 4 Oct 2007 12:24:16 -0700 Subject: [PATCH] SPARC: Make software trap 3 flush the register windows like the ABI specifies. --HG-- extra : convert_revision : 8ff43617b56dcca5783d6cc490f87140fc20a36d --- src/arch/sparc/process.cc | 103 +++++++++++++++++++++++++++++- src/arch/sparc/process.hh | 3 + src/arch/sparc/solaris/process.cc | 2 +- src/arch/sparc/solaris/process.hh | 4 +- 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 29b1a244b..91564e754 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -73,8 +73,39 @@ void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc) { switch(trapNum) { + case 0x01: //Software breakpoint + warn("Software breakpoint encountered at pc %#x.\n", tc->readPC()); + break; + case 0x02: //Division by zero + warn("Software signaled a division by zero at pc %#x.\n", + tc->readPC()); + break; case 0x03: //Flush window trap - warn("Ignoring request to flush register windows.\n"); + flushWindows(tc); + break; + case 0x04: //Clean windows + warn("Ignoring process request for clean register " + "windows at pc %#x.\n", tc->readPC()); + break; + case 0x05: //Range check + warn("Software signaled a range check at pc %#x.\n", + tc->readPC()); + break; + case 0x06: //Fix alignment + warn("Ignoring process request for os assisted unaligned accesses " + "at pc %#x.\n", tc->readPC()); + break; + case 0x07: //Integer overflow + warn("Software signaled an integer overflow at pc %#x.\n", + tc->readPC()); + break; + case 0x32: //Get integer condition codes + warn("Ignoring process request to get the integer condition codes " + "at pc %#x.\n", tc->readPC()); + break; + case 0x33: //Set integer condition codes + warn("Ignoring process request to set the integer condition codes " + "at pc %#x.\n", tc->readPC()); break; default: panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum); @@ -636,3 +667,73 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize) // num_processes++; } + +void Sparc32LiveProcess::flushWindows(ThreadContext *tc) +{ + IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3); + IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4); + IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6); + MiscReg CWP = tc->readMiscReg(MISCREG_CWP); + MiscReg origCWP = CWP; + CWP = (CWP + Cansave + 2) % NWindows; + while(NWindows - 2 - Cansave != 0) + { + if (Otherwin) { + panic("Otherwin non-zero.\n"); + } else { + tc->setMiscReg(MISCREG_CWP, CWP); + //Do the stores + IntReg sp = tc->readIntReg(StackPointerReg); + for (int index = 16; index < 32; index++) { + IntReg regVal = tc->readIntReg(index); + regVal = htog(regVal); + if (!tc->getMemPort()->tryWriteBlob( + sp + (index - 16) * 4, (uint8_t *)®Val, 4)) { + warn("Failed to save register to the stack when " + "flushing windows.\n"); + } + } + Canrestore--; + Cansave++; + CWP = (CWP + 1) % NWindows; + } + } + tc->setIntReg(NumIntArchRegs + 3, Cansave); + tc->setIntReg(NumIntArchRegs + 4, Canrestore); + tc->setMiscReg(MISCREG_CWP, origCWP); +} + +void Sparc64LiveProcess::flushWindows(ThreadContext *tc) +{ + IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3); + IntReg Canrestore = tc->readIntReg(NumIntArchRegs + 4); + IntReg Otherwin = tc->readIntReg(NumIntArchRegs + 6); + MiscReg CWP = tc->readMiscReg(MISCREG_CWP); + MiscReg origCWP = CWP; + CWP = (CWP + Cansave + 2) % NWindows; + while(NWindows - 2 - Cansave != 0) + { + if (Otherwin) { + panic("Otherwin non-zero.\n"); + } else { + tc->setMiscReg(MISCREG_CWP, CWP); + //Do the stores + IntReg sp = tc->readIntReg(StackPointerReg); + for (int index = 16; index < 32; index++) { + IntReg regVal = tc->readIntReg(index); + regVal = htog(regVal); + if (!tc->getMemPort()->tryWriteBlob( + sp + 2047 + (index - 16) * 8, (uint8_t *)®Val, 8)) { + warn("Failed to save register to the stack when " + "flushing windows.\n"); + } + } + Canrestore--; + Cansave++; + CWP = (CWP + 1) % NWindows; + } + } + tc->setIntReg(NumIntArchRegs + 3, Cansave); + tc->setIntReg(NumIntArchRegs + 4, Canrestore); + tc->setMiscReg(MISCREG_CWP, origCWP); +} diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index 2512441c6..f4e823a9a 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -66,6 +66,7 @@ class SparcLiveProcess : public LiveProcess Addr readSpillStart() { return spillStart; } + virtual void flushWindows(ThreadContext *tc) = 0; }; struct M5_32_auxv_t @@ -116,6 +117,7 @@ class Sparc32LiveProcess : public SparcLiveProcess void argsInit(int intSize, int pageSize); + void flushWindows(ThreadContext *tc); }; struct M5_64_auxv_t @@ -169,6 +171,7 @@ class Sparc64LiveProcess : public SparcLiveProcess void argsInit(int intSize, int pageSize); + void flushWindows(ThreadContext *tc); }; #endif // __SPARC_PROCESS_HH__ diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index f9876bf00..b7a49ab8d 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -336,7 +336,7 @@ SparcSolarisProcess::SparcSolarisProcess(const std::string &name, uint64_t _egid, uint64_t _pid, uint64_t _ppid) - : SparcLiveProcess(name, objFile, system, + : Sparc64LiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd, argv, envp, cwd, _uid, _euid, _gid, _egid, _pid, _ppid), Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) diff --git a/src/arch/sparc/solaris/process.hh b/src/arch/sparc/solaris/process.hh index f65a60656..174eaecd7 100644 --- a/src/arch/sparc/solaris/process.hh +++ b/src/arch/sparc/solaris/process.hh @@ -38,7 +38,7 @@ namespace SparcISA { /// A process with emulated SPARC/Solaris syscalls. -class SparcSolarisProcess : public SparcLiveProcess +class SparcSolarisProcess : public Sparc64LiveProcess { public: /// Constructor. @@ -66,4 +66,4 @@ class SparcSolarisProcess : public SparcLiveProcess } // namespace SparcISA -#endif // __ALPHA_SOLARIS_PROCESS_HH__ +#endif // __SPARC_SOLARIS_PROCESS_HH__