From b760b99f4d9f5469d88c67ae8a06e5f9543a43e7 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Mon, 20 Oct 2008 16:22:59 -0400 Subject: [PATCH] O3CPU: Undo Gabe's changes to remove hwrei and simpalcheck from O3 CPU. Removing hwrei causes the instruction after the hwrei to be fetched before the ITB/DTB_CM register is updated in a call pal call sys and thus the translation fails because the user is attempting to access a super page address. Minimally, it seems as though some sort of fetch stall or refetch after a hwrei is required. I think this works currently because the hwrei uses the exec context interface, and the o3 stalls when that occurs. Additionally, these changes don't update the LOCK register and probably break ll/sc. Both o3 changes were removed since a great deal of manual patching would be required to only remove the hwrei change. --- src/arch/alpha/ev5.cc | 50 ++++++++++++++++++++++++++++++++++ src/arch/alpha/isa/decoder.isa | 34 ++--------------------- src/arch/alpha/isa/main.isa | 3 -- src/arch/x86/bios/IntelMP.py | 9 ------ src/cpu/checker/cpu.hh | 2 ++ src/cpu/exec_context.hh | 12 +++++++- src/cpu/o3/cpu.cc | 45 ++++++++++++++++++++++++++++++ src/cpu/o3/cpu.hh | 5 ++++ src/cpu/o3/dyn_inst.hh | 3 ++ src/cpu/o3/dyn_inst_impl.hh | 32 ++++++++++++++++++++++ src/cpu/ozone/cpu.hh | 2 ++ src/cpu/ozone/cpu_impl.hh | 40 +++++++++++++++++++++++++++ src/cpu/ozone/dyn_inst.hh | 2 ++ src/cpu/ozone/dyn_inst_impl.hh | 22 +++++++++++++++ src/cpu/simple/base.hh | 2 ++ src/cpu/simple_thread.hh | 4 +++ 16 files changed, 222 insertions(+), 45 deletions(-) diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index c11b3632e..7dc02a611 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -547,3 +547,53 @@ copyIprs(ThreadContext *src, ThreadContext *dest) } } // namespace AlphaISA + +#if FULL_SYSTEM + +using namespace AlphaISA; + +Fault +SimpleThread::hwrei() +{ + if (!(readPC() & 0x3)) + return new UnimplementedOpcodeFault; + + setNextPC(readMiscRegNoEffect(IPR_EXC_ADDR)); + + if (!misspeculating()) { + if (kernelStats) + kernelStats->hwrei(); + } + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + +/** + * Check for special simulator handling of specific PAL calls. + * If return value is false, actual PAL call will be suppressed. + */ +bool +SimpleThread::simPalCheck(int palFunc) +{ + if (kernelStats) + kernelStats->callpal(palFunc, tc); + + switch (palFunc) { + case PAL::halt: + halt(); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (system->breakpoint()) + return false; + break; + } + + return true; +} + +#endif // FULL_SYSTEM diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa index 06676ae87..270940df2 100644 --- a/src/arch/alpha/isa/decoder.isa +++ b/src/arch/alpha/isa/decoder.isa @@ -698,28 +698,7 @@ decode OPCODE default Unknown::unknown() { else { // check to see if simulator wants to do something special // on this PAL call (including maybe suppress it) - - bool dopal = true; - - ThreadContext * tc = xc->tcBase(); - AlphaISA::Kernel::Statistics * kernelStats = tc->getKernelStats(); - System * system = tc->getSystemPtr(); - if (kernelStats) - kernelStats->callpal(palFunc, tc); - - switch (palFunc) { - case PAL::halt: - tc->halt(); - if (--System::numSystemsRunning == 0) - exitSimLoop("all cpus halted"); - break; - - case PAL::bpt: - case PAL::bugchk: - if (system->breakpoint()) - dopal = false; - break; - } + bool dopal = xc->simPalCheck(palFunc); if (dopal) { xc->setMiscReg(IPR_EXC_ADDR, NPC); @@ -807,16 +786,7 @@ decode OPCODE default Unknown::unknown() { format BasicOperate { 0x1e: decode PALMODE { 0: OpcdecFault::hw_rei(); - 1: hw_rei({{ - NPC = ExcAddr; - ThreadContext * tc = xc->tcBase(); - if (!tc->misspeculating()) { - AlphaISA::Kernel::Statistics * kernelStats = - tc->getKernelStats(); - if (kernelStats) - kernelStats->hwrei(); - } - }}, IsSerializing, IsSerializeBefore); + 1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore); } // M5 special opcodes use the reserved 0x01 opcode space diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa index 0f7f74359..5231712c8 100644 --- a/src/arch/alpha/isa/main.isa +++ b/src/arch/alpha/isa/main.isa @@ -69,8 +69,6 @@ output exec {{ #include #if FULL_SYSTEM -#include "arch/alpha/kernel_stats.hh" -#include "arch/alpha/osfpal.hh" #include "sim/pseudo_inst.hh" #endif #include "arch/alpha/ipr.hh" @@ -189,7 +187,6 @@ def operands {{ 'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1), 'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1), 'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', None, 1), - 'ExcAddr': ('ControlReg', 'uq', 'IPR_EXC_ADDR', None, 1), # The next two are hacks for non-full-system call-pal emulation 'R0': ('IntReg', 'uq', '0', None, 1), 'R16': ('IntReg', 'uq', '16', None, 1), diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py index 758932180..70e7963fa 100644 --- a/src/arch/x86/bios/IntelMP.py +++ b/src/arch/x86/bios/IntelMP.py @@ -86,15 +86,6 @@ class X86IntelMPConfigTable(SimObject): ext_entries = VectorParam.X86IntelMPExtConfigEntry([], 'extended configuration table entries') - def add_entry(self, entry): - if isinstance(entry, X86IntelMPBaseConfigEntry): - self.base_entries.append(entry) - elif isinstance(entry, X86IntelMPExtConfigEntry): - self.base_entries.append(entry) - else: - panic("Don't know what type of Intel MP entry %s is." \ - % entry.__class__.__name__) - class X86IntelMPBaseConfigEntry(SimObject): type = 'X86IntelMPBaseConfigEntry' cxx_class = 'X86ISA::IntelMP::BaseConfigEntry' diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 0f01f17c5..5b3c4582c 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -336,7 +336,9 @@ class CheckerCPU : public BaseCPU void translateDataReadReq(Request *req); #if FULL_SYSTEM + Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } + bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else // Assume that the normal CPU's call to syscall was successful. // The checker's state would have already been updated by the syscall. diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh index 836cf4352..2b9fe4bcf 100644 --- a/src/cpu/exec_context.hh +++ b/src/cpu/exec_context.hh @@ -143,7 +143,17 @@ class ExecContext { * given flags. */ void writeHint(Addr addr, int size, unsigned flags); -#if !FULL_SYSTEM +#if FULL_SYSTEM + /** Somewhat Alpha-specific function that handles returning from + * an error or interrupt. */ + Fault hwrei(); + + /** + * Check for special simulator handling of specific PAL calls. If + * return value is false, actual PAL call will be suppressed. + */ + bool simPalCheck(int palFunc); +#else /** Executes a syscall specified by the callnum. */ void syscall(int64_t callnum); #endif diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index c110bbd50..41b7e8b14 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -53,6 +53,10 @@ #include "cpu/checker/cpu.hh" #endif +#if THE_ISA == ALPHA_ISA +#include "arch/alpha/osfpal.hh" +#endif + class BaseCPUParams; using namespace TheISA; @@ -901,6 +905,47 @@ FullO3CPU::post_interrupt(int int_num, int index) } } +template +Fault +FullO3CPU::hwrei(unsigned tid) +{ +#if THE_ISA == ALPHA_ISA + // Need to clear the lock flag upon returning from an interrupt. + this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid); + + this->thread[tid]->kernelStats->hwrei(); + + // FIXME: XXX check for interrupts? XXX +#endif + return NoFault; +} + +template +bool +FullO3CPU::simPalCheck(int palFunc, unsigned tid) +{ +#if THE_ISA == ALPHA_ISA + if (this->thread[tid]->kernelStats) + this->thread[tid]->kernelStats->callpal(palFunc, + this->threadContexts[tid]); + + switch (palFunc) { + case PAL::halt: + halt(); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (this->system->breakpoint()) + return false; + break; + } +#endif + return true; +} + template Fault FullO3CPU::getInterrupts() diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 07ba8d701..406d965be 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -414,6 +414,11 @@ class FullO3CPU : public BaseO3CPU /** Posts an interrupt. */ void post_interrupt(int int_num, int index); + /** HW return from error interrupt. */ + Fault hwrei(unsigned tid); + + bool simPalCheck(int palFunc, unsigned tid); + /** Returns the Fault for any valid interrupt. */ Fault getInterrupts(); diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 28dd60f5f..292547b6b 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -168,8 +168,11 @@ class BaseO3DynInst : public BaseDynInst } #if FULL_SYSTEM + /** Calls hardware return from error interrupt. */ + Fault hwrei(); /** Traps to handle specified fault. */ void trap(Fault fault); + bool simPalCheck(int palFunc); #else /** Calls a syscall. */ void syscall(int64_t callnum); diff --git a/src/cpu/o3/dyn_inst_impl.hh b/src/cpu/o3/dyn_inst_impl.hh index 3b713ea8f..6398a3afe 100644 --- a/src/cpu/o3/dyn_inst_impl.hh +++ b/src/cpu/o3/dyn_inst_impl.hh @@ -124,12 +124,44 @@ BaseO3DynInst::completeAcc(PacketPtr pkt) } #if FULL_SYSTEM +template +Fault +BaseO3DynInst::hwrei() +{ +#if THE_ISA == ALPHA_ISA + // Can only do a hwrei when in pal mode. + if (!(this->readPC() & 0x3)) + return new AlphaISA::UnimplementedOpcodeFault; + + // Set the next PC based on the value of the EXC_ADDR IPR. + this->setNextPC(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR, + this->threadNumber)); + + // Tell CPU to clear any state it needs to if a hwrei is taken. + this->cpu->hwrei(this->threadNumber); +#else + +#endif + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + template void BaseO3DynInst::trap(Fault fault) { this->cpu->trap(fault, this->threadNumber); } + +template +bool +BaseO3DynInst::simPalCheck(int palFunc) +{ +#if THE_ISA != ALPHA_ISA + panic("simPalCheck called, but PAL only exists in Alpha!\n"); +#endif + return this->cpu->simPalCheck(palFunc, this->threadNumber); +} #else template void diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index ee5e9e668..845cbbd95 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -507,6 +507,8 @@ class OzoneCPU : public BaseCPU void dumpInsts() { frontEnd->dumpInsts(); } #if FULL_SYSTEM + Fault hwrei(); + bool simPalCheck(int palFunc); void processInterrupts(); #else void syscall(uint64_t &callnum); diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 94af07525..c8e0dfe3d 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -668,6 +668,21 @@ OzoneCPU::setSyscallReturn(SyscallReturn return_value, int tid) } } #else +template +Fault +OzoneCPU::hwrei() +{ + // Need to move this to ISA code + // May also need to make this per thread + + lockFlag = false; + lockAddrList.clear(); + thread.kernelStats->hwrei(); + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + template void OzoneCPU::processInterrupts() @@ -685,6 +700,31 @@ OzoneCPU::processInterrupts() interrupt->invoke(thread.getTC()); } } + +template +bool +OzoneCPU::simPalCheck(int palFunc) +{ + // Need to move this to ISA code + // May also need to make this per thread + thread.kernelStats->callpal(palFunc, tc); + + switch (palFunc) { + case PAL::halt: + haltContext(thread.readTid()); + if (--System::numSystemsRunning == 0) + exitSimLoop("all cpus halted"); + break; + + case PAL::bpt: + case PAL::bugchk: + if (system->breakpoint()) + return false; + break; + } + + return true; +} #endif template diff --git a/src/cpu/ozone/dyn_inst.hh b/src/cpu/ozone/dyn_inst.hh index 12a19e70d..e138cbe13 100644 --- a/src/cpu/ozone/dyn_inst.hh +++ b/src/cpu/ozone/dyn_inst.hh @@ -240,7 +240,9 @@ class OzoneDynInst : public BaseDynInst void setMiscReg(int misc_reg, const MiscReg &val); #if FULL_SYSTEM + Fault hwrei(); void trap(Fault fault); + bool simPalCheck(int palFunc); #else void syscall(uint64_t &callnum); #endif diff --git a/src/cpu/ozone/dyn_inst_impl.hh b/src/cpu/ozone/dyn_inst_impl.hh index 396007687..8519917f5 100644 --- a/src/cpu/ozone/dyn_inst_impl.hh +++ b/src/cpu/ozone/dyn_inst_impl.hh @@ -248,12 +248,34 @@ OzoneDynInst::setMiscReg(int misc_reg, const MiscReg &val) #if FULL_SYSTEM +template +Fault +OzoneDynInst::hwrei() +{ + if (!(this->readPC() & 0x3)) + return new AlphaISA::UnimplementedOpcodeFault; + + this->setNextPC(this->thread->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR)); + + this->cpu->hwrei(); + + // FIXME: XXX check for interrupts? XXX + return NoFault; +} + template void OzoneDynInst::trap(Fault fault) { fault->invoke(this->thread->getTC()); } + +template +bool +OzoneDynInst::simPalCheck(int palFunc) +{ + return this->cpu->simPalCheck(palFunc); +} #else template void diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 03c20a6f2..b7fcf1708 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -413,7 +413,9 @@ class BaseSimpleCPU : public BaseCPU //Fault CacheOp(uint8_t Op, Addr EA); #if FULL_SYSTEM + Fault hwrei() { return thread->hwrei(); } void ev5_trap(Fault fault) { fault->invoke(tc); } + bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else void syscall(int64_t callnum) { thread->syscall(callnum); } #endif diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index d26e984a3..189cbeec5 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -185,6 +185,10 @@ class SimpleThread : public ThreadState void dumpFuncProfile(); + Fault hwrei(); + + bool simPalCheck(int palFunc); + #endif /******************************************* -- 2.30.2