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.
This commit is contained in:
parent
4fac54f227
commit
b760b99f4d
16 changed files with 222 additions and 45 deletions
|
@ -547,3 +547,53 @@ copyIprs(ThreadContext *src, ThreadContext *dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AlphaISA
|
} // 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
|
||||||
|
|
|
@ -698,28 +698,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
else {
|
else {
|
||||||
// check to see if simulator wants to do something special
|
// check to see if simulator wants to do something special
|
||||||
// on this PAL call (including maybe suppress it)
|
// on this PAL call (including maybe suppress it)
|
||||||
|
bool dopal = xc->simPalCheck(palFunc);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dopal) {
|
if (dopal) {
|
||||||
xc->setMiscReg(IPR_EXC_ADDR, NPC);
|
xc->setMiscReg(IPR_EXC_ADDR, NPC);
|
||||||
|
@ -807,16 +786,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
format BasicOperate {
|
format BasicOperate {
|
||||||
0x1e: decode PALMODE {
|
0x1e: decode PALMODE {
|
||||||
0: OpcdecFault::hw_rei();
|
0: OpcdecFault::hw_rei();
|
||||||
1: hw_rei({{
|
1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore);
|
||||||
NPC = ExcAddr;
|
|
||||||
ThreadContext * tc = xc->tcBase();
|
|
||||||
if (!tc->misspeculating()) {
|
|
||||||
AlphaISA::Kernel::Statistics * kernelStats =
|
|
||||||
tc->getKernelStats();
|
|
||||||
if (kernelStats)
|
|
||||||
kernelStats->hwrei();
|
|
||||||
}
|
|
||||||
}}, IsSerializing, IsSerializeBefore);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// M5 special opcodes use the reserved 0x01 opcode space
|
// M5 special opcodes use the reserved 0x01 opcode space
|
||||||
|
|
|
@ -69,8 +69,6 @@ output exec {{
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
#include "arch/alpha/kernel_stats.hh"
|
|
||||||
#include "arch/alpha/osfpal.hh"
|
|
||||||
#include "sim/pseudo_inst.hh"
|
#include "sim/pseudo_inst.hh"
|
||||||
#endif
|
#endif
|
||||||
#include "arch/alpha/ipr.hh"
|
#include "arch/alpha/ipr.hh"
|
||||||
|
@ -189,7 +187,6 @@ def operands {{
|
||||||
'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1),
|
'Runiq': ('ControlReg', 'uq', 'MISCREG_UNIQ', None, 1),
|
||||||
'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1),
|
'FPCR': ('ControlReg', 'uq', 'MISCREG_FPCR', None, 1),
|
||||||
'IntrFlag': ('ControlReg', 'uq', 'MISCREG_INTR', 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
|
# The next two are hacks for non-full-system call-pal emulation
|
||||||
'R0': ('IntReg', 'uq', '0', None, 1),
|
'R0': ('IntReg', 'uq', '0', None, 1),
|
||||||
'R16': ('IntReg', 'uq', '16', None, 1),
|
'R16': ('IntReg', 'uq', '16', None, 1),
|
||||||
|
|
|
@ -86,15 +86,6 @@ class X86IntelMPConfigTable(SimObject):
|
||||||
ext_entries = VectorParam.X86IntelMPExtConfigEntry([],
|
ext_entries = VectorParam.X86IntelMPExtConfigEntry([],
|
||||||
'extended configuration table entries')
|
'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):
|
class X86IntelMPBaseConfigEntry(SimObject):
|
||||||
type = 'X86IntelMPBaseConfigEntry'
|
type = 'X86IntelMPBaseConfigEntry'
|
||||||
cxx_class = 'X86ISA::IntelMP::BaseConfigEntry'
|
cxx_class = 'X86ISA::IntelMP::BaseConfigEntry'
|
||||||
|
|
|
@ -336,7 +336,9 @@ class CheckerCPU : public BaseCPU
|
||||||
void translateDataReadReq(Request *req);
|
void translateDataReadReq(Request *req);
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
Fault hwrei() { return thread->hwrei(); }
|
||||||
void ev5_trap(Fault fault) { fault->invoke(tc); }
|
void ev5_trap(Fault fault) { fault->invoke(tc); }
|
||||||
|
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
|
||||||
#else
|
#else
|
||||||
// Assume that the normal CPU's call to syscall was successful.
|
// Assume that the normal CPU's call to syscall was successful.
|
||||||
// The checker's state would have already been updated by the syscall.
|
// The checker's state would have already been updated by the syscall.
|
||||||
|
|
|
@ -143,7 +143,17 @@ class ExecContext {
|
||||||
* given flags. */
|
* given flags. */
|
||||||
void writeHint(Addr addr, int size, unsigned 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. */
|
/** Executes a syscall specified by the callnum. */
|
||||||
void syscall(int64_t callnum);
|
void syscall(int64_t callnum);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,6 +53,10 @@
|
||||||
#include "cpu/checker/cpu.hh"
|
#include "cpu/checker/cpu.hh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if THE_ISA == ALPHA_ISA
|
||||||
|
#include "arch/alpha/osfpal.hh"
|
||||||
|
#endif
|
||||||
|
|
||||||
class BaseCPUParams;
|
class BaseCPUParams;
|
||||||
|
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
@ -901,6 +905,47 @@ FullO3CPU<Impl>::post_interrupt(int int_num, int index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
Fault
|
||||||
|
FullO3CPU<Impl>::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 <class Impl>
|
||||||
|
bool
|
||||||
|
FullO3CPU<Impl>::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 <class Impl>
|
template <class Impl>
|
||||||
Fault
|
Fault
|
||||||
FullO3CPU<Impl>::getInterrupts()
|
FullO3CPU<Impl>::getInterrupts()
|
||||||
|
|
|
@ -414,6 +414,11 @@ class FullO3CPU : public BaseO3CPU
|
||||||
/** Posts an interrupt. */
|
/** Posts an interrupt. */
|
||||||
void post_interrupt(int int_num, int index);
|
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. */
|
/** Returns the Fault for any valid interrupt. */
|
||||||
Fault getInterrupts();
|
Fault getInterrupts();
|
||||||
|
|
||||||
|
|
|
@ -168,8 +168,11 @@ class BaseO3DynInst : public BaseDynInst<Impl>
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
/** Calls hardware return from error interrupt. */
|
||||||
|
Fault hwrei();
|
||||||
/** Traps to handle specified fault. */
|
/** Traps to handle specified fault. */
|
||||||
void trap(Fault fault);
|
void trap(Fault fault);
|
||||||
|
bool simPalCheck(int palFunc);
|
||||||
#else
|
#else
|
||||||
/** Calls a syscall. */
|
/** Calls a syscall. */
|
||||||
void syscall(int64_t callnum);
|
void syscall(int64_t callnum);
|
||||||
|
|
|
@ -124,12 +124,44 @@ BaseO3DynInst<Impl>::completeAcc(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
template <class Impl>
|
||||||
|
Fault
|
||||||
|
BaseO3DynInst<Impl>::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 <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
BaseO3DynInst<Impl>::trap(Fault fault)
|
BaseO3DynInst<Impl>::trap(Fault fault)
|
||||||
{
|
{
|
||||||
this->cpu->trap(fault, this->threadNumber);
|
this->cpu->trap(fault, this->threadNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
bool
|
||||||
|
BaseO3DynInst<Impl>::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
|
#else
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
|
|
|
@ -507,6 +507,8 @@ class OzoneCPU : public BaseCPU
|
||||||
void dumpInsts() { frontEnd->dumpInsts(); }
|
void dumpInsts() { frontEnd->dumpInsts(); }
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
Fault hwrei();
|
||||||
|
bool simPalCheck(int palFunc);
|
||||||
void processInterrupts();
|
void processInterrupts();
|
||||||
#else
|
#else
|
||||||
void syscall(uint64_t &callnum);
|
void syscall(uint64_t &callnum);
|
||||||
|
|
|
@ -668,6 +668,21 @@ OzoneCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
template <class Impl>
|
||||||
|
Fault
|
||||||
|
OzoneCPU<Impl>::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 <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
OzoneCPU<Impl>::processInterrupts()
|
OzoneCPU<Impl>::processInterrupts()
|
||||||
|
@ -685,6 +700,31 @@ OzoneCPU<Impl>::processInterrupts()
|
||||||
interrupt->invoke(thread.getTC());
|
interrupt->invoke(thread.getTC());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
bool
|
||||||
|
OzoneCPU<Impl>::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
|
#endif
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
|
|
@ -240,7 +240,9 @@ class OzoneDynInst : public BaseDynInst<Impl>
|
||||||
void setMiscReg(int misc_reg, const MiscReg &val);
|
void setMiscReg(int misc_reg, const MiscReg &val);
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
Fault hwrei();
|
||||||
void trap(Fault fault);
|
void trap(Fault fault);
|
||||||
|
bool simPalCheck(int palFunc);
|
||||||
#else
|
#else
|
||||||
void syscall(uint64_t &callnum);
|
void syscall(uint64_t &callnum);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -248,12 +248,34 @@ OzoneDynInst<Impl>::setMiscReg(int misc_reg, const MiscReg &val)
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
Fault
|
||||||
|
OzoneDynInst<Impl>::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 <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
OzoneDynInst<Impl>::trap(Fault fault)
|
OzoneDynInst<Impl>::trap(Fault fault)
|
||||||
{
|
{
|
||||||
fault->invoke(this->thread->getTC());
|
fault->invoke(this->thread->getTC());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
bool
|
||||||
|
OzoneDynInst<Impl>::simPalCheck(int palFunc)
|
||||||
|
{
|
||||||
|
return this->cpu->simPalCheck(palFunc);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
|
|
|
@ -413,7 +413,9 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
//Fault CacheOp(uint8_t Op, Addr EA);
|
//Fault CacheOp(uint8_t Op, Addr EA);
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
|
Fault hwrei() { return thread->hwrei(); }
|
||||||
void ev5_trap(Fault fault) { fault->invoke(tc); }
|
void ev5_trap(Fault fault) { fault->invoke(tc); }
|
||||||
|
bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
|
||||||
#else
|
#else
|
||||||
void syscall(int64_t callnum) { thread->syscall(callnum); }
|
void syscall(int64_t callnum) { thread->syscall(callnum); }
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -185,6 +185,10 @@ class SimpleThread : public ThreadState
|
||||||
|
|
||||||
void dumpFuncProfile();
|
void dumpFuncProfile();
|
||||||
|
|
||||||
|
Fault hwrei();
|
||||||
|
|
||||||
|
bool simPalCheck(int palFunc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*******************************************
|
/*******************************************
|
||||||
|
|
Loading…
Reference in a new issue