diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/alpha/isa/decoder.isa | 2 | ||||
-rw-r--r-- | src/arch/mips/isa/decoder.isa | 3 | ||||
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 4 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/two_byte_opcodes.isa | 2 | ||||
-rw-r--r-- | src/arch/x86/isa/decoder/x87.isa | 4 | ||||
-rw-r--r-- | src/arch/x86/process.cc | 5 | ||||
-rw-r--r-- | src/cpu/base_dyn_inst.hh | 1 | ||||
-rw-r--r-- | src/cpu/nativetrace.cc | 173 | ||||
-rw-r--r-- | src/cpu/nativetrace.hh | 111 | ||||
-rw-r--r-- | src/cpu/static_inst.hh | 4 |
10 files changed, 206 insertions, 103 deletions
diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index af1a91a62..2177e8c4f 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -714,7 +714,7 @@ decode OPCODE default Unknown::unknown() { }}, IsNonSpeculative); 0x83: callsys({{ xc->syscall(R0); - }}, IsSerializeAfter, IsNonSpeculative); + }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); // Read uniq reg into ABI return value register (r0) 0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess); // Write uniq reg with value from ABI arg register (r16) diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa index e55d2e070..40ea223f6 100644 --- a/src/arch/mips/isa/decoder.isa +++ b/src/arch/mips/isa/decoder.isa @@ -134,7 +134,8 @@ decode OPCODE_HI default Unknown::unknown() { 0x2: movz({{ Rd = (Rt == 0) ? Rs : Rd; }}); 0x3: movn({{ Rd = (Rt != 0) ? Rs : Rd; }}); 0x4: syscall({{ xc->syscall(R2); }}, - IsSerializeAfter, IsNonSpeculative); + IsSerializeAfter, IsNonSpeculative, + IsSyscall); 0x7: sync({{ ; }}, IsMemBarrier); } diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 68b2183ad..14c652606 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -1230,7 +1230,7 @@ decode OP default Unknown::unknown() DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); fault = new TrapInstruction(lTrapNum); } - }}, IsSerializeAfter, IsNonSpeculative); + }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); 0x2: Trap::tccx({{ if(passesCondition(Ccr<7:4>, COND2)) { @@ -1238,7 +1238,7 @@ decode OP default Unknown::unknown() DPRINTF(Sparc, "The trap number is %d\n", lTrapNum); fault = new TrapInstruction(lTrapNum); } - }}, IsSerializeAfter, IsNonSpeculative); + }}, IsSerializeAfter, IsNonSpeculative, IsSyscall); } 0x3B: Nop::flush({{/*Instruction memory flush*/}}, IsWriteBarrier, MemWriteOp); diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index a8c4e7062..e8307c6e6 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -70,7 +70,7 @@ #if FULL_SYSTEM 0x05: syscall(); #else - 0x05: SyscallInst::syscall('xc->syscall(rax)'); + 0x05: SyscallInst::syscall('xc->syscall(rax)', IsSyscall); #endif 0x06: clts(); //sandpile.org says (AMD) after sysret, so I might want to check diff --git a/src/arch/x86/isa/decoder/x87.isa b/src/arch/x86/isa/decoder/x87.isa index f16647fe5..bab687acd 100644 --- a/src/arch/x86/isa/decoder/x87.isa +++ b/src/arch/x86/isa/decoder/x87.isa @@ -103,7 +103,7 @@ 0x5: fldln2(); 0x6: fldz(); } - default: fldcw(); + default: fldcw_Mw(); } 0x6: decode MODRM_MOD { 0x3: decode MODRM_RM { @@ -129,7 +129,7 @@ 0x6: fsin(); 0x7: fcos(); } - default: fnstcw(); + default: fnstcw_Mw(); } } //0x2: esc2(); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 036805612..17904cb33 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -412,11 +412,6 @@ X86LiveProcess::argsInit(int intSize, int pageSize) initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); - //Set up the thread context to start running the process - //Because of the peculiarities of how syscall works, I believe - //a process starts with r11 containing the value of eflags or maybe r11 - //from before the call to execve. Empirically this value is 0x200. - threadContexts[0]->setIntReg(INTREG_R11, 0x200); //Set the stack pointer register threadContexts[0]->setIntReg(StackPointerReg, stack_min); diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index a55c1e3c0..362babeff 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -498,6 +498,7 @@ class BaseDynInst : public FastAlloc, public RefCounted bool isQuiesce() const { return staticInst->isQuiesce(); } bool isIprAccess() const { return staticInst->isIprAccess(); } bool isUnverifiable() const { return staticInst->isUnverifiable(); } + bool isSyscall() const { return staticInst->isSyscall(); } bool isMacroop() const { return staticInst->isMacroop(); } bool isMicroop() const { return staticInst->isMicroop(); } bool isDelayedCommit() const { return staticInst->isDelayedCommit(); } diff --git a/src/cpu/nativetrace.cc b/src/cpu/nativetrace.cc index 90a0e1a62..fe524e245 100644 --- a/src/cpu/nativetrace.cc +++ b/src/cpu/nativetrace.cc @@ -60,119 +60,122 @@ NativeTrace::NativeTrace(const std::string & _name) : InstTracer(_name) } ccprintf(cerr, "Listening for native process on port %d\n", port); fd = native_listener.accept(); + checkRcx = true; + checkR11 = true; } bool -NativeTraceRecord::checkIntReg(const char * regName, int index, int size) +NativeTrace::checkRcxReg(const char * name, uint64_t &mVal, uint64_t &nVal) { - uint64_t regVal; - int res = read(parent->fd, ®Val, size); - if(res < 0) - panic("Read call failed! %s\n", strerror(errno)); - regVal = TheISA::gtoh(regVal); - uint64_t realRegVal = thread->readIntReg(index); - if(regVal != realRegVal) - { - DPRINTFN("Register %s should be %#x but is %#x.\n", - regName, regVal, realRegVal); - return false; - } + if(!checkRcx) + checkRcx = (mVal != oldRcxVal || nVal != oldRealRcxVal); + if(checkRcx) + return checkReg(name, mVal, nVal); return true; } -bool NativeTraceRecord::checkPC(const char * regName, int size) +bool +NativeTrace::checkR11Reg(const char * name, uint64_t &mVal, uint64_t &nVal) { - uint64_t regVal; - int res = read(parent->fd, ®Val, size); - if(res < 0) - panic("Read call failed! %s\n", strerror(errno)); - regVal = TheISA::gtoh(regVal); - uint64_t realRegVal = thread->readNextPC(); - if(regVal != realRegVal) - { - DPRINTFN("%s should be %#x but is %#x.\n", - regName, regVal, realRegVal); - return false; - } + if(!checkR11) + checkR11 = (mVal != oldR11Val || nVal != oldRealR11Val); + if(checkR11) + return checkReg(name, mVal, nVal); return true; } void Trace::NativeTraceRecord::dump() { -// ostream &outs = Trace::output(); - //Don't print what happens for each micro-op, just print out //once at the last op, and for regular instructions. if(!staticInst->isMicroop() || staticInst->isLastMicroop()) + parent->check(thread, staticInst->isSyscall()); +} + +void +Trace::NativeTrace::check(ThreadContext * tc, bool isSyscall) +{ +// ostream &outs = Trace::output(); + nState.update(fd); + mState.update(tc); + + if(isSyscall) { - checkIntReg("rax", INTREG_RAX, sizeof(uint64_t)); - checkIntReg("rcx", INTREG_RCX, sizeof(uint64_t)); - checkIntReg("rdx", INTREG_RDX, sizeof(uint64_t)); - checkIntReg("rbx", INTREG_RBX, sizeof(uint64_t)); - checkIntReg("rsp", INTREG_RSP, sizeof(uint64_t)); - checkIntReg("rbp", INTREG_RBP, sizeof(uint64_t)); - checkIntReg("rsi", INTREG_RSI, sizeof(uint64_t)); - checkIntReg("rdi", INTREG_RDI, sizeof(uint64_t)); - checkIntReg("r8", INTREG_R8, sizeof(uint64_t)); - checkIntReg("r9", INTREG_R9, sizeof(uint64_t)); - checkIntReg("r10", INTREG_R10, sizeof(uint64_t)); - checkIntReg("r11", INTREG_R11, sizeof(uint64_t)); - checkIntReg("r12", INTREG_R12, sizeof(uint64_t)); - checkIntReg("r13", INTREG_R13, sizeof(uint64_t)); - checkIntReg("r14", INTREG_R14, sizeof(uint64_t)); - checkIntReg("r15", INTREG_R15, sizeof(uint64_t)); - checkPC("rip", sizeof(uint64_t)); + checkRcx = false; + checkR11 = false; + oldRcxVal = mState.rcx; + oldRealRcxVal = nState.rcx; + oldR11Val = mState.r11; + oldRealR11Val = nState.r11; + } + + checkReg("rax", mState.rax, nState.rax); + checkRcxReg("rcx", mState.rcx, nState.rcx); + checkReg("rdx", mState.rdx, nState.rdx); + checkReg("rbx", mState.rbx, nState.rbx); + checkReg("rsp", mState.rsp, nState.rsp); + checkReg("rbp", mState.rbp, nState.rbp); + checkReg("rsi", mState.rsi, nState.rsi); + checkReg("rdi", mState.rdi, nState.rdi); + checkReg("r8", mState.r8, nState.r8); + checkReg("r9", mState.r9, nState.r9); + checkReg("r10", mState.r10, nState.r10); + checkR11Reg("r11", mState.r11, nState.r11); + checkReg("r12", mState.r12, nState.r12); + checkReg("r13", mState.r13, nState.r13); + checkReg("r14", mState.r14, nState.r14); + checkReg("r15", mState.r15, nState.r15); + checkReg("rip", mState.rip, nState.rip); #if THE_ISA == SPARC_ISA - /*for(int f = 0; f <= 62; f+=2) - { - uint64_t regVal; - int res = read(fd, ®Val, sizeof(regVal)); - if(res < 0) - panic("First read call failed! %s\n", strerror(errno)); - regVal = TheISA::gtoh(regVal); - uint64_t realRegVal = thread->readFloatRegBits(f, 64); - if(regVal != realRegVal) - { - DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal); - } - }*/ + /*for(int f = 0; f <= 62; f+=2) + { uint64_t regVal; int res = read(fd, ®Val, sizeof(regVal)); if(res < 0) panic("First read call failed! %s\n", strerror(errno)); regVal = TheISA::gtoh(regVal); - uint64_t realRegVal = thread->readNextPC(); - if(regVal != realRegVal) - { - DPRINTF(ExecRegDelta, - "Register pc should be %#x but is %#x.\n", - regVal, realRegVal); - } - res = read(fd, ®Val, sizeof(regVal)); - if(res < 0) - panic("First read call failed! %s\n", strerror(errno)); - regVal = TheISA::gtoh(regVal); - realRegVal = thread->readNextNPC(); + uint64_t realRegVal = thread->readFloatRegBits(f, 64); if(regVal != realRegVal) { - DPRINTF(ExecRegDelta, - "Register npc should be %#x but is %#x.\n", - regVal, realRegVal); - } - res = read(fd, ®Val, sizeof(regVal)); - if(res < 0) - panic("First read call failed! %s\n", strerror(errno)); - regVal = TheISA::gtoh(regVal); - realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); - if((regVal & 0xF) != (realRegVal & 0xF)) - { - DPRINTF(ExecRegDelta, - "Register ccr should be %#x but is %#x.\n", - regVal, realRegVal); + DPRINTF(ExecRegDelta, "Register f%d should be %#x but is %#x.\n", f, regVal, realRegVal); } -#endif + }*/ + uint64_t regVal; + int res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + uint64_t realRegVal = thread->readNextPC(); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, + "Register pc should be %#x but is %#x.\n", + regVal, realRegVal); } + res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + realRegVal = thread->readNextNPC(); + if(regVal != realRegVal) + { + DPRINTF(ExecRegDelta, + "Register npc should be %#x but is %#x.\n", + regVal, realRegVal); + } + res = read(fd, ®Val, sizeof(regVal)); + if(res < 0) + panic("First read call failed! %s\n", strerror(errno)); + regVal = TheISA::gtoh(regVal); + realRegVal = thread->readIntReg(SparcISA::NumIntArchRegs + 2); + if((regVal & 0xF) != (realRegVal & 0xF)) + { + DPRINTF(ExecRegDelta, + "Register ccr should be %#x but is %#x.\n", + regVal, realRegVal); + } +#endif } /* namespace Trace */ } diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh index 48395792d..126077581 100644 --- a/src/cpu/nativetrace.hh +++ b/src/cpu/nativetrace.hh @@ -36,6 +36,7 @@ #include "cpu/static_inst.hh" #include "sim/host.hh" #include "sim/insttracer.hh" +#include "arch/x86/intregs.hh" class ThreadContext; @@ -49,12 +50,6 @@ class NativeTraceRecord : public InstRecord protected: NativeTrace * parent; - bool - checkIntReg(const char * regName, int index, int size); - - bool - checkPC(const char * regName, int size); - public: NativeTraceRecord(NativeTrace * _parent, Tick _when, ThreadContext *_thread, @@ -73,8 +68,109 @@ class NativeTrace : public InstTracer ListenSocket native_listener; + bool checkRcx; + bool checkR11; + uint64_t oldRcxVal, oldR11Val; + uint64_t oldRealRcxVal, oldRealR11Val; + + struct ThreadState { + uint64_t rax; + uint64_t rcx; + uint64_t rdx; + uint64_t rbx; + uint64_t rsp; + uint64_t rbp; + uint64_t rsi; + uint64_t rdi; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + + void update(int fd) + { + int bytesLeft = sizeof(ThreadState); + int bytesRead = 0; + do + { + int res = read(fd, ((char *)this) + bytesRead, bytesLeft); + if(res < 0) + panic("Read call failed! %s\n", strerror(errno)); + bytesLeft -= res; + bytesRead += res; + } while(bytesLeft); + rax = TheISA::gtoh(rax); + rcx = TheISA::gtoh(rcx); + rdx = TheISA::gtoh(rdx); + rbx = TheISA::gtoh(rbx); + rsp = TheISA::gtoh(rsp); + rbp = TheISA::gtoh(rbp); + rsi = TheISA::gtoh(rsi); + rdi = TheISA::gtoh(rdi); + r8 = TheISA::gtoh(r8); + r9 = TheISA::gtoh(r9); + r10 = TheISA::gtoh(r10); + r11 = TheISA::gtoh(r11); + r12 = TheISA::gtoh(r12); + r13 = TheISA::gtoh(r13); + r14 = TheISA::gtoh(r14); + r15 = TheISA::gtoh(r15); + rip = TheISA::gtoh(rip); + } + + void update(ThreadContext * tc) + { + rax = tc->readIntReg(X86ISA::INTREG_RAX); + rcx = tc->readIntReg(X86ISA::INTREG_RCX); + rdx = tc->readIntReg(X86ISA::INTREG_RDX); + rbx = tc->readIntReg(X86ISA::INTREG_RBX); + rsp = tc->readIntReg(X86ISA::INTREG_RSP); + rbp = tc->readIntReg(X86ISA::INTREG_RBP); + rsi = tc->readIntReg(X86ISA::INTREG_RSI); + rdi = tc->readIntReg(X86ISA::INTREG_RDI); + r8 = tc->readIntReg(X86ISA::INTREG_R8); + r9 = tc->readIntReg(X86ISA::INTREG_R9); + r10 = tc->readIntReg(X86ISA::INTREG_R10); + r11 = tc->readIntReg(X86ISA::INTREG_R11); + r12 = tc->readIntReg(X86ISA::INTREG_R12); + r13 = tc->readIntReg(X86ISA::INTREG_R13); + r14 = tc->readIntReg(X86ISA::INTREG_R14); + r15 = tc->readIntReg(X86ISA::INTREG_R15); + rip = tc->readNextPC(); + } + + }; + + ThreadState nState; + ThreadState mState; + + public: + template<class T> + bool + checkReg(const char * regName, T &val, T &realVal) + { + if(val != realVal) + { + DPRINTFN("Register %s should be %#x but is %#x.\n", + regName, realVal, val); + return false; + } + return true; + } + + bool + checkRcxReg(const char * regName, uint64_t &, uint64_t &); + + bool + checkR11Reg(const char * regName, uint64_t &, uint64_t &); + NativeTrace(const std::string & name); NativeTraceRecord * @@ -88,6 +184,9 @@ class NativeTrace : public InstTracer staticInst, pc, tc->misspeculating()); } + void + check(ThreadContext *, bool syscall); + friend class NativeTraceRecord; }; diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index b0a19c151..f32b61ee5 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -143,6 +143,9 @@ class StaticInstBase : public RefCounted IsIprAccess, ///< Accesses IPRs IsUnverifiable, ///< Can't be verified by a checker + IsSyscall, ///< Causes a system call to be emulated in syscall + /// emulation mode. + //Flags for microcode IsMacroop, ///< Is a macroop containing microops IsMicroop, ///< Is a microop @@ -243,6 +246,7 @@ class StaticInstBase : public RefCounted bool isQuiesce() const { return flags[IsQuiesce]; } bool isIprAccess() const { return flags[IsIprAccess]; } bool isUnverifiable() const { return flags[IsUnverifiable]; } + bool isSyscall() const { return flags[IsSyscall]; } bool isMacroop() const { return flags[IsMacroop]; } bool isMicroop() const { return flags[IsMicroop]; } bool isDelayedCommit() const { return flags[IsDelayedCommit]; } |