cpu/base.cc
cpu/base_dyn_inst.cc
- cpu/exec_context.cc
+ cpu/cpu_exec_context.cc
cpu/exetrace.cc
cpu/pc_event.cc
cpu/static_inst.cc
// Alpha Linux convention for pipe() is that fd[0] is returned as
// the return value of the function, and fd[1] is returned in r20.
- xc->regs.intRegFile[20] = sim_fds[1];
+ xc->setIntReg(20, sim_fds[1]);
return sim_fds[0];
}
strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
strcpy(name->machine, "alpha");
- name.copyOut(xc->mem);
+ name.copyOut(xc->getMemPtr());
return 0;
}
TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
// I don't think this exactly matches the HW FPCR
*fpcr = 0;
- fpcr.copyOut(xc->mem);
+ fpcr.copyOut(xc->getMemPtr());
return 0;
}
case 14: { // SSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
// I don't think this exactly matches the HW FPCR
- fpcr.copyIn(xc->mem);
+ fpcr.copyIn(xc->getMemPtr());
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
return 0;
Fault
AlphaDTB::translate(MemReqPtr &req, bool write) const
{
- RegFile *regs = &req->xc->regs;
ExecContext *xc = req->xc;
- Addr pc = regs->pc;
+ Addr pc = xc->readPC();
AlphaISA::mode_type mode =
(AlphaISA::mode_type)DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM));
strcpy(name->version, "732");
strcpy(name->machine, "alpha");
- name.copyOut(xc->mem);
+ name.copyOut(xc->getMemPtr());
return 0;
}
case Tru64::GSI_MAX_CPU: {
TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
*max_cpu = htog((uint32_t)process->numCpus());
- max_cpu.copyOut(xc->mem);
+ max_cpu.copyOut(xc->getMemPtr());
return 1;
}
case Tru64::GSI_CPUS_IN_BOX: {
TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
*cpus_in_box = htog((uint32_t)process->numCpus());
- cpus_in_box.copyOut(xc->mem);
+ cpus_in_box.copyOut(xc->getMemPtr());
return 1;
}
case Tru64::GSI_PHYSMEM: {
TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
*physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
- physmem.copyOut(xc->mem);
+ physmem.copyOut(xc->getMemPtr());
return 1;
}
infop->cpu_ex_binding = htog(0);
infop->mhz = htog(667);
- infop.copyOut(xc->mem);
+ infop.copyOut(xc->getMemPtr());
return 1;
}
case Tru64::GSI_PROC_TYPE: {
TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
*proc_type = htog((uint64_t)11);
- proc_type.copyOut(xc->mem);
+ proc_type.copyOut(xc->getMemPtr());
return 1;
}
strncpy((char *)bufArg.bufferPtr(),
"COMPAQ Professional Workstation XP1000",
nbytes);
- bufArg.copyOut(xc->mem);
+ bufArg.copyOut(xc->getMemPtr());
return 1;
}
case Tru64::GSI_CLK_TCK: {
TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
*clk_hz = htog((uint64_t)1024);
- clk_hz.copyOut(xc->mem);
+ clk_hz.copyOut(xc->getMemPtr());
return 1;
}
{
if (number < 6) {
if (fp)
- return xc->regs.floatRegFile.q[16 + number];
+ return xc->readFloatRegInt(16 + number);
else
- return xc->regs.intRegFile[16 + number];
+ return xc->readIntReg(16 + number);
} else {
- Addr sp = xc->regs.intRegFile[30];
+ Addr sp = xc->readIntReg(30);
Addr paddr = vtophys(xc, sp + (number-6) * sizeof(uint64_t));
- return xc->physmem->phys_read_qword(paddr);
+ return xc->getPhysMemPtr()->phys_read_qword(paddr);
}
}
#include "base/stats/events.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/fast/cpu.hh"
#include "kern/kernel_stats.hh"
// Machine dependent functions
//
void
-AlphaISA::initCPU(RegFile *regs, int cpuId)
+AlphaISA::initCPU(ExecContext *xc, int cpuId)
{
- initIPRs(®s->miscRegs, cpuId);
+ initIPRs(xc, cpuId);
// CPU comes up with PAL regs enabled
swap_palshadow(regs, true);
- regs->intRegFile[16] = cpuId;
- regs->intRegFile[0] = cpuId;
+ xc->setIntReg(16, cpuId);
+ xc->setIntReg(0, cpuId);
- regs->pc = regs->miscRegs.readReg(IPR_PAL_BASE) + fault_addr(ResetFault);
- regs->npc = regs->pc + sizeof(MachInst);
+ xc->setPC(xc->readMiscReg(IPR_PAL_BASE) + fault_addr(ResetFault));
+ xc->setNextPC(xc->readPC() + sizeof(MachInst));
}
////////////////////////////////////////////////////////////////////////
//
//
void
-AlphaISA::initIPRs(MiscRegFile *miscRegs, int cpuId)
+AlphaISA::initIPRs(ExecContext *xc, int cpuId)
{
- miscRegs->clearIprs();
+ for (int i = 0; i < NumInternalProcRegs; ++i) {
+ xc->setMiscReg(i, 0);
+ }
- miscRegs->setReg(IPR_PAL_BASE, PalBase);
- miscRegs->setReg(IPR_MCSR, 0x6);
- miscRegs->setReg(IPR_PALtemp16, cpuId);
+ xc->setMiscReg(IPR_PAL_BASE, PalBase);
+ xc->setMiscReg(IPR_MCSR, 0x6);
+ xc->setMiscReg(IPR_PALtemp16, cpuId);
}
// Insure ISA semantics
// (no longer very clean due to the change in setIntReg() in the
// cpu model. Consider changing later.)
- cpu->xc->setIntReg(ZeroReg, 0);
- cpu->xc->setFloatRegDouble(ZeroReg, 0.0);
+ cpu->cpuXC->setIntReg(ZeroReg, 0);
+ cpu->cpuXC->setFloatRegDouble(ZeroReg, 0.0);
}
void
-ExecContext::ev5_trap(Fault fault)
+CPUExecContext::ev5_trap(Fault fault)
{
DPRINTF(Fault, "Fault %s at PC: %#x\n", fault->name, regs.pc);
cpu->recordEvent(csprintf("Fault %s", fault->name));
assert(!misspeculating());
- kernelStats->fault(fault);
+ cpu->kernelStats->fault(fault);
if (fault == ArithmeticFault)
panic("Arithmetic traps are unimplemented!");
}
Fault
-ExecContext::hwrei()
+CPUExecContext::hwrei()
{
if (!inPalMode())
return UnimplementedOpcodeFault;
setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
if (!misspeculating()) {
- kernelStats->hwrei();
+ cpu->kernelStats->hwrei();
if ((readMiscReg(AlphaISA::IPR_EXC_ADDR) & 1) == 0)
AlphaISA::swap_palshadow(®s, false);
return NoFault;
}
-void
-AlphaISA::MiscRegFile::clearIprs()
-{
- bzero((char *)ipr, NumInternalProcRegs * sizeof(InternalProcReg));
-}
-
AlphaISA::MiscReg
AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ExecContext *xc)
{
case AlphaISA::IPR_CC:
retval |= ipr[idx] & ULL(0xffffffff00000000);
- retval |= xc->cpu->curCycle() & ULL(0x00000000ffffffff);
+ retval |= xc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff);
break;
case AlphaISA::IPR_VA:
case AlphaISA::IPR_DTB_PTE:
{
- AlphaISA::PTE &pte = xc->dtb->index(!xc->misspeculating());
+ AlphaISA::PTE &pte = xc->getDTBPtr()->index(!xc->misspeculating());
retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
// write entire quad w/ no side-effect
old = ipr[idx];
ipr[idx] = val;
- xc->kernelStats->context(old, val);
+ xc->getCpuPtr()->kernelStats->context(old, val, xc);
break;
case AlphaISA::IPR_DTB_PTE:
// only write least significant five bits - interrupt level
ipr[idx] = val & 0x1f;
- xc->kernelStats->swpipl(ipr[idx]);
+ xc->getCpuPtr()->kernelStats->swpipl(ipr[idx]);
break;
case AlphaISA::IPR_DTB_CM:
if (val & 0x18)
- xc->kernelStats->mode(Kernel::user);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::user, xc);
else
- xc->kernelStats->mode(Kernel::kernel);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc);
case AlphaISA::IPR_ICM:
// only write two mode bits - processor mode
// really a control write
ipr[idx] = 0;
- xc->dtb->flushAll();
+ xc->getDTBPtr()->flushAll();
break;
case AlphaISA::IPR_DTB_IAP:
// really a control write
ipr[idx] = 0;
- xc->dtb->flushProcesses();
+ xc->getDTBPtr()->flushProcesses();
break;
case AlphaISA::IPR_DTB_IS:
// really a control write
ipr[idx] = val;
- xc->dtb->flushAddr(val, DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ xc->getDTBPtr()->flushAddr(val,
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
break;
case AlphaISA::IPR_DTB_TAG: {
pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
// insert new TAG/PTE value into data TLB
- xc->dtb->insert(val, pte);
+ xc->getDTBPtr()->insert(val, pte);
}
break;
pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
// insert new TAG/PTE value into data TLB
- xc->itb->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
+ xc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
}
break;
// really a control write
ipr[idx] = 0;
- xc->itb->flushAll();
+ xc->getITBPtr()->flushAll();
break;
case AlphaISA::IPR_ITB_IAP:
// really a control write
ipr[idx] = 0;
- xc->itb->flushProcesses();
+ xc->getITBPtr()->flushProcesses();
break;
case AlphaISA::IPR_ITB_IS:
// really a control write
ipr[idx] = val;
- xc->itb->flushAddr(val, ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
+ xc->getITBPtr()->flushAddr(val,
+ ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
break;
default:
* If return value is false, actual PAL call will be suppressed.
*/
bool
-ExecContext::simPalCheck(int palFunc)
+CPUExecContext::simPalCheck(int palFunc)
{
- kernelStats->callpal(palFunc);
+ cpu->kernelStats->callpal(palFunc, proxy);
switch (palFunc) {
case PAL::halt:
0x21: m5exit({{
AlphaPseudo::m5exit(xc->xcBase(), R16);
}}, No_OpClass, IsNonSpeculative);
- 0x30: initparam({{ Ra = xc->xcBase()->cpu->system->init_param; }});
+ 0x30: initparam({{ Ra = xc->xcBase()->getCpuPtr()->system->init_param; }});
0x40: resetstats({{
AlphaPseudo::resetstats(xc->xcBase(), R16, R17);
}}, IsNonSpeculative);
ExecContext *xc);
#if FULL_SYSTEM
- void clearIprs();
-
protected:
InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
{
Addr addr = 0;
- if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
panic("thread info not compiled into kernel\n");
thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
panic("thread info not compiled into kernel\n");
task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
panic("thread info not compiled into kernel\n");
task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
panic("thread info not compiled into kernel\n");
pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
- if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr))
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
panic("thread info not compiled into kernel\n");
name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
}
bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
- Addr pc = xc->regs.npc;
- bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd;
+ Addr pc = xc->readNextPC();
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
if (usermode) {
stack.push_back(user);
return;
}
- SymbolTable *symtab = xc->system->kernelSymtab;
- Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg];
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
+ Addr ksp = xc->readIntReg(TheISA::StackPointerReg);
Addr bottom = ksp & ~0x3fff;
Addr addr;
panic("could not find address %#x", pc);
stack.push_back(addr);
- pc = xc->regs.pc;
+ pc = xc->readPC();
}
Addr ra;
return;
}
- bool kernel = xc->system->kernelStart <= pc &&
- pc <= xc->system->kernelEnd;
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
if (!kernel)
return;
void
StackTrace::dump()
{
- StringWrap name(xc->cpu->name());
- SymbolTable *symtab = xc->system->kernelSymtab;
+ StringWrap name(xc->getCpuPtr()->name());
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
DPRINTFN("------ Stack ------\n");
paddr = vaddr;
} else {
AlphaISA::PageTableEntry pte =
- kernel_pte_lookup(xc->physmem, ptbr, vaddr);
+ kernel_pte_lookup(xc->getPhysMemPtr(), ptbr, vaddr);
if (pte.valid())
paddr = pte.paddr() | vaddr.offset();
}
uint8_t *
ptomem(ExecContext *xc, Addr paddr, size_t len)
{
- return xc->physmem->dma_addr(paddr, len);
+ return xc->getPhysMemPtr()->dma_addr(paddr, len);
}
uint8_t *
vtomem(ExecContext *xc, Addr vaddr, size_t len)
{
Addr paddr = vtophys(xc, vaddr);
- return xc->physmem->dma_addr(paddr, len);
+ return xc->getPhysMemPtr()->dma_addr(paddr, len);
}
void
paddr = vtophys(xc, src);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)cplen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
memcpy(dst, dmaaddr, len);
while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
memcpy(dst, dmaaddr, AlphaISA::PageBytes);
if (cplen > 0) {
paddr = vtophys(xc, src);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
assert(dmaaddr);
memcpy(dst, dmaaddr, cplen);
paddr = vtophys(xc, dest);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)cplen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
memcpy(dmaaddr, src, len);
while (cplen > AlphaISA::PageBytes) {
paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
memcpy(dmaaddr, src, AlphaISA::PageBytes);
if (cplen > 0) {
paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, cplen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
assert(dmaaddr);
memcpy(dmaaddr, src, cplen);
paddr = vtophys(xc, vaddr);
len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
(int)maxlen);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, len);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, len);
while (maxlen > AlphaISA::PageBytes) {
paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, AlphaISA::PageBytes);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr,
+ AlphaISA::PageBytes);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, AlphaISA::PageBytes);
if (maxlen > 0) {
paddr = vtophys(xc, vaddr);
- dmaaddr = (char *)xc->physmem->dma_addr(paddr, maxlen);
+ dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, maxlen);
assert(dmaaddr);
char *term = (char *)memchr(dmaaddr, 0, maxlen);
memcpy(&gdbregs[KGDB_REG_F0], context->regs.floatRegFile.q,
32 * sizeof(uint64_t));
#endif
- gdbregs[KGDB_REG_PC] = context->regs.pc;
+ gdbregs[KGDB_REG_PC] = context->readPC();
}
///////////////////////////////////////////////////////////
memcpy(context->regs.floatRegFile.q, &gdbregs[KGDB_REG_F0],
32 * sizeof(uint64_t));
#endif
- context->regs.pc = gdbregs[KGDB_REG_PC];
+ context->setPC(gdbregs[KGDB_REG_PC]);
}
void
void
RemoteGDB::setSingleStep()
{
- Addr pc = context->regs.pc;
+ Addr pc = context->readPC();
Addr npc, bpc;
bool set_bt = false;
return false;
DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
- context->regs.pc, context->regs.npc);
+ context->readPC(), context->readNextPC());
clearSingleStep();
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
clearSingleStep();
goto out;
case KGDB_CONT:
if (p - data < datalen) {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
clearSingleStep();
goto out;
subcmd = hex2i(&p);
if (*p++ == ';') {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
setSingleStep();
goto out;
case KGDB_STEP:
if (p - data < datalen) {
val = hex2i(&p);
- context->regs.pc = val;
- context->regs.npc = val + sizeof(MachInst);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
}
setSingleStep();
goto out;
#include "cpu/profile.hh"
#include "cpu/sampler/sampler.hh"
#include "sim/param.hh"
+#include "sim/process.hh"
#include "sim/sim_events.hh"
+#include "sim/system.hh"
#include "base/trace.hh"
+#if FULL_SYSTEM
+#include "kern/kernel_stats.hh"
+#endif
+
using namespace std;
vector<BaseCPU *> BaseCPU::cpuList;
profileEvent = NULL;
if (params->profile)
profileEvent = new ProfileEvent(this, params->profile);
+
+ kernelStats = new Kernel::Statistics(system);
#endif
+
}
BaseCPU::Params::Params()
BaseCPU::~BaseCPU()
{
+#if FULL_SYSTEM
+ if (kernelStats)
+ delete kernelStats;
+#endif
}
void
}
} else if (size == 1)
execContexts[0]->regStats(name());
+
+#if FULL_SYSTEM
+ if (kernelStats)
+ kernelStats->regStats(name() + ".kern");
+#endif
}
if (id != -1)
id += i;
- xc->cpu_id = system->registerExecContext(xc, id);
+ xc->setCpuId(system->registerExecContext(xc, id));
#else
- xc->cpu_id = xc->process->registerExecContext(xc);
+ xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc));
#endif
}
}
ExecContext *oldXC = oldCPU->execContexts[i];
newXC->takeOverFrom(oldXC);
- assert(newXC->cpu_id == oldXC->cpu_id);
+ assert(newXC->readCpuId() == oldXC->readCpuId());
#if FULL_SYSTEM
- system->replaceExecContext(newXC, newXC->cpu_id);
+ system->replaceExecContext(newXC, newXC->readCpuId());
#else
- assert(newXC->process == oldXC->process);
- newXC->process->replaceExecContext(newXC, newXC->cpu_id);
+ assert(newXC->getProcessPtr() == oldXC->getProcessPtr());
+ newXC->getProcessPtr()->replaceExecContext(newXC, newXC->readCpuId());
#endif
}
for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
interrupts[i] = oldCPU->interrupts[i];
intstatus = oldCPU->intstatus;
-
+/*
for (int i = 0; i < execContexts.size(); ++i)
if (execContexts[i]->profile)
execContexts[i]->profile->clear();
-
+*/
if (profileEvent)
profileEvent->schedule(curTick);
#endif
void
BaseCPU::ProfileEvent::process()
{
- for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
+/* for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
ExecContext *xc = cpu->execContexts[i];
xc->profile->sample(xc->profileNode, xc->profilePC);
}
-
+*/
schedule(curTick + interval);
}
{
SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
SERIALIZE_SCALAR(intstatus);
+
+#if FULL_SYSTEM
+ if (kernelStats)
+ kernelStats->serialize(os);
+#endif
+
}
void
{
UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
UNSERIALIZE_SCALAR(intstatus);
+
+#if FULL_SYSTEM
+ if (kernelStats)
+ kernelStats->unserialize(cp, section);
+#endif
}
#endif // FULL_SYSTEM
#if FULL_SYSTEM
class System;
+namespace Kernel { class Statistics; }
#endif
class BranchPred;
public:
// Number of CPU cycles simulated
Stats::Scalar<> numCycles;
+
+#if FULL_SYSTEM
+ Kernel::Statistics *kernelStats;
+#endif
};
#endif // __CPU_BASE_HH__
BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC,
Addr pred_PC, InstSeqNum seq_num,
FullCPU *cpu)
- : staticInst(machInst), traceData(NULL), cpu(cpu), xc(cpu->xcBase())
+ : staticInst(machInst), traceData(NULL), cpu(cpu), cpuXC(cpu->cpuXCBase())
{
seqNum = seq_num;
// state.
// Generate a MemReq so we can translate the effective address.
- MemReqPtr req = new MemReq(addr, xc, 1, flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), 1, flags);
req->asid = asid;
// Prefetches never cause faults.
fault = NoFault;
// note this is a local, not BaseDynInst::fault
- Fault trans_fault = xc->translateDataReadReq(req);
+ Fault trans_fault = cpuXC->translateDataReadReq(req);
if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) {
// It's a valid address to cacheable space. Record key MemReq
// will casue a TLB miss trap if necessary... not sure whether
// that's the best thing to do or not. We don't really need the
// MemReq otherwise, since wh64 has no functional effect.
- MemReqPtr req = new MemReq(addr, xc, size, flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), size, flags);
req->asid = asid;
- fault = xc->translateDataWriteReq(req);
+ fault = cpuXC->translateDataWriteReq(req);
if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
// Record key MemReq parameters so we can generate another one
Fault
BaseDynInst<Impl>::copySrcTranslate(Addr src)
{
- MemReqPtr req = new MemReq(src, xc, 64);
+ MemReqPtr req = new MemReq(src, cpuXC->getProxy(), 64);
req->asid = asid;
// translate to physical address
- Fault fault = xc->translateDataReadReq(req);
+ Fault fault = cpuXC->translateDataReadReq(req);
if (fault == NoFault) {
- xc->copySrcAddr = src;
- xc->copySrcPhysAddr = req->paddr;
+ cpuXC->copySrcAddr = src;
+ cpuXC->copySrcPhysAddr = req->paddr;
} else {
- xc->copySrcAddr = 0;
- xc->copySrcPhysAddr = 0;
+ cpuXC->copySrcAddr = 0;
+ cpuXC->copySrcPhysAddr = 0;
}
return fault;
}
BaseDynInst<Impl>::copy(Addr dest)
{
uint8_t data[64];
- FunctionalMemory *mem = xc->mem;
- assert(xc->copySrcPhysAddr || xc->misspeculating());
- MemReqPtr req = new MemReq(dest, xc, 64);
+ FunctionalMemory *mem = cpuXC->mem;
+ assert(cpuXC->copySrcPhysAddr || cpuXC->misspeculating());
+ MemReqPtr req = new MemReq(dest, cpuXC->getProxy(), 64);
req->asid = asid;
// translate to physical address
- Fault fault = xc->translateDataWriteReq(req);
+ Fault fault = cpuXC->translateDataWriteReq(req);
if (fault == NoFault) {
Addr dest_addr = req->paddr;
// Need to read straight from memory since we have more than 8 bytes.
- req->paddr = xc->copySrcPhysAddr;
+ req->paddr = cpuXC->copySrcPhysAddr;
mem->read(req, data);
req->paddr = dest_addr;
mem->write(req, data);
FullCPU *cpu;
/** Pointer to the exec context. Will not exist in the final version. */
- ExecContext *xc;
+ CPUExecContext *cpuXC;
/** The kind of fault this instruction has generated. */
Fault fault;
/** Returns the exec context.
* @todo: Remove this once the ExecContext is no longer used.
*/
- ExecContext *xcBase() { return xc; }
+ ExecContext *xcBase() { return cpuXC->getProxy(); }
private:
/** Instruction effective address.
inline Fault
BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
{
- MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
req->asid = asid;
fault = cpu->translateDataReadReq(req);
traceData->setData(data);
}
- MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
+ MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
req->asid = asid;
--- /dev/null
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+
+#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/exec_context.hh"
+
+#if FULL_SYSTEM
+#include "base/callback.hh"
+#include "base/cprintf.hh"
+#include "base/output.hh"
+#include "cpu/profile.hh"
+#include "kern/kernel_stats.hh"
+#include "sim/serialize.hh"
+#include "sim/sim_exit.hh"
+#include "sim/system.hh"
+#include "targetarch/stacktrace.hh"
+#else
+#include "sim/process.hh"
+#endif
+
+using namespace std;
+
+// constructor
+#if FULL_SYSTEM
+CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
+ AlphaITB *_itb, AlphaDTB *_dtb,
+ FunctionalMemory *_mem)
+ : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
+ cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
+ memctrl(_sys->memctrl), physmem(_sys->physmem), profile(NULL),
+ func_exe_inst(0), storeCondFailures(0)
+{
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+
+ memset(®s, 0, sizeof(RegFile));
+
+ if (cpu->params->profile) {
+ profile = new FunctionProfile(system->kernelSymtab);
+ Callback *cb =
+ new MakeCallback<CPUExecContext,
+ &CPUExecContext::dumpFuncProfile>(this);
+ registerExitCallback(cb);
+ }
+
+ // let's fill with a dummy node for now so we don't get a segfault
+ // on the first cycle when there's no node available.
+ static ProfileNode dummyNode;
+ profileNode = &dummyNode;
+ profilePC = 3;
+}
+#else
+CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
+ Process *_process, int _asid)
+ : _status(ExecContext::Unallocated),
+ cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
+ process(_process), mem(process->getMemory()), asid(_asid),
+ func_exe_inst(0), storeCondFailures(0)
+{
+ memset(®s, 0, sizeof(RegFile));
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+}
+
+CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
+ FunctionalMemory *_mem, int _asid)
+ : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
+ func_exe_inst(0), storeCondFailures(0)
+{
+ memset(®s, 0, sizeof(RegFile));
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+}
+
+CPUExecContext::CPUExecContext(RegFile *regFile)
+ : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1),
+ func_exe_inst(0), storeCondFailures(0)
+{
+ regs = *regFile;
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+}
+
+#endif
+
+CPUExecContext::~CPUExecContext()
+{
+ delete proxy;
+}
+
+#if FULL_SYSTEM
+void
+CPUExecContext::dumpFuncProfile()
+{
+ std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
+ profile->dump(proxy, *os);
+}
+#endif
+
+void
+CPUExecContext::takeOverFrom(ExecContext *oldContext)
+{
+/*
+ // some things should already be set up
+ assert(mem == oldContext->mem);
+#if FULL_SYSTEM
+ assert(system == oldContext->system);
+#else
+ assert(process == oldContext->process);
+#endif
+
+ // copy over functional state
+ _status = oldContext->_status;
+ regs = oldContext->regs;
+ cpu_id = oldContext->cpu_id;
+ func_exe_inst = oldContext->func_exe_inst;
+
+ storeCondFailures = 0;
+
+ oldContext->_status = CPUExecContext::Unallocated;
+*/
+}
+
+void
+CPUExecContext::serialize(ostream &os)
+{
+ SERIALIZE_ENUM(_status);
+ regs.serialize(os);
+ // thread_num and cpu_id are deterministic from the config
+ SERIALIZE_SCALAR(func_exe_inst);
+ SERIALIZE_SCALAR(inst);
+}
+
+
+void
+CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion)
+{
+ UNSERIALIZE_ENUM(_status);
+ regs.unserialize(cp, section);
+ // thread_num and cpu_id are deterministic from the config
+ UNSERIALIZE_SCALAR(func_exe_inst);
+ UNSERIALIZE_SCALAR(inst);
+}
+
+
+void
+CPUExecContext::activate(int delay)
+{
+ if (status() == ExecContext::Active)
+ return;
+
+ _status = ExecContext::Active;
+ cpu->activateContext(thread_num, delay);
+}
+
+void
+CPUExecContext::suspend()
+{
+ if (status() == ExecContext::Suspended)
+ return;
+
+#if FULL_SYSTEM
+ // Don't change the status from active if there are pending interrupts
+ if (cpu->check_interrupts()) {
+ assert(status() == ExecContext::Active);
+ return;
+ }
+#endif
+
+ _status = ExecContext::Suspended;
+ cpu->suspendContext(thread_num);
+}
+
+void
+CPUExecContext::deallocate()
+{
+ if (status() == ExecContext::Unallocated)
+ return;
+
+ _status = ExecContext::Unallocated;
+ cpu->deallocateContext(thread_num);
+}
+
+void
+CPUExecContext::halt()
+{
+ if (status() == ExecContext::Halted)
+ return;
+
+ _status = ExecContext::Halted;
+ cpu->haltContext(thread_num);
+}
+
+
+void
+CPUExecContext::regStats(const string &name)
+{
+}
+
+void
+CPUExecContext::copyArchRegs(ExecContext *xc)
+{
+ // First loop through the integer registers.
+ for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
+ setIntReg(i, xc->readIntReg(i));
+ }
+
+ // Then loop through the floating point registers.
+ for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
+ setFloatRegDouble(i, xc->readFloatRegDouble(i));
+ setFloatRegInt(i, xc->readFloatRegInt(i));
+ }
+
+ // Copy misc. registers
+ setMiscReg(AlphaISA::Fpcr_DepTag, xc->readMiscReg(AlphaISA::Fpcr_DepTag));
+ setMiscReg(AlphaISA::Uniq_DepTag, xc->readMiscReg(AlphaISA::Uniq_DepTag));
+ setMiscReg(AlphaISA::Lock_Flag_DepTag,
+ xc->readMiscReg(AlphaISA::Lock_Flag_DepTag));
+ setMiscReg(AlphaISA::Lock_Addr_DepTag,
+ xc->readMiscReg(AlphaISA::Lock_Addr_DepTag));
+
+ // Lastly copy PC/NPC
+ setPC(xc->readPC());
+ setNextPC(xc->readNextPC());
+}
+
+void
+CPUExecContext::trap(Fault fault)
+{
+ //TheISA::trap(fault); //One possible way to do it...
+
+ /** @todo: Going to hack it for now. Do a true fixup later. */
+#if FULL_SYSTEM
+ ev5_trap(fault);
+#else
+ fatal("fault (%d) detected @ PC 0x%08p", fault, readPC());
+#endif
+}
--- /dev/null
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
+#define __CPU_CPU_EXEC_CONTEXT_HH__
+
+#include "arch/isa_traits.hh"
+#include "config/full_system.hh"
+#include "cpu/exec_context.hh"
+#include "mem/functional/functional.hh"
+#include "mem/mem_req.hh"
+#include "sim/byteswap.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+
+// forward declaration: see functional_memory.hh
+class FunctionalMemory;
+class PhysicalMemory;
+class BaseCPU;
+
+#if FULL_SYSTEM
+
+#include "sim/system.hh"
+#include "targetarch/alpha_memory.hh"
+
+class FunctionProfile;
+class ProfileNode;
+class MemoryController;
+
+#else // !FULL_SYSTEM
+
+#include "sim/process.hh"
+
+#endif // FULL_SYSTEM
+
+//
+// The CPUExecContext object represents a functional context for
+// instruction execution. It incorporates everything required for
+// architecture-level functional simulation of a single thread.
+//
+
+class CPUExecContext
+{
+ protected:
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MachInst MachInst;
+ typedef TheISA::MiscRegFile MiscRegFile;
+ typedef TheISA::MiscReg MiscReg;
+ public:
+ typedef ExecContext::Status Status;
+
+ private:
+ Status _status;
+
+ public:
+ Status status() const { return _status; }
+
+ void setStatus(Status newStatus) { _status = newStatus; }
+
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ void activate(int delay = 1);
+
+ /// Set the status to Suspended.
+ void suspend();
+
+ /// Set the status to Unallocated.
+ void deallocate();
+
+ /// Set the status to Halted.
+ void halt();
+
+ protected:
+ RegFile regs; // correct-path register context
+
+ public:
+ // pointer to CPU associated with this context
+ BaseCPU *cpu;
+
+ ProxyExecContext<CPUExecContext> *proxy;
+
+ // Current instruction
+ MachInst inst;
+
+ // Index of hardware thread context on the CPU that this represents.
+ int thread_num;
+
+ // ID of this context w.r.t. the System or Process object to which
+ // it belongs. For full-system mode, this is the system CPU ID.
+ int cpu_id;
+
+#if FULL_SYSTEM
+ FunctionalMemory *mem;
+ AlphaITB *itb;
+ AlphaDTB *dtb;
+ System *system;
+
+ // the following two fields are redundant, since we can always
+ // look them up through the system pointer, but we'll leave them
+ // here for now for convenience
+ MemoryController *memctrl;
+ PhysicalMemory *physmem;
+
+ FunctionProfile *profile;
+ ProfileNode *profileNode;
+ Addr profilePC;
+ void dumpFuncProfile();
+
+#else
+ Process *process;
+
+ FunctionalMemory *mem; // functional storage for process address space
+
+ // Address space ID. Note that this is used for TIMING cache
+ // simulation only; all functional memory accesses should use
+ // one of the FunctionalMemory pointers above.
+ short asid;
+
+#endif
+
+ /**
+ * Temporary storage to pass the source address from copy_load to
+ * copy_store.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcAddr;
+ /**
+ * Temp storage for the physical source address of a copy.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcPhysAddr;
+
+
+ /*
+ * number of executed instructions, for matching with syscall trace
+ * points in EIO files.
+ */
+ Counter func_exe_inst;
+
+ //
+ // Count failed store conditionals so we can warn of apparent
+ // application deadlock situations.
+ unsigned storeCondFailures;
+
+ // constructor: initialize context from given process structure
+#if FULL_SYSTEM
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
+ AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
+#else
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
+ int _asid);
+ // Constructor to use XC to pass reg file around. Not used for anything
+ // else.
+ CPUExecContext(RegFile *regFile);
+#endif
+ virtual ~CPUExecContext();
+
+ virtual void takeOverFrom(ExecContext *oldContext);
+
+ void regStats(const std::string &name);
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string §ion);
+
+ BaseCPU *getCpuPtr() { return cpu; }
+
+ ExecContext *getProxy() { return proxy; }
+
+ int getThreadNum() { return thread_num; }
+
+#if FULL_SYSTEM
+ System *getSystemPtr() { return system; }
+
+ PhysicalMemory *getPhysMemPtr() { return physmem; }
+
+ AlphaITB *getITBPtr() { return itb; }
+
+ AlphaDTB *getDTBPtr() { return dtb; }
+
+ bool validInstAddr(Addr addr) { return true; }
+ bool validDataAddr(Addr addr) { return true; }
+ int getInstAsid() { return regs.instAsid(); }
+ int getDataAsid() { return regs.dataAsid(); }
+
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return itb->translate(req);
+ }
+
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, false);
+ }
+
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, true);
+ }
+
+#else
+ Process *getProcessPtr() { return process; }
+
+ bool validInstAddr(Addr addr)
+ { return process->validInstAddr(addr); }
+
+ bool validDataAddr(Addr addr)
+ { return process->validDataAddr(addr); }
+
+ int getInstAsid() { return asid; }
+ int getDataAsid() { return asid; }
+
+ Fault dummyTranslation(MemReqPtr &req)
+ {
+#if 0
+ assert((req->vaddr >> 48 & 0xffff) == 0);
+#endif
+
+ // put the asid in the upper 16 bits of the paddr
+ req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
+ req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
+ return NoFault;
+ }
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+#endif
+
+ template <class T>
+ Fault read(MemReqPtr &req, T &data)
+ {
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
+ if (req->flags & LOCKED) {
+ req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
+ req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
+ }
+#endif
+
+ Fault error;
+ error = mem->read(req, data);
+ data = LittleEndianGuest::gtoh(data);
+ return error;
+ }
+
+ template <class T>
+ Fault write(MemReqPtr &req, T &data)
+ {
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
+ ExecContext *xc;
+
+ // If this is a store conditional, act appropriately
+ if (req->flags & LOCKED) {
+ xc = req->xc;
+
+ if (req->flags & UNCACHEABLE) {
+ // Don't update result register (see stq_c in isa_desc)
+ req->result = 2;
+ xc->setStCondFailures(0);//Needed? [RGD]
+ } else {
+ bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
+ Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
+ req->result = lock_flag;
+ if (!lock_flag ||
+ ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ xc->setStCondFailures(xc->readStCondFailures() + 1);
+ if (((xc->readStCondFailures()) % 100000) == 0) {
+ std::cerr << "Warning: "
+ << xc->readStCondFailures()
+ << " consecutive store conditional failures "
+ << "on cpu " << req->xc->readCpuId()
+ << std::endl;
+ }
+ return NoFault;
+ }
+ else xc->setStCondFailures(0);
+ }
+ }
+
+ // Need to clear any locked flags on other proccessors for
+ // this address. Only do this for succsful Store Conditionals
+ // and all other stores (WH64?). Unsuccessful Store
+ // Conditionals would have returned above, and wouldn't fall
+ // through.
+ for (int i = 0; i < system->execContexts.size(); i++){
+ xc = system->execContexts[i];
+ if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
+ (req->paddr & ~0xf)) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ }
+ }
+
+#endif
+ return mem->write(req, (T)LittleEndianGuest::htog(data));
+ }
+
+ virtual bool misspeculating();
+
+
+ MachInst getInst() { return inst; }
+
+ void setInst(MachInst new_inst)
+ {
+ inst = new_inst;
+ }
+
+ Fault instRead(MemReqPtr &req)
+ {
+ return mem->read(req, inst);
+ }
+
+ void setCpuId(int id) { cpu_id = id; }
+
+ int readCpuId() { return cpu_id; }
+
+ FunctionalMemory *getMemPtr() { return mem; }
+
+ void copyArchRegs(ExecContext *xc);
+
+ //
+ // New accessors for new decoder.
+ //
+ uint64_t readIntReg(int reg_idx)
+ {
+ return regs.intRegFile[reg_idx];
+ }
+
+ float readFloatRegSingle(int reg_idx)
+ {
+ return (float)regs.floatRegFile.d[reg_idx];
+ }
+
+ double readFloatRegDouble(int reg_idx)
+ {
+ return regs.floatRegFile.d[reg_idx];
+ }
+
+ uint64_t readFloatRegInt(int reg_idx)
+ {
+ return regs.floatRegFile.q[reg_idx];
+ }
+
+ void setIntReg(int reg_idx, uint64_t val)
+ {
+ regs.intRegFile[reg_idx] = val;
+ }
+
+ void setFloatRegSingle(int reg_idx, float val)
+ {
+ regs.floatRegFile.d[reg_idx] = (double)val;
+ }
+
+ void setFloatRegDouble(int reg_idx, double val)
+ {
+ regs.floatRegFile.d[reg_idx] = val;
+ }
+
+ void setFloatRegInt(int reg_idx, uint64_t val)
+ {
+ regs.floatRegFile.q[reg_idx] = val;
+ }
+
+ uint64_t readPC()
+ {
+ return regs.pc;
+ }
+
+ void setPC(uint64_t val)
+ {
+ regs.pc = val;
+ }
+
+ uint64_t readNextPC()
+ {
+ return regs.npc;
+ }
+
+ void setNextPC(uint64_t val)
+ {
+ regs.npc = val;
+ }
+
+ MiscReg readMiscReg(int misc_reg)
+ {
+ return regs.miscRegs.readReg(misc_reg);
+ }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy);
+ }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ return regs.miscRegs.setReg(misc_reg, val);
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy);
+ }
+
+ unsigned readStCondFailures() { return storeCondFailures; }
+
+ void setStCondFailures(unsigned sc_failures)
+ { storeCondFailures = sc_failures; }
+
+ void clearArchRegs() { memset(®s, 0, sizeof(regs)); }
+
+#if FULL_SYSTEM
+ int readIntrFlag() { return regs.intrflag; }
+ void setIntrFlag(int val) { regs.intrflag = val; }
+ Fault hwrei();
+ bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
+ void ev5_trap(Fault fault);
+ bool simPalCheck(int palFunc);
+#endif
+
+ /** Meant to be more generic trap function to be
+ * called when an instruction faults.
+ * @param fault The fault generated by executing the instruction.
+ * @todo How to do this properly so it's dependent upon ISA only?
+ */
+
+ void trap(Fault fault);
+
+#if !FULL_SYSTEM
+ TheISA::IntReg getSyscallArg(int i)
+ {
+ return regs.intRegFile[TheISA::ArgumentReg0 + i];
+ }
+
+ // used to shift args for indirect syscall
+ void setSyscallArg(int i, TheISA::IntReg val)
+ {
+ regs.intRegFile[TheISA::ArgumentReg0 + i] = val;
+ }
+
+ void setSyscallReturn(SyscallReturn return_value)
+ {
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ const int RegA3 = 19; // only place this is used
+ if (return_value.successful()) {
+ // no error
+ regs.intRegFile[RegA3] = 0;
+ regs.intRegFile[TheISA::ReturnValueReg] = return_value.value();
+ } else {
+ // got an error, return details
+ regs.intRegFile[RegA3] = (TheISA::IntReg) -1;
+ regs.intRegFile[TheISA::ReturnValueReg] = -return_value.value();
+ }
+ }
+
+ void syscall()
+ {
+ process->syscall(proxy);
+ }
+
+ Counter readFuncExeInst() { return func_exe_inst; }
+
+ void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; }
+#endif
+};
+
+
+// for non-speculative execution context, spec_mode is always false
+inline bool
+CPUExecContext::misspeculating()
+{
+ return false;
+}
+
+#endif // __CPU_CPU_EXEC_CONTEXT_HH__
+++ /dev/null
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-
-#if FULL_SYSTEM
-#include "base/callback.hh"
-#include "base/cprintf.hh"
-#include "base/output.hh"
-#include "cpu/profile.hh"
-#include "kern/kernel_stats.hh"
-#include "sim/serialize.hh"
-#include "sim/sim_exit.hh"
-#include "sim/system.hh"
-#include "targetarch/stacktrace.hh"
-#else
-#include "sim/process.hh"
-#endif
-
-using namespace std;
-
-// constructor
-#if FULL_SYSTEM
-ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
- AlphaITB *_itb, AlphaDTB *_dtb,
- FunctionalMemory *_mem)
- : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
- cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
- memctrl(_sys->memctrl), physmem(_sys->physmem),
- kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
- fnbin(kernelBinning->fnbin), profile(NULL),
- func_exe_inst(0), storeCondFailures(0)
-{
- kernelStats = new Kernel::Statistics(this);
- memset(®s, 0, sizeof(RegFile));
-
- if (cpu->params->profile) {
- profile = new FunctionProfile(system->kernelSymtab);
- Callback *cb =
- new MakeCallback<ExecContext, &ExecContext::dumpFuncProfile>(this);
- registerExitCallback(cb);
- }
-
- // let's fill with a dummy node for now so we don't get a segfault
- // on the first cycle when there's no node available.
- static ProfileNode dummyNode;
- profileNode = &dummyNode;
- profilePC = 3;
-}
-#else
-ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
- Process *_process, int _asid)
- : _status(ExecContext::Unallocated),
- cpu(_cpu), thread_num(_thread_num), cpu_id(-1),
- process(_process), mem(process->getMemory()), asid(_asid),
- func_exe_inst(0), storeCondFailures(0)
-{
- memset(®s, 0, sizeof(RegFile));
-}
-
-ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
- FunctionalMemory *_mem, int _asid)
- : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid),
- func_exe_inst(0), storeCondFailures(0)
-{
- memset(®s, 0, sizeof(RegFile));
-}
-#endif
-
-ExecContext::~ExecContext()
-{
-#if FULL_SYSTEM
- delete kernelStats;
-#endif
-}
-
-#if FULL_SYSTEM
-void
-ExecContext::dumpFuncProfile()
-{
- std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
- profile->dump(this, *os);
-}
-#endif
-
-void
-ExecContext::takeOverFrom(ExecContext *oldContext)
-{
- // some things should already be set up
- assert(mem == oldContext->mem);
-#if FULL_SYSTEM
- assert(system == oldContext->system);
-#else
- assert(process == oldContext->process);
-#endif
-
- // copy over functional state
- _status = oldContext->_status;
- regs = oldContext->regs;
- cpu_id = oldContext->cpu_id;
- func_exe_inst = oldContext->func_exe_inst;
-
- storeCondFailures = 0;
-
- oldContext->_status = ExecContext::Unallocated;
-}
-
-void
-ExecContext::serialize(ostream &os)
-{
- SERIALIZE_ENUM(_status);
- regs.serialize(os);
- // thread_num and cpu_id are deterministic from the config
- SERIALIZE_SCALAR(func_exe_inst);
- SERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- kernelStats->serialize(os);
-#endif
-}
-
-
-void
-ExecContext::unserialize(Checkpoint *cp, const std::string §ion)
-{
- UNSERIALIZE_ENUM(_status);
- regs.unserialize(cp, section);
- // thread_num and cpu_id are deterministic from the config
- UNSERIALIZE_SCALAR(func_exe_inst);
- UNSERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- kernelStats->unserialize(cp, section);
-#endif
-}
-
-
-void
-ExecContext::activate(int delay)
-{
- if (status() == Active)
- return;
-
- _status = Active;
- cpu->activateContext(thread_num, delay);
-}
-
-void
-ExecContext::suspend()
-{
- if (status() == Suspended)
- return;
-
-#if FULL_SYSTEM
- // Don't change the status from active if there are pending interrupts
- if (cpu->check_interrupts()) {
- assert(status() == Active);
- return;
- }
-#endif
-
- _status = Suspended;
- cpu->suspendContext(thread_num);
-}
-
-void
-ExecContext::deallocate()
-{
- if (status() == Unallocated)
- return;
-
- _status = Unallocated;
- cpu->deallocateContext(thread_num);
-}
-
-void
-ExecContext::halt()
-{
- if (status() == Halted)
- return;
-
- _status = Halted;
- cpu->haltContext(thread_num);
-}
-
-
-void
-ExecContext::regStats(const string &name)
-{
-#if FULL_SYSTEM
- kernelStats->regStats(name + ".kern");
-#endif
-}
-
-void
-ExecContext::trap(Fault fault)
-{
- //TheISA::trap(fault); //One possible way to do it...
-
- /** @todo: Going to hack it for now. Do a true fixup later. */
-#if FULL_SYSTEM
- ev5_trap(fault);
-#else
- fatal("fault (%d) detected @ PC 0x%08p", fault, readPC());
-#endif
-}
/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#define __CPU_EXEC_CONTEXT_HH__
#include "config/full_system.hh"
-#include "mem/functional/functional.hh"
#include "mem/mem_req.hh"
+#include "sim/faults.hh"
#include "sim/host.hh"
#include "sim/serialize.hh"
-#include "arch/isa_traits.hh"
-//#include "arch/isa_registers.hh"
#include "sim/byteswap.hh"
// forward declaration: see functional_memory.hh
+// @todo: Figure out a more architecture independent way to obtain the ITB and
+// DTB pointers.
+class AlphaDTB;
+class AlphaITB;
+class BaseCPU;
class FunctionalMemory;
class PhysicalMemory;
-class BaseCPU;
-
-#if FULL_SYSTEM
-
-#include "sim/system.hh"
-#include "targetarch/alpha_memory.hh"
-
-class FunctionProfile;
-class ProfileNode;
-class MemoryController;
-namespace Kernel { class Binning; class Statistics; }
-
-#else // !FULL_SYSTEM
-
-#include "sim/process.hh"
-
-#endif // FULL_SYSTEM
-
-//
-// The ExecContext object represents a functional context for
-// instruction execution. It incorporates everything required for
-// architecture-level functional simulation of a single thread.
-//
+class Process;
+class System;
class ExecContext
{
protected:
typedef TheISA::RegFile RegFile;
typedef TheISA::MachInst MachInst;
+ typedef TheISA::IntReg IntReg;
typedef TheISA::MiscRegFile MiscRegFile;
typedef TheISA::MiscReg MiscReg;
public:
Active,
/// Temporarily inactive. Entered while waiting for
- /// initialization,synchronization, etc.
+ /// synchronization, etc.
Suspended,
/// Permanently shut down. Entered when target executes
Halted
};
- private:
- Status _status;
+ virtual ~ExecContext() { };
- public:
- Status status() const { return _status; }
+ virtual BaseCPU *getCpuPtr() = 0;
+
+ virtual void setCpuId(int id) = 0;
- void setStatus(Status newStatus) { _status = newStatus; }
+ virtual int readCpuId() = 0;
+
+ virtual FunctionalMemory *getMemPtr() = 0;
+
+#if FULL_SYSTEM
+ virtual System *getSystemPtr() = 0;
+
+ virtual PhysicalMemory *getPhysMemPtr() = 0;
+
+ virtual AlphaITB *getITBPtr() = 0;
+
+ virtual AlphaDTB * getDTBPtr() = 0;
+#else
+ virtual Process *getProcessPtr() = 0;
+#endif
+
+ virtual Status status() const = 0;
/// Set the status to Active. Optional delay indicates number of
/// cycles to wait before beginning execution.
- void activate(int delay = 1);
+ virtual void activate(int delay = 1) = 0;
/// Set the status to Suspended.
- void suspend();
+ virtual void suspend() = 0;
/// Set the status to Unallocated.
- void deallocate();
+ virtual void deallocate() = 0;
/// Set the status to Halted.
- void halt();
+ virtual void halt() = 0;
- public:
- RegFile regs; // correct-path register context
+#if FULL_SYSTEM
+ virtual void dumpFuncProfile() = 0;
+#endif
- // pointer to CPU associated with this context
- BaseCPU *cpu;
+ virtual void takeOverFrom(ExecContext *oldContext) = 0;
- // Current instruction
- MachInst inst;
+ virtual void regStats(const std::string &name) = 0;
- // Index of hardware thread context on the CPU that this represents.
- int thread_num;
+ virtual void serialize(std::ostream &os) = 0;
+ virtual void unserialize(Checkpoint *cp, const std::string §ion) = 0;
- // ID of this context w.r.t. the System or Process object to which
- // it belongs. For full-system mode, this is the system CPU ID.
- int cpu_id;
+ virtual int getThreadNum() = 0;
-#if FULL_SYSTEM
- FunctionalMemory *mem;
- AlphaITB *itb;
- AlphaDTB *dtb;
- System *system;
-
- // the following two fields are redundant, since we can always
- // look them up through the system pointer, but we'll leave them
- // here for now for convenience
- MemoryController *memctrl;
- PhysicalMemory *physmem;
-
- Kernel::Binning *kernelBinning;
- Kernel::Statistics *kernelStats;
- bool bin;
- bool fnbin;
-
- FunctionProfile *profile;
- ProfileNode *profileNode;
- Addr profilePC;
- void dumpFuncProfile();
+ virtual bool validInstAddr(Addr addr) = 0;
+ virtual bool validDataAddr(Addr addr) = 0;
+ virtual int getInstAsid() = 0;
+ virtual int getDataAsid() = 0;
-#else
- Process *process;
+ virtual Fault translateInstReq(MemReqPtr &req) = 0;
+
+ virtual Fault translateDataReadReq(MemReqPtr &req) = 0;
+
+ virtual Fault translateDataWriteReq(MemReqPtr &req) = 0;
+
+ virtual TheISA::MachInst getInst() = 0;
+
+ virtual void copyArchRegs(ExecContext *xc) = 0;
+
+ virtual void clearArchRegs() = 0;
+
+ //
+ // New accessors for new decoder.
+ //
+ virtual uint64_t readIntReg(int reg_idx) = 0;
+
+ virtual float readFloatRegSingle(int reg_idx) = 0;
- FunctionalMemory *mem; // functional storage for process address space
+ virtual double readFloatRegDouble(int reg_idx) = 0;
- // Address space ID. Note that this is used for TIMING cache
- // simulation only; all functional memory accesses should use
- // one of the FunctionalMemory pointers above.
- short asid;
+ virtual uint64_t readFloatRegInt(int reg_idx) = 0;
+ virtual void setIntReg(int reg_idx, uint64_t val) = 0;
+
+ virtual void setFloatRegSingle(int reg_idx, float val) = 0;
+
+ virtual void setFloatRegDouble(int reg_idx, double val) = 0;
+
+ virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0;
+
+ virtual uint64_t readPC() = 0;
+
+ virtual void setPC(uint64_t val) = 0;
+
+ virtual uint64_t readNextPC() = 0;
+
+ virtual void setNextPC(uint64_t val) = 0;
+
+ virtual MiscReg readMiscReg(int misc_reg) = 0;
+
+ virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0;
+
+ virtual Fault setMiscReg(int misc_reg, const MiscReg &val) = 0;
+
+ virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0;
+
+ virtual unsigned readStCondFailures() = 0;
+
+ virtual void setStCondFailures(unsigned sc_failures) = 0;
+
+#if FULL_SYSTEM
+ virtual int readIntrFlag() = 0;
+ virtual void setIntrFlag(int val) = 0;
+ virtual Fault hwrei() = 0;
+ virtual bool inPalMode() = 0;
+ virtual void ev5_trap(Fault fault) = 0;
+ virtual bool simPalCheck(int palFunc) = 0;
#endif
- /**
- * Temporary storage to pass the source address from copy_load to
- * copy_store.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcAddr;
- /**
- * Temp storage for the physical source address of a copy.
- * @todo Remove this temporary when we have a better way to do it.
+ virtual bool misspeculating() = 0;
+
+ /** Meant to be more generic trap function to be
+ * called when an instruction faults.
+ * @param fault The fault generated by executing the instruction.
+ * @todo How to do this properly so it's dependent upon ISA only?
*/
- Addr copySrcPhysAddr;
+ virtual void trap(Fault fault) = 0;
- /*
- * number of executed instructions, for matching with syscall trace
- * points in EIO files.
- */
- Counter func_exe_inst;
+#if !FULL_SYSTEM
+ virtual IntReg getSyscallArg(int i) = 0;
- //
- // Count failed store conditionals so we can warn of apparent
- // application deadlock situations.
- unsigned storeCondFailures;
+ // used to shift args for indirect syscall
+ virtual void setSyscallArg(int i, IntReg val) = 0;
- // constructor: initialize context from given process structure
-#if FULL_SYSTEM
- ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
-#else
- ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
- ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
- int _asid);
+ virtual void setSyscallReturn(SyscallReturn return_value) = 0;
+
+ virtual void syscall() = 0;
+
+ virtual Counter readFuncExeInst() = 0;
+
+ virtual void setFuncExeInst(Counter new_val) = 0;
#endif
- virtual ~ExecContext();
+};
- virtual void takeOverFrom(ExecContext *oldContext);
+template <class XC>
+class ProxyExecContext : public ExecContext
+{
+ public:
+ ProxyExecContext(XC *actual_xc)
+ { actualXC = actual_xc; }
- void regStats(const std::string &name);
+ private:
+ XC *actualXC;
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string §ion);
+ public:
-#if FULL_SYSTEM
- bool validInstAddr(Addr addr) { return true; }
- bool validDataAddr(Addr addr) { return true; }
- int getInstAsid() { return regs.instAsid(); }
- int getDataAsid() { return regs.dataAsid(); }
+ BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); }
- Fault translateInstReq(MemReqPtr &req)
- {
- return itb->translate(req);
- }
+ void setCpuId(int id) { actualXC->setCpuId(id); }
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dtb->translate(req, false);
- }
+ int readCpuId() { return actualXC->readCpuId(); }
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dtb->translate(req, true);
- }
+ FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); }
-#else
- bool validInstAddr(Addr addr)
- { return process->validInstAddr(addr); }
+#if FULL_SYSTEM
+ System *getSystemPtr() { return actualXC->getSystemPtr(); }
- bool validDataAddr(Addr addr)
- { return process->validDataAddr(addr); }
+ PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); }
- int getInstAsid() { return asid; }
- int getDataAsid() { return asid; }
+ AlphaITB *getITBPtr() { return actualXC->getITBPtr(); }
- Fault dummyTranslation(MemReqPtr &req)
- {
-#if 0
- assert((req->vaddr >> 48 & 0xffff) == 0);
+ AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); }
+#else
+ Process *getProcessPtr() { return actualXC->getProcessPtr(); }
#endif
- // put the asid in the upper 16 bits of the paddr
- req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
- req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
- return NoFault;
- }
- Fault translateInstReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
+ Status status() const { return actualXC->status(); }
-#endif
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ void activate(int delay = 1) { actualXC->activate(delay); }
- template <class T>
- Fault read(MemReqPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- MiscRegFile *cregs = &req->xc->regs.miscRegs;
- cregs->setReg(TheISA::Lock_Addr_DepTag, req->paddr);
- cregs->setReg(TheISA::Lock_Flag_DepTag, true);
- }
-#endif
+ /// Set the status to Suspended.
+ void suspend() { actualXC->suspend(); }
- Fault error;
- error = mem->read(req, data);
- data = LittleEndianGuest::gtoh(data);
- return error;
- }
+ /// Set the status to Unallocated.
+ void deallocate() { actualXC->deallocate(); }
- template <class T>
- Fault write(MemReqPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
-
- MiscRegFile *cregs;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- cregs = &req->xc->regs.miscRegs;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- req->xc->storeCondFailures = 0;//Needed? [RGD]
- } else {
- bool lock_flag = cregs->readReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = cregs->readReg(TheISA::Lock_Addr_DepTag);
- req->result = lock_flag;
- if (!lock_flag ||
- ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- cregs->setReg(TheISA::Lock_Flag_DepTag, false);
- if (((++req->xc->storeCondFailures) % 100000) == 0) {
- std::cerr << "Warning: "
- << req->xc->storeCondFailures
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->cpu_id
- << std::endl;
- }
- return NoFault;
- }
- else req->xc->storeCondFailures = 0;
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < system->execContexts.size(); i++){
- cregs = &system->execContexts[i]->regs.miscRegs;
- if ((cregs->readReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
- (req->paddr & ~0xf)) {
- cregs->setReg(TheISA::Lock_Flag_DepTag, false);
- }
- }
+ /// Set the status to Halted.
+ void halt() { actualXC->halt(); }
+#if FULL_SYSTEM
+ void dumpFuncProfile() { actualXC->dumpFuncProfile(); }
#endif
- return mem->write(req, (T)LittleEndianGuest::htog(data));
- }
- virtual bool misspeculating();
+ void takeOverFrom(ExecContext *oldContext)
+ { actualXC->takeOverFrom(oldContext); }
+ void regStats(const std::string &name) { actualXC->regStats(name); }
- MachInst getInst() { return inst; }
+ void serialize(std::ostream &os) { actualXC->serialize(os); }
+ void unserialize(Checkpoint *cp, const std::string §ion)
+ { actualXC->unserialize(cp, section); }
- void setInst(MachInst new_inst)
- {
- inst = new_inst;
- }
+ int getThreadNum() { return actualXC->getThreadNum(); }
- Fault instRead(MemReqPtr &req)
- {
- return mem->read(req, inst);
- }
+ bool validInstAddr(Addr addr) { return actualXC->validInstAddr(addr); }
+ bool validDataAddr(Addr addr) { return actualXC->validDataAddr(addr); }
+ int getInstAsid() { return actualXC->getInstAsid(); }
+ int getDataAsid() { return actualXC->getDataAsid(); }
+
+ Fault translateInstReq(MemReqPtr &req)
+ { return actualXC->translateInstReq(req); }
+
+ Fault translateDataReadReq(MemReqPtr &req)
+ { return actualXC->translateDataReadReq(req); }
+
+ Fault translateDataWriteReq(MemReqPtr &req)
+ { return actualXC->translateDataWriteReq(req); }
+
+ // @todo: Do I need this?
+ MachInst getInst() { return actualXC->getInst(); }
+
+ // @todo: Do I need this?
+ void copyArchRegs(ExecContext *xc) { actualXC->copyArchRegs(xc); }
+
+ void clearArchRegs() { actualXC->clearArchRegs(); }
//
// New accessors for new decoder.
//
uint64_t readIntReg(int reg_idx)
- {
- return regs.intRegFile[reg_idx];
- }
+ { return actualXC->readIntReg(reg_idx); }
float readFloatRegSingle(int reg_idx)
- {
- return (float)regs.floatRegFile.d[reg_idx];
- }
+ { return actualXC->readFloatRegSingle(reg_idx); }
double readFloatRegDouble(int reg_idx)
- {
- return regs.floatRegFile.d[reg_idx];
- }
+ { return actualXC->readFloatRegDouble(reg_idx); }
uint64_t readFloatRegInt(int reg_idx)
- {
- return regs.floatRegFile.q[reg_idx];
- }
+ { return actualXC->readFloatRegInt(reg_idx); }
void setIntReg(int reg_idx, uint64_t val)
- {
- regs.intRegFile[reg_idx] = val;
- }
+ { actualXC->setIntReg(reg_idx, val); }
void setFloatRegSingle(int reg_idx, float val)
- {
- regs.floatRegFile.d[reg_idx] = (double)val;
- }
+ { actualXC->setFloatRegSingle(reg_idx, val); }
void setFloatRegDouble(int reg_idx, double val)
- {
- regs.floatRegFile.d[reg_idx] = val;
- }
+ { actualXC->setFloatRegDouble(reg_idx, val); }
void setFloatRegInt(int reg_idx, uint64_t val)
- {
- regs.floatRegFile.q[reg_idx] = val;
- }
+ { actualXC->setFloatRegInt(reg_idx, val); }
- uint64_t readPC()
- {
- return regs.pc;
- }
+ uint64_t readPC() { return actualXC->readPC(); }
- void setNextPC(uint64_t val)
- {
- regs.npc = val;
- }
+ void setPC(uint64_t val) { actualXC->setPC(val); }
+
+ uint64_t readNextPC() { return actualXC->readNextPC(); }
+
+ void setNextPC(uint64_t val) { actualXC->setNextPC(val); }
MiscReg readMiscReg(int misc_reg)
- {
- return regs.miscRegs.readReg(misc_reg);
- }
+ { return actualXC->readMiscReg(misc_reg); }
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return regs.miscRegs.readRegWithEffect(misc_reg, fault, this);
- }
+ { return actualXC->readMiscRegWithEffect(misc_reg, fault); }
Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setReg(misc_reg, val);
- }
+ { return actualXC->setMiscReg(misc_reg, val); }
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setRegWithEffect(misc_reg, val, this);
- }
+ { return actualXC->setMiscRegWithEffect(misc_reg, val); }
+
+ unsigned readStCondFailures()
+ { return actualXC->readStCondFailures(); }
+
+ void setStCondFailures(unsigned sc_failures)
+ { actualXC->setStCondFailures(sc_failures); }
#if FULL_SYSTEM
- int readIntrFlag() { return regs.intrflag; }
- void setIntrFlag(int val) { regs.intrflag = val; }
- Fault hwrei();
- bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
- void ev5_trap(Fault fault);
- bool simPalCheck(int palFunc);
+ int readIntrFlag() { return actualXC->readIntrFlag(); }
+
+ void setIntrFlag(int val) { actualXC->setIntrFlag(val); }
+
+ Fault hwrei() { return actualXC->hwrei(); }
+
+ bool inPalMode() { return actualXC->inPalMode(); }
+
+ void ev5_trap(Fault fault) { actualXC->ev5_trap(fault); }
+
+ bool simPalCheck(int palFunc) { return actualXC->simPalCheck(palFunc); }
#endif
+ // @todo: Fix this!
+ bool misspeculating() { return false; }
+
/** Meant to be more generic trap function to be
* called when an instruction faults.
* @param fault The fault generated by executing the instruction.
* @todo How to do this properly so it's dependent upon ISA only?
*/
- void trap(Fault fault);
+ void trap(Fault fault) { actualXC->trap(fault); }
#if !FULL_SYSTEM
- TheISA::IntReg getSyscallArg(int i)
- {
- return regs.intRegFile[TheISA::ArgumentReg0 + i];
- }
+ IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); }
// used to shift args for indirect syscall
- void setSyscallArg(int i, TheISA::IntReg val)
- {
- regs.intRegFile[TheISA::ArgumentReg0 + i] = val;
- }
+ void setSyscallArg(int i, IntReg val)
+ { actualXC->setSyscallArg(i, val); }
void setSyscallReturn(SyscallReturn return_value)
- {
- // check for error condition. Alpha syscall convention is to
- // indicate success/failure in reg a3 (r19) and put the
- // return value itself in the standard return value reg (v0).
- const int RegA3 = 19; // only place this is used
- if (return_value.successful()) {
- // no error
- regs.intRegFile[RegA3] = 0;
- regs.intRegFile[TheISA::ReturnValueReg] = return_value.value();
- } else {
- // got an error, return details
- regs.intRegFile[RegA3] = (TheISA::IntReg) -1;
- regs.intRegFile[TheISA::ReturnValueReg] = -return_value.value();
- }
- }
-
- void syscall()
- {
- process->syscall(this);
- }
-#endif
-};
+ { actualXC->setSyscallReturn(return_value); }
+ void syscall() { actualXC->syscall(); }
-// for non-speculative execution context, spec_mode is always false
-inline bool
-ExecContext::misspeculating()
-{
- return false;
-}
+ Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
-#endif // __CPU_EXEC_CONTEXT_HH__
+ void setFuncExeInst(Counter new_val)
+ { return actualXC->setFuncExeInst(new_val); }
+#endif
+};
+
+#endif
#include "encumbered/cpu/full/spec_state.hh"
#include "encumbered/cpu/full/issue.hh"
#include "cpu/exetrace.hh"
-#include "cpu/exec_context.hh"
#include "base/loader/symtab.hh"
#include "cpu/base.hh"
#include "cpu/static_inst.hh"
IntrControl::post(int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[0]->cpu;
+ BaseCPU *temp = xcvec[0]->getCpuPtr();
temp->post_interrupt(int_num, index);
}
IntrControl::post(int cpu_id, int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[cpu_id]->cpu;
+ BaseCPU *temp = xcvec[cpu_id]->getCpuPtr();
temp->post_interrupt(int_num, index);
}
IntrControl::clear(int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[0]->cpu;
+ BaseCPU *temp = xcvec[0]->getCpuPtr();
temp->clear_interrupt(int_num, index);
}
IntrControl::clear(int cpu_id, int int_num, int index)
{
std::vector<ExecContext *> &xcvec = cpu->system->execContexts;
- BaseCPU *temp = xcvec[cpu_id]->cpu;
+ BaseCPU *temp = xcvec[cpu_id]->getCpuPtr();
temp->clear_interrupt(int_num, index);
}
#include "cpu/base.hh"
#include "sim/sim_object.hh"
#include "sim/system.hh"
-#include "cpu/exec_context.hh"
class IntrControl : public SimObject
#include "base/misc.hh"
#include "base/statistics.hh"
-#include "cpu/exec_context.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/memtest/memtest.hh"
#include "mem/cache/base_cache.hh"
#include "sim/builder.hh"
vector<string> cmd;
cmd.push_back("/bin/ls");
vector<string> null_vec;
- xc = new ExecContext(NULL, 0, mainMem, 0);
+ cpuXC = new CPUExecContext(NULL, 0, mainMem, 0);
blockSize = cacheInterface->getBlockSize();
blockAddrMask = blockSize - 1;
req->data = new uint8_t[req->size];
req->paddr &= ~(req->size - 1);
req->time = curTick;
- req->xc = xc;
+ req->xc = cpuXC->getProxy();
if (cmd < percentReads) {
// read
MemInterface *cacheInterface;
FunctionalMemory *mainMem;
FunctionalMemory *checkMem;
- ExecContext *xc;
+ CPUExecContext *cpuXC;
unsigned size; // size of testing memory region
// set the register.
IntReg getSyscallArg(int i)
{
- return this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
+ return this->cpuXC->readIntReg(AlphaISA::ArgumentReg0 + i);
}
// used to shift args for indirect syscall
void setSyscallArg(int i, IntReg val)
{
- this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
+ this->cpuXC->setIntReg(AlphaISA::ArgumentReg0 + i, val);
}
void setSyscallReturn(int64_t return_value)
const int RegA3 = 19; // only place this is used
if (return_value >= 0) {
// no error
- this->xc->regs.intRegFile[RegA3] = 0;
- this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
+ this->cpuXC->setIntReg(RegA3, 0);
+ this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, return_value);
} else {
// got an error, return details
- this->xc->regs.intRegFile[RegA3] = (IntReg) -1;
- this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
+ this->cpuXC->setIntReg(RegA3, (IntReg) -1);
+ this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, -return_value);
}
}
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
if (req->flags & LOCKED) {
- MiscRegFile *cregs = &req->xc->regs.miscRegs;
- cregs->setReg(TheISA::Lock_Addr_DepTag, req->paddr);
- cregs->setReg(TheISA::Lock_Flag_DepTag, true);
+ req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
+ req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
}
#endif
Fault write(MemReqPtr &req, T &data)
{
#if FULL_SYSTEM && defined(TARGET_ALPHA)
-
- MiscRegFile *cregs;
+ ExecContext *xc;
// If this is a store conditional, act appropriately
if (req->flags & LOCKED) {
- cregs = &req->xc->regs.miscRegs;
+ xc = req->xc;
if (req->flags & UNCACHEABLE) {
// Don't update result register (see stq_c in isa_desc)
req->result = 2;
- req->xc->storeCondFailures = 0;//Needed? [RGD]
+ xc->setStCondFailures(0);//Needed? [RGD]
} else {
- bool lock_flag = cregs->readReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = cregs->readReg(TheISA::Lock_Addr_DepTag);
+ bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
+ Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
req->result = lock_flag;
if (!lock_flag ||
((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- cregs->setReg(TheISA::Lock_Flag_DepTag, false);
- if (((++req->xc->storeCondFailures) % 100000) == 0) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ xc->setStCondFailures(xc->readStCondFailures() + 1);
+ if (((xc->readStCondFailures()) % 100000) == 0) {
std::cerr << "Warning: "
- << req->xc->storeCondFailures
+ << xc->readStCondFailures()
<< " consecutive store conditional failures "
- << "on cpu " << req->xc->cpu_id
+ << "on cpu " << req->xc->readCpuId()
<< std::endl;
}
return NoFault;
}
- else req->xc->storeCondFailures = 0;
+ else xc->setStCondFailures(0);
}
}
// Conditionals would have returned above, and wouldn't fall
// through.
for (int i = 0; i < this->system->execContexts.size(); i++){
- cregs = &this->system->execContexts[i]->regs.miscRegs;
- if ((cregs->readReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
+ xc = this->system->execContexts[i];
+ if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
(req->paddr & ~0xf)) {
- cregs->setReg(TheISA::Lock_Flag_DepTag, false);
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
}
}
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/o3/alpha_cpu.hh"
#include "cpu/o3/alpha_impl.hh"
for (int i = 0; i < AlphaISA::NumIntRegs; ++i)
{
renamed_reg = this->renameMap.lookup(i);
- this->xc->regs.intRegFile[i] = this->regFile.readIntReg(renamed_reg);
+ this->cpuXC->setIntReg(i, this->regFile.readIntReg(renamed_reg));
DPRINTF(FullCPU, "FullCPU: Copying register %i, has data %lli.\n",
renamed_reg, this->regFile.intRegFile[renamed_reg]);
}
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
- this->xc->regs.floatRegFile.d[i] =
- this->regFile.readFloatRegDouble(renamed_reg);
- this->xc->regs.floatRegFile.q[i] =
- this->regFile.readFloatRegInt(renamed_reg);
+ this->cpuXC->setFloatRegDouble(i,
+ this->regFile.readFloatRegDouble(renamed_reg));
+ this->cpuXC->setFloatRegInt(i,
+ this->regFile.readFloatRegInt(renamed_reg));
}
/*
- this->xc->regs.miscRegs.fpcr = this->regFile.miscRegs.fpcr;
- this->xc->regs.miscRegs.uniq = this->regFile.miscRegs.uniq;
- this->xc->regs.miscRegs.lock_flag = this->regFile.miscRegs.lock_flag;
- this->xc->regs.miscRegs.lock_addr = this->regFile.miscRegs.lock_addr;
+ this->cpuXC->regs.miscRegs.fpcr = this->regFile.miscRegs.fpcr;
+ this->cpuXC->regs.miscRegs.uniq = this->regFile.miscRegs.uniq;
+ this->cpuXC->regs.miscRegs.lock_flag = this->regFile.miscRegs.lock_flag;
+ this->cpuXC->regs.miscRegs.lock_addr = this->regFile.miscRegs.lock_addr;
*/
- this->xc->regs.pc = this->rob.readHeadPC();
- this->xc->regs.npc = this->xc->regs.pc+4;
+ this->cpuXC->setPC(this->rob.readHeadPC());
+ this->cpuXC->setNextPC(this->cpuXC->readPC()+4);
- this->xc->func_exe_inst = this->funcExeInst;
+#if !FULL_SYSTEM
+ this->cpuXC->setFuncExeInst(this->funcExeInst);
+#endif
}
// This function will probably mess things up unless the ROB is empty and
DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
"now has data %lli.\n",
renamed_reg, this->regFile.intRegFile[renamed_reg],
- this->xc->regs.intRegFile[i]);
+ this->cpuXC->readIntReg(i));
- this->regFile.setIntReg(renamed_reg, this->xc->regs.intRegFile[i]);
+ this->regFile.setIntReg(renamed_reg, this->cpuXC->readIntReg(i));
}
// Then loop through the floating point registers.
{
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
this->regFile.setFloatRegDouble(renamed_reg,
- this->xc->regs.floatRegFile.d[i]);
+ this->cpuXC->readFloatRegDouble(i));
this->regFile.setFloatRegInt(renamed_reg,
- this->xc->regs.floatRegFile.q[i]);
+ this->cpuXC->readFloatRegInt(i));
}
/*
// Then loop through the misc registers.
- this->regFile.miscRegs.fpcr = this->xc->regs.miscRegs.fpcr;
- this->regFile.miscRegs.uniq = this->xc->regs.miscRegs.uniq;
- this->regFile.miscRegs.lock_flag = this->xc->regs.miscRegs.lock_flag;
- this->regFile.miscRegs.lock_addr = this->xc->regs.miscRegs.lock_addr;
+ this->regFile.miscRegs.fpcr = this->cpuXC->regs.miscRegs.fpcr;
+ this->regFile.miscRegs.uniq = this->cpuXC->regs.miscRegs.uniq;
+ this->regFile.miscRegs.lock_flag = this->cpuXC->regs.miscRegs.lock_flag;
+ this->regFile.miscRegs.lock_addr = this->cpuXC->regs.miscRegs.lock_addr;
*/
// Then finally set the PC and the next PC.
-// regFile.pc = xc->regs.pc;
-// regFile.npc = xc->regs.npc;
-
- this->funcExeInst = this->xc->func_exe_inst;
+// regFile.pc = cpuXC->regs.pc;
+// regFile.npc = cpuXC->regs.npc;
+#if !FULL_SYSTEM
+ this->funcExeInst = this->cpuXC->readFuncExeInst();
+#endif
}
#if FULL_SYSTEM
#endif
#include "sim/root.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/exec_context.hh"
#include "cpu/o3/alpha_dyn_inst.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/cpu.hh"
-#include "cpu/exec_context.hh"
using namespace std;
renameQueue(5, 5),
iewQueue(5, 5),
- xc(NULL),
+ cpuXC(NULL),
globalSeqNum(1),
for (int i = 0; i < this->number_of_threads; ++i) {
#if FULL_SYSTEM
assert(i == 0);
- system->execContexts[i] =
- new ExecContext(this, i, system, itb, dtb, mem);
+ thread[i] = new CPUExecContext(this, 0, system, itb, dtb, mem);
+ system->execContexts[i] = thread[i]->getProxy();
execContexts.push_back(system->execContexts[i]);
#else
DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
"process is %#x",
i, params.workload[i]->prog_entry, thread[i]);
- thread[i] = new ExecContext(this, i, params.workload[i], i);
+ thread[i] = new CPUExecContext(this, i, params.workload[i], i);
}
assert(params.workload[i]->getMemory() != NULL);
assert(mem != NULL);
- execContexts.push_back(thread[i]);
+ execContexts.push_back(thread[i]->getProxy());
#endif // !FULL_SYSTEM
}
// Note that this is a hack so that my code which still uses xc-> will
// still work. I should remove this eventually
-#if FULL_SYSTEM
- xc = system->execContexts[0];
-#else
- xc = thread[0];
-#endif
+ cpuXC = thread[0];
// The stages also need their CPU pointer setup. However this must be
// done at the upper level CPU because they have pointers to the upper
// that it can start properly.
#if FULL_SYSTEM
ExecContext *src_xc = system->execContexts[0];
- TheISA::initCPU(&src_xc->regs, src_xc->cpu_id);
+ TheISA::initCPU(src_xc, src_xc->readCpuId());
#else
- ExecContext *src_xc = thread[0];
+ ExecContext *src_xc = thread[0]->getProxy();
#endif
// First loop through the integer registers.
for (int i = 0; i < TheISA::NumIntRegs; ++i)
{
- regFile.intRegFile[i] = src_xc->regs.intRegFile[i];
+ regFile.intRegFile[i] = src_xc->readIntReg(i);
}
// Then loop through the floating point registers.
for (int i = 0; i < TheISA::NumFloatRegs; ++i)
{
- regFile.floatRegFile[i].d = src_xc->regs.floatRegFile.d[i];
- regFile.floatRegFile[i].q = src_xc->regs.floatRegFile.q[i];
+ regFile.floatRegFile[i].d = src_xc->readFloatRegDouble(i);
+ regFile.floatRegFile[i].q = src_xc->readFloatRegInt(i);
}
/*
// Then loop through the misc registers.
regFile.miscRegs.lock_addr = src_xc->regs.miscRegs.lock_addr;
*/
// Then finally set the PC and the next PC.
- regFile.pc = src_xc->regs.pc;
- regFile.npc = src_xc->regs.npc;
+ regFile.pc = src_xc->readPC();
+ regFile.npc = src_xc->readNextPC();
}
}
#include "base/timebuf.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/o3/comm.hh"
#include "cpu/o3/cpu_policy.hh"
-#include "cpu/exec_context.hh"
#include "sim/process.hh"
#if FULL_SYSTEM
using namespace EV5;
#endif
+class ExecContext;
class FunctionalMemory;
class Process;
bool validDataAddr(Addr addr)
{ return thread[0]->validDataAddr(addr); }
- int getInstAsid() { return thread[0]->asid; }
- int getDataAsid() { return thread[0]->asid; }
+ int getInstAsid() { return thread[0]->getInstAsid(); }
+ int getDataAsid() { return thread[0]->getDataAsid(); }
#endif
public:
/** The temporary exec context to support older accessors. */
- ExecContext *xc;
+ CPUExecContext *cpuXC;
/** Temporary function to get pointer to exec context. */
ExecContext *xcBase()
{
-#if FULL_SYSTEM
- return system->execContexts[0];
-#else
+ return thread[0]->getProxy();
+ }
+
+ CPUExecContext *cpuXCBase()
+ {
return thread[0];
-#endif
}
InstSeqNum globalSeqNum;
AlphaDTB *dtb;
// SWContext *swCtx;
-#else
- std::vector<ExecContext *> thread;
#endif
+ std::vector<CPUExecContext *> thread;
FunctionalMemory *mem;
#include "cpu/pc_event.hh"
#include "sim/debug.hh"
#include "sim/root.hh"
+#include "sim/system.hh"
using namespace std;
bool
PCEventQueue::doService(ExecContext *xc)
{
- Addr pc = xc->regs.pc & ~0x3;
+ Addr pc = xc->readPC() & ~0x3;
int serviced = 0;
range_t range = equal_range(pc);
for (iterator i = range.first; i != range.second; ++i) {
// another event. This for example, prevents two invocations
// of the SkipFuncEvent. Maybe we should have separate PC
// event queues for each processor?
- if (pc != (xc->regs.pc & ~0x3))
+ if (pc != (xc->readPC() & ~0x3))
continue;
DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n",
void
BreakPCEvent::process(ExecContext *xc)
{
- StringWrap name(xc->cpu->name() + ".break_event");
+ StringWrap name(xc->getCpuPtr()->name() + ".break_event");
DPRINTFN("break event %s triggered\n", descr());
debug_break();
if (remove)
#include "base/stats/events.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/profile.hh"
ExecContext *xc = execContexts[i];
// initialize CPU, including PC
- TheISA::initCPU(&xc->regs, xc->cpu_id);
+ TheISA::initCPU(xc, xc->readCpuId());
}
#endif
}
}
SimpleCPU::SimpleCPU(Params *p)
- : BaseCPU(p), tickEvent(this, p->width), xc(NULL),
+ : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL),
cacheCompletionEvent(this)
{
_status = Idle;
#if FULL_SYSTEM
- xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
+ cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
#else
- xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0);
+ cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process,
+ /* asid */ 0);
#endif // !FULL_SYSTEM
+ xcProxy = cpuXC->getProxy();
icacheInterface = p->icache_interface;
dcacheInterface = p->dcache_interface;
memReq = new MemReq();
- memReq->xc = xc;
+ memReq->xc = xcProxy;
memReq->asid = 0;
memReq->data = new uint8_t[64];
lastIcacheStall = 0;
lastDcacheStall = 0;
- execContexts.push_back(xc);
+ execContexts.push_back(xcProxy);
}
SimpleCPU::~SimpleCPU()
SimpleCPU::activateContext(int thread_num, int delay)
{
assert(thread_num == 0);
- assert(xc);
+ assert(cpuXC);
assert(_status == Idle);
notIdleFraction++;
SimpleCPU::suspendContext(int thread_num)
{
assert(thread_num == 0);
- assert(xc);
+ assert(cpuXC);
assert(_status == Running);
notIdleFraction--;
SERIALIZE_ENUM(_status);
SERIALIZE_SCALAR(inst);
nameOut(os, csprintf("%s.xc", name()));
- xc->serialize(os);
+ cpuXC->serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
nameOut(os, csprintf("%s.cacheCompletionEvent", name()));
BaseCPU::unserialize(cp, section);
UNSERIALIZE_ENUM(_status);
UNSERIALIZE_SCALAR(inst);
- xc->unserialize(cp, csprintf("%s.xc", section));
+ cpuXC->unserialize(cp, csprintf("%s.xc", section));
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
cacheCompletionEvent
.unserialize(cp, csprintf("%s.cacheCompletionEvent", section));
memReq->reset(src & ~(blk_size - 1), blk_size);
// translate to physical address
- Fault fault = xc->translateDataReadReq(memReq);
+ Fault fault = cpuXC->translateDataReadReq(memReq);
assert(fault != AlignmentFault);
if (fault == NoFault) {
- xc->copySrcAddr = src;
- xc->copySrcPhysAddr = memReq->paddr + offset;
+ cpuXC->copySrcAddr = src;
+ cpuXC->copySrcPhysAddr = memReq->paddr + offset;
} else {
- xc->copySrcAddr = 0;
- xc->copySrcPhysAddr = 0;
+ cpuXC->copySrcAddr = 0;
+ cpuXC->copySrcPhysAddr = 0;
}
return fault;
}
// Only support block sizes of 64 atm.
assert(blk_size == 64);
uint8_t data[blk_size];
- //assert(xc->copySrcAddr);
+ //assert(cpuXC->copySrcAddr);
int offset = dest & (blk_size - 1);
// Make sure block doesn't span page
memReq->reset(dest & ~(blk_size -1), blk_size);
// translate to physical address
- Fault fault = xc->translateDataWriteReq(memReq);
+ Fault fault = cpuXC->translateDataWriteReq(memReq);
assert(fault != AlignmentFault);
if (fault == NoFault) {
Addr dest_addr = memReq->paddr + offset;
// Need to read straight from memory since we have more than 8 bytes.
- memReq->paddr = xc->copySrcPhysAddr;
- xc->mem->read(memReq, data);
+ memReq->paddr = cpuXC->copySrcPhysAddr;
+ cpuXC->mem->read(memReq, data);
memReq->paddr = dest_addr;
- xc->mem->write(memReq, data);
+ cpuXC->mem->write(memReq, data);
if (dcacheInterface) {
memReq->cmd = Copy;
memReq->completionEvent = NULL;
- memReq->paddr = xc->copySrcPhysAddr;
+ memReq->paddr = cpuXC->copySrcPhysAddr;
memReq->dest = dest_addr;
memReq->size = 64;
memReq->time = curTick;
SimpleCPU::read(Addr addr, T &data, unsigned flags)
{
if (status() == DcacheMissStall || status() == DcacheMissSwitch) {
- Fault fault = xc->read(memReq,data);
+ Fault fault = cpuXC->read(memReq,data);
if (traceData) {
traceData->setAddr(addr);
memReq->reset(addr, sizeof(T), flags);
// translate to physical address
- Fault fault = xc->translateDataReadReq(memReq);
+ Fault fault = cpuXC->translateDataReadReq(memReq);
// if we have a cache, do cache access too
if (fault == NoFault && dcacheInterface) {
_status = DcacheMissStall;
} else {
// do functional access
- fault = xc->read(memReq, data);
+ fault = cpuXC->read(memReq, data);
}
} else if(fault == NoFault) {
// do functional access
- fault = xc->read(memReq, data);
+ fault = cpuXC->read(memReq, data);
}
memReq->reset(addr, sizeof(T), flags);
// translate to physical address
- Fault fault = xc->translateDataWriteReq(memReq);
+ Fault fault = cpuXC->translateDataWriteReq(memReq);
// do functional access
if (fault == NoFault)
- fault = xc->write(memReq, data);
+ fault = cpuXC->write(memReq, data);
if (fault == NoFault && dcacheInterface) {
memReq->cmd = Write;
Addr
SimpleCPU::dbg_vtophys(Addr addr)
{
- return vtophys(xc, addr);
+ return vtophys(xcProxy, addr);
}
#endif // FULL_SYSTEM
{
BaseCPU::post_interrupt(int_num, index);
- if (xc->status() == ExecContext::Suspended) {
+ if (cpuXC->status() == ExecContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
- xc->activate();
+ cpuXC->activate();
}
}
#endif // FULL_SYSTEM
Fault fault = NoFault;
#if FULL_SYSTEM
- if (checkInterrupts && check_interrupts() && !xc->inPalMode() &&
+ if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() &&
status() != IcacheMissComplete) {
int ipl = 0;
int summary = 0;
checkInterrupts = false;
- if (xc->readMiscReg(IPR_SIRR)) {
+ if (cpuXC->readMiscReg(IPR_SIRR)) {
for (int i = INTLEVEL_SOFTWARE_MIN;
i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (xc->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
+ if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
// See table 4-19 of 21164 hardware reference
ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
summary |= (ULL(1) << i);
}
}
- uint64_t interrupts = xc->cpu->intr_status();
+ uint64_t interrupts = cpuXC->cpu->intr_status();
for (int i = INTLEVEL_EXTERNAL_MIN;
i < INTLEVEL_EXTERNAL_MAX; i++) {
if (interrupts & (ULL(1) << i)) {
}
}
- if (xc->readMiscReg(IPR_ASTRR))
+ if (cpuXC->readMiscReg(IPR_ASTRR))
panic("asynchronous traps not implemented\n");
- if (ipl && ipl > xc->readMiscReg(IPR_IPLR)) {
- xc->setMiscReg(IPR_ISR, summary);
- xc->setMiscReg(IPR_INTID, ipl);
- xc->ev5_trap(InterruptFault);
+ if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) {
+ cpuXC->setMiscReg(IPR_ISR, summary);
+ cpuXC->setMiscReg(IPR_INTID, ipl);
+ cpuXC->ev5_trap(InterruptFault);
DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- xc->readMiscReg(IPR_IPLR), ipl, summary);
+ cpuXC->readMiscReg(IPR_IPLR), ipl, summary);
}
}
#endif
// maintain $r0 semantics
- xc->regs.intRegFile[ZeroReg] = 0;
+ cpuXC->setIntReg(ZeroReg, 0);
#ifdef TARGET_ALPHA
- xc->regs.floatRegFile.d[ZeroReg] = 0.0;
+ cpuXC->setFloatRegDouble(ZeroReg, 0.0);
#endif // TARGET_ALPHA
if (status() == IcacheMissComplete) {
#endif
memReq->cmd = Read;
- memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t),
- IFETCH_FLAGS(xc->regs.pc));
+ memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
+ IFETCH_FLAGS(cpuXC->readPC()));
- fault = xc->translateInstReq(memReq);
+ fault = cpuXC->translateInstReq(memReq);
if (fault == NoFault)
- fault = xc->mem->read(memReq, inst);
+ fault = cpuXC->mem->read(memReq, inst);
if (icacheInterface && fault == NoFault) {
memReq->completionEvent = NULL;
inst = gtoh(inst);
curStaticInst = StaticInst::decode(inst);
- traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst,
- xc->regs.pc);
+ traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst,
+ cpuXC->readPC());
#if FULL_SYSTEM
- xc->setInst(inst);
+ cpuXC->setInst(inst);
#endif // FULL_SYSTEM
- xc->func_exe_inst++;
+ cpuXC->func_exe_inst++;
fault = curStaticInst->execute(this, traceData);
#if FULL_SYSTEM
- if (xc->fnbin) {
- assert(xc->kernelStats);
- system->kernelBinning->execute(xc, inst);
+ if (system->kernelBinning->fnbin) {
+ assert(kernelStats);
+ system->kernelBinning->execute(xcProxy, inst);
}
- if (xc->profile) {
- bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
- xc->profilePC = usermode ? 1 : xc->regs.pc;
- ProfileNode *node = xc->profile->consume(xc, inst);
+ if (cpuXC->profile) {
+ bool usermode =
+ (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
+ cpuXC->profilePC = usermode ? 1 : cpuXC->readPC();
+ ProfileNode *node = cpuXC->profile->consume(xcProxy, inst);
if (node)
- xc->profileNode = node;
+ cpuXC->profileNode = node;
}
#endif
traceData->finalize();
}
- traceFunctions(xc->regs.pc);
+ traceFunctions(cpuXC->readPC());
} // if (fault == NoFault)
if (fault != NoFault) {
#if FULL_SYSTEM
- xc->ev5_trap(fault);
+ cpuXC->ev5_trap(fault);
#else // !FULL_SYSTEM
- fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc);
+ fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
#endif // FULL_SYSTEM
}
else {
// go to the next instruction
- xc->regs.pc = xc->regs.npc;
- xc->regs.npc += sizeof(MachInst);
+ cpuXC->setPC(cpuXC->readNextPC());
+ cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
}
#if FULL_SYSTEM
Addr oldpc;
do {
- oldpc = xc->regs.pc;
- system->pcEventQueue.service(xc);
- } while (oldpc != xc->regs.pc);
+ oldpc = cpuXC->readPC();
+ system->pcEventQueue.service(xcProxy);
+ } while (oldpc != cpuXC->readPC());
#endif
assert(status() == Running ||
#include "base/statistics.hh"
#include "config/full_system.hh"
#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/pc_event.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/static_inst.hh"
#endif // FULL_SYSTEM
+class ExecContext;
class MemInterface;
class Checkpoint;
public:
// execution context
- ExecContext *xc;
+ CPUExecContext *cpuXC;
+
+ ExecContext *xcProxy;
void switchOut(Sampler *s);
void takeOverFrom(BaseCPU *oldCPU);
uint64_t readIntReg(const StaticInst *si, int idx)
{
- return xc->readIntReg(si->srcRegIdx(idx));
+ return cpuXC->readIntReg(si->srcRegIdx(idx));
}
float readFloatRegSingle(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegSingle(reg_idx);
+ return cpuXC->readFloatRegSingle(reg_idx);
}
double readFloatRegDouble(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegDouble(reg_idx);
+ return cpuXC->readFloatRegDouble(reg_idx);
}
uint64_t readFloatRegInt(const StaticInst *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return xc->readFloatRegInt(reg_idx);
+ return cpuXC->readFloatRegInt(reg_idx);
}
void setIntReg(const StaticInst *si, int idx, uint64_t val)
{
- xc->setIntReg(si->destRegIdx(idx), val);
+ cpuXC->setIntReg(si->destRegIdx(idx), val);
}
void setFloatRegSingle(const StaticInst *si, int idx, float val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegSingle(reg_idx, val);
+ cpuXC->setFloatRegSingle(reg_idx, val);
}
void setFloatRegDouble(const StaticInst *si, int idx, double val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegDouble(reg_idx, val);
+ cpuXC->setFloatRegDouble(reg_idx, val);
}
void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- xc->setFloatRegInt(reg_idx, val);
+ cpuXC->setFloatRegInt(reg_idx, val);
}
- uint64_t readPC() { return xc->readPC(); }
- void setNextPC(uint64_t val) { xc->setNextPC(val); }
+ uint64_t readPC() { return cpuXC->readPC(); }
+ void setNextPC(uint64_t val) { cpuXC->setNextPC(val); }
MiscReg readMiscReg(int misc_reg)
{
- return xc->readMiscReg(misc_reg);
+ return cpuXC->readMiscReg(misc_reg);
}
MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
{
- return xc->readMiscRegWithEffect(misc_reg, fault);
+ return cpuXC->readMiscRegWithEffect(misc_reg, fault);
}
Fault setMiscReg(int misc_reg, const MiscReg &val)
{
- return xc->setMiscReg(misc_reg, val);
+ return cpuXC->setMiscReg(misc_reg, val);
}
Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
{
- return xc->setMiscRegWithEffect(misc_reg, val);
+ return cpuXC->setMiscRegWithEffect(misc_reg, val);
}
#if FULL_SYSTEM
- Fault hwrei() { return xc->hwrei(); }
- int readIntrFlag() { return xc->readIntrFlag(); }
- void setIntrFlag(int val) { xc->setIntrFlag(val); }
- bool inPalMode() { return xc->inPalMode(); }
- void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
- bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
+ Fault hwrei() { return cpuXC->hwrei(); }
+ int readIntrFlag() { return cpuXC->readIntrFlag(); }
+ void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
+ bool inPalMode() { return cpuXC->inPalMode(); }
+ void ev5_trap(Fault fault) { cpuXC->ev5_trap(fault); }
+ bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
#else
- void syscall() { xc->syscall(); }
+ void syscall() { cpuXC->syscall(); }
#endif
- bool misspeculating() { return xc->misspeculating(); }
- ExecContext *xcBase() { return xc; }
+ bool misspeculating() { return cpuXC->misspeculating(); }
+ ExecContext *xcBase() { return xcProxy; }
};
#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
case TSDEV_CC_MISC:
*(uint64_t*)data = (ipint << 8) & 0xF |
(itint << 4) & 0xF |
- (xc->cpu_id & 0x3);
+ (xc->readCpuId() & 0x3);
return NoFault;
case TSDEV_CC_AAR0:
case TSDEV_CC_AAR1:
*
*/
+#include "arch/isa_traits.hh"
#include "base/loader/symtab.hh"
#include "cpu/exec_context.hh"
#include "kern/freebsd/freebsd_system.hh"
#include "mem/functional/memory_control.hh"
#include "mem/functional/physical.hh"
#include "sim/builder.hh"
-#include "arch/isa_traits.hh"
#include "sim/byteswap.hh"
#include "targetarch/vtophys.hh"
Addr ppc_paddr = 0;
Addr timer_paddr = 0;
- ppc_vaddr = (Addr)xc->regs.intRegFile[ArgumentReg1];
- timer_vaddr = (Addr)xc->regs.intRegFile[ArgumentReg2];
+ ppc_vaddr = (Addr)xc->readIntReg(ArgumentReg1);
+ timer_vaddr = (Addr)xc->readIntReg(ArgumentReg2);
ppc_paddr = vtophys(physmem, ppc_vaddr);
timer_paddr = vtophys(physmem, timer_vaddr);
FreebsdSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
{
SkipFuncEvent::process(xc);
- ((FreebsdSystem *)xc->system)->doCalibrateClocks(xc);
+ ((FreebsdSystem *)xc->getSystemPtr())->doCalibrateClocks(xc);
}
const char *modestr[] = { "kernel", "user", "idle", "interrupt" };
-Statistics::Statistics(ExecContext *context)
- : xc(context), idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
+Statistics::Statistics(System *system)
+ : idleProcess((Addr)-1), themode(kernel), lastModeTick(0),
iplLast(0), iplLastTick(0)
{
- bin_int = xc->system->params->bin_int;
+ bin_int = system->params->bin_int;
}
void
}
void
-Statistics::setIdleProcess(Addr idlepcbb)
+Statistics::setIdleProcess(Addr idlepcbb, ExecContext *xc)
{
assert(themode == kernel || themode == interrupt);
idleProcess = idlepcbb;
themode = idle;
- changeMode(themode);
+ changeMode(themode, xc);
}
void
-Statistics::changeMode(cpu_mode newmode)
+Statistics::changeMode(cpu_mode newmode, ExecContext *xc)
{
_mode[newmode]++;
_modeGood[newmode]++;
_modeTicks[themode] += curTick - lastModeTick;
- xc->system->kernelBinning->changeMode(newmode);
+ xc->getSystemPtr()->kernelBinning->changeMode(newmode);
lastModeTick = curTick;
themode = newmode;
}
void
-Statistics::mode(cpu_mode newmode)
+Statistics::mode(cpu_mode newmode, ExecContext *xc)
{
Addr pcbb = xc->readMiscReg(AlphaISA::IPR_PALtemp23);
if (bin_int == false && newmode == interrupt)
newmode = kernel;
- changeMode(newmode);
+ changeMode(newmode, xc);
}
void
-Statistics::context(Addr oldpcbb, Addr newpcbb)
+Statistics::context(Addr oldpcbb, Addr newpcbb, ExecContext *xc)
{
assert(themode != user);
_swap_context++;
- changeMode(newpcbb == idleProcess ? idle : kernel);
+ changeMode(newpcbb == idleProcess ? idle : kernel, xc);
}
void
-Statistics::callpal(int code)
+Statistics::callpal(int code, ExecContext *xc)
{
if (!PAL::name(code))
return;
switch (code) {
case PAL::callsys: {
- int number = xc->regs.intRegFile[0];
+ int number = xc->readIntReg(0);
if (SystemCalls<Tru64>::validSyscallNumber(number)) {
int cvtnum = SystemCalls<Tru64>::convert(number);
_syscall[cvtnum]++;
} break;
case PAL::swpctx:
- if (xc->system->kernelBinning)
- xc->system->kernelBinning->palSwapContext(xc);
+ if (xc->getSystemPtr()->kernelBinning)
+ xc->getSystemPtr()->kernelBinning->palSwapContext(xc);
break;
}
}
private:
std::string myname;
- ExecContext *xc;
Addr idleProcess;
cpu_mode themode;
Tick lastModeTick;
bool bin_int;
- void changeMode(cpu_mode newmode);
+ void changeMode(cpu_mode newmode, ExecContext *xc);
private:
Stats::Scalar<> _arm;
Tick iplLastTick;
public:
- Statistics(ExecContext *context);
+ Statistics(System *system);
const std::string name() const { return myname; }
void regStats(const std::string &name);
else _faults[fault->id]++;
}// FIXME: When there are no generic system fault objects, this will go back to _faults[fault]++; }
void swpipl(int ipl);
- void mode(cpu_mode newmode);
- void context(Addr oldpcbb, Addr newpcbb);
- void callpal(int code);
+ void mode(cpu_mode newmode, ExecContext *xc);
+ void context(Addr oldpcbb, Addr newpcbb, ExecContext *xc);
+ void callpal(int code, ExecContext *xc);
- void setIdleProcess(Addr idle);
+ void setIdleProcess(Addr idle, ExecContext *xc);
public:
virtual void serialize(std::ostream &os);
uint8_t *loops_per_jiffy =
physmem->dma_addr(paddr, sizeof(uint32_t));
- Tick cpuFreq = xc->cpu->frequency();
+ Tick cpuFreq = xc->getCpuPtr()->frequency();
Tick intrFreq = platform->intrFrequency();
*(uint32_t *)loops_per_jiffy =
(uint32_t)((cpuFreq / intrFreq) * 0.9988);
{
SkipFuncEvent::process(xc);
// calculate and set loops_per_jiffy
- ((LinuxSystem *)xc->system)->setDelayLoop(xc);
+ ((LinuxSystem *)xc->getSystemPtr())->setDelayLoop(xc);
}
void
{
if (DTRACE(DebugPrintf)) {
if (!raw) {
- StringWrap name(xc->system->name() + ".dprintk");
+ StringWrap name(xc->getSystemPtr()->name() + ".dprintk");
DPRINTFN("");
}
* thread_info struct. So we can get the address by masking off
* the lower 14 bits.
*/
- current = xc->regs.intRegFile[TheISA::StackPointerReg] & ~0x3fff;
+ current = xc->readIntReg(TheISA::StackPointerReg) & ~0x3fff;
return VPtr<thread_info>(xc, current);
}
void
SkipFuncEvent::process(ExecContext *xc)
{
- Addr newpc = xc->regs.intRegFile[ReturnAddressReg];
+ Addr newpc = xc->readIntReg(ReturnAddressReg);
DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
- xc->regs.pc, newpc);
+ xc->readPC(), newpc);
- xc->regs.pc = newpc;
- xc->regs.npc = xc->regs.pc + sizeof(MachInst);
+ xc->setPC(newpc);
+ xc->setNextPC(xc->readPC() + sizeof(TheISA::MachInst));
- BranchPred *bp = xc->cpu->getBranchPred();
+ BranchPred *bp = xc->getCpuPtr()->getBranchPred();
if (bp != NULL) {
- bp->popRAS(xc->thread_num);
+ bp->popRAS(xc->getThreadNum());
}
}
if (xc->misspeculating())
return;
- xc->system->kernelBinning->call(xc, mybin);
+ xc->getSystemPtr()->kernelBinning->call(xc, mybin);
}
void
IdleStartEvent::process(ExecContext *xc)
{
- xc->kernelStats->setIdleProcess(xc->readMiscReg(AlphaISA::IPR_PALtemp23));
+ xc->getCpuPtr()->kernelStats->setIdleProcess(
+ xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc);
remove();
}
void
InterruptStartEvent::process(ExecContext *xc)
{
- xc->kernelStats->mode(Kernel::interrupt);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::interrupt, xc);
}
void
{
// We go back to kernel, if we are user, inside the rti
// pal code we will get switched to user because of the ICM write
- xc->kernelStats->mode(Kernel::kernel);
+ xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc);
}
addr, m.m_data, m.m_len);
char *buffer = new char[m.m_len];
CopyOut(xc, buffer, m.m_data, m.m_len);
- Trace::dataDump(curTick, xc->system->name(), (uint8_t *)buffer,
+ Trace::dataDump(curTick, xc->getSystemPtr()->name(), (uint8_t *)buffer,
m.m_len);
delete [] buffer;
// just pass basep through uninterpreted.
TypedBufferArg<int64_t> basep(tgt_basep);
- basep.copyIn(xc->mem);
+ basep.copyIn(xc->getMemPtr());
long host_basep = (off_t)htog((int64_t)*basep);
int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
tgt_dp->d_reclen = tgt_bufsize;
tgt_dp->d_namlen = namelen;
strcpy(tgt_dp->d_name, host_dp->d_name);
- tgt_dp.copyOut(xc->mem);
+ tgt_dp.copyOut(xc->getMemPtr());
tgt_buf_ptr += tgt_bufsize;
host_buf_ptr += host_dp->d_reclen;
delete [] host_buf;
*basep = htog((int64_t)host_basep);
- basep.copyOut(xc->mem);
+ basep.copyOut(xc->getMemPtr());
return tgt_buf_ptr - tgt_buf;
#endif
ExecContext *xc)
{
using TheISA::RegFile;
- RegFile *regs = &xc->regs;
TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
- sc.copyIn(xc->mem);
+ sc.copyIn(xc->getMemPtr());
// Restore state from sigcontext structure.
// Note that we'll advance PC <- NPC before the end of the cycle,
// so we need to restore the desired PC into NPC.
// The current regs->pc will get clobbered.
- regs->npc = htog(sc->sc_pc);
+ xc->setNextPC(htog(sc->sc_pc));
for (int i = 0; i < 31; ++i) {
- regs->intRegFile[i] = htog(sc->sc_regs[i]);
- regs->floatRegFile.q[i] = htog(sc->sc_fpregs[i]);
+ xc->setIntReg(i, htog(sc->sc_regs[i]));
+ xc->setFloatRegInt(i, htog(sc->sc_fpregs[i]));
}
xc->setMiscReg(TheISA::Fpcr_DepTag, htog(sc->sc_fpcr));
elp->si_phz = htog(clk_hz);
elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch?
elp->si_max_procs = htog(process->numCpus());
- elp.copyOut(xc->mem);
+ elp.copyOut(xc->getMemPtr());
return 0;
}
{
TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
- argp.copyIn(xc->mem);
+ argp.copyIn(xc->getMemPtr());
// if the user chose an address, just let them have it. Otherwise
// pick one for them.
int stack_size = (htog(argp->rsize) + htog(argp->ysize) +
htog(argp->gsize));
process->next_thread_stack_base -= stack_size;
- argp.copyOut(xc->mem);
+ argp.copyOut(xc->getMemPtr());
}
return 0;
TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
- attrp.copyIn(xc->mem);
+ attrp.copyIn(xc->getMemPtr());
if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) {
cerr << "nxm_task_init: thread library version mismatch! "
config->nxm_slot_state = htog(slot_state_addr);
config->nxm_rad[0] = htog(rad_state_addr);
- config.copyOut(xc->mem);
+ config.copyOut(xc->getMemPtr());
// initialize the slot_state array and copy it out
TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
(i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
}
- slot_state.copyOut(xc->mem);
+ slot_state.copyOut(xc->getMemPtr());
// same for the per-RAD "shared" struct. Note that we need to
// allocate extra bytes for the per-VP array which is embedded at
}
}
- rad_state.copyOut(xc->mem);
+ rad_state.copyOut(xc->getMemPtr());
//
// copy pointer to shared config area out to user
//
*configptr_ptr = htog(config_addr);
- configptr_ptr.copyOut(xc->mem);
+ configptr_ptr.copyOut(xc->getMemPtr());
// Register this as a valid address range with the process
process->nxm_start = base_addr;
init_exec_context(ExecContext *ec,
Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
{
- memset(&ec->regs, 0, sizeof(ec->regs));
+ ec->clearArchRegs();
- ec->regs.intRegFile[TheISA::ArgumentReg0] = gtoh(attrp->registers.a0);
- ec->regs.intRegFile[27/*t12*/] = gtoh(attrp->registers.pc);
- ec->regs.intRegFile[TheISA::StackPointerReg] = gtoh(attrp->registers.sp);
+ ec->setIntReg(TheISA::ArgumentReg0, gtoh(attrp->registers.a0));
+ ec->setIntReg(27/*t12*/, gtoh(attrp->registers.pc));
+ ec->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp));
ec->setMiscReg(TheISA::Uniq_DepTag, uniq_val);
- ec->regs.pc = gtoh(attrp->registers.pc);
- ec->regs.npc = gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst);
+ ec->setPC(gtoh(attrp->registers.pc));
+ ec->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst));
ec->activate();
}
int thread_index = xc->getSyscallArg(2);
// get attribute args
- attrp.copyIn(xc->mem);
+ attrp.copyIn(xc->getMemPtr());
if (gtoh(attrp->version) != NXM_LIB_VERSION) {
cerr << "nxm_thread_create: thread library version mismatch! "
TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
rad_state_size);
- rad_state.copyIn(xc->mem);
+ rad_state.copyIn(xc->getMemPtr());
uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
// This is supposed to be a port number. Make something up.
*kidp = htog(99);
- kidp.copyOut(xc->mem);
+ kidp.copyOut(xc->getMemPtr());
return 0;
} else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {
ssp->nxm_u.pth_id = attrp->pthid;
ssp->nxm_u.nxm_active = htog(uniq_val | 1);
- rad_state.copyOut(xc->mem);
+ rad_state.copyOut(xc->getMemPtr());
Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
int slot_state_size =
slot_state(slot_state_addr,
slot_state_size);
- slot_state.copyIn(xc->mem);
+ slot_state.copyIn(xc->getMemPtr());
if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
cerr << "nxm_thread_createFunc: requested VP slot "
// doesn't work anyway
slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
- slot_state.copyOut(xc->mem);
+ slot_state.copyOut(xc->getMemPtr());
// Find a free simulator execution context.
for (int i = 0; i < process->numCpus(); ++i) {
// and get away with just sticking the thread index
// here.
*kidp = htog(thread_index);
- kidp.copyOut(xc->mem);
+ kidp.copyOut(xc->getMemPtr());
return 0;
}
uint64_t action = xc->getSyscallArg(3);
uint64_t usecs = xc->getSyscallArg(4);
- cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs
- << " " << flags << " " << action << " " << usecs << endl;
+ cout << xc->getCpuPtr()->name() << ": nxm_thread_block " << tid << " "
+ << secs << " " << flags << " " << action << " " << usecs << endl;
return 0;
}
uint64_t usecs = xc->getSyscallArg(3);
uint64_t flags = xc->getSyscallArg(4);
- BaseCPU *cpu = xc->cpu;
+ BaseCPU *cpu = xc->getCpuPtr();
cout << cpu->name() << ": nxm_block "
<< hex << uaddr << dec << " " << val
{
Addr uaddr = xc->getSyscallArg(0);
- cout << xc->cpu->name() << ": nxm_unblock "
+ cout << xc->getCpuPtr()->name() << ": nxm_unblock "
<< hex << uaddr << dec << endl;
return 0;
{
TypedBufferArg<uint64_t> lockp(uaddr);
- lockp.copyIn(xc->mem);
+ lockp.copyIn(xc->getMemPtr());
if (gtoh(*lockp) == 0) {
// lock is free: grab it
*lockp = htog(1);
- lockp.copyOut(xc->mem);
+ lockp.copyOut(xc->getMemPtr());
} else {
// lock is busy: disable until free
process->waitList.push_back(Process::WaitRec(uaddr, xc));
{
TypedBufferArg<uint64_t> lockp(uaddr);
- lockp.copyIn(xc->mem);
+ lockp.copyIn(xc->getMemPtr());
assert(*lockp != 0);
// Check for a process waiting on the lock.
// clear lock field if no waiting context is taking over the lock
if (num_waiting == 0) {
*lockp = 0;
- lockp.copyOut(xc->mem);
+ lockp.copyOut(xc->getMemPtr());
}
}
Addr uaddr = xc->getSyscallArg(0);
TypedBufferArg<uint64_t> lockp(uaddr);
- lockp.copyIn(xc->mem);
+ lockp.copyIn(xc->getMemPtr());
if (gtoh(*lockp) == 0) {
// lock is free: grab it
*lockp = htog(1);
- lockp.copyOut(xc->mem);
+ lockp.copyOut(xc->getMemPtr());
return 0;
} else {
return 1;
TypedBufferArg<uint64_t> lockp(lock_addr);
// user is supposed to acquire lock before entering
- lockp.copyIn(xc->mem);
+ lockp.copyIn(xc->getMemPtr());
assert(gtoh(*lockp) != 0);
m5_unlock_mutex(lock_addr, process, xc);
// annotation for vmunix::badaddr in:
// simos/simulation/apps/tcl/osf/tlaser.tcl
- uint64_t a0 = xc->regs.intRegFile[ArgumentReg0];
+ uint64_t a0 = xc->readIntReg(ArgumentReg0);
if (!TheISA::IsK0Seg(a0) ||
- xc->memctrl->badaddr(TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) {
+ xc->getSystemPtr()->memctrl->badaddr(
+ TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) {
DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0);
- xc->regs.intRegFile[ReturnValueReg] = 0x1;
+ xc->setIntReg(ReturnValueReg, 0x1);
SkipFuncEvent::process(xc);
}
else
PrintfEvent::process(ExecContext *xc)
{
if (DTRACE(Printf)) {
- DebugOut() << curTick << ": " << xc->cpu->name() << ": ";
+ DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
AlphaArguments args(xc);
tru64::Printf(args);
{
if (DTRACE(DebugPrintf)) {
if (!raw)
- DebugOut() << curTick << ": " << xc->cpu->name() << ": ";
+ DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
AlphaArguments args(xc);
tru64::Printf(args);
#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
+#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/smt.hh"
#include "encumbered/cpu/full/thread.hh"
init_regs = new RegFile;
memset(init_regs, 0, sizeof(RegFile));
+ cpuXC = new CPUExecContext(init_regs);
+
// initialize first 3 fds (stdin, stdout, stderr)
fd_map[STDIN_FILENO] = stdin_fd;
fd_map[STDOUT_FILENO] = stdout_fd;
if (myIndex == 0) {
// copy process's initial regs struct
- xc->regs = *init_regs;
+ xc->copyArchRegs(cpuXC->getProxy());
}
// return CPU number to caller and increment available CPU count
{
num_syscalls++;
- int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
+ int64_t callnum = xc->readIntReg(ReturnValueReg);
SyscallDesc *desc = getDesc(callnum);
if (desc == NULL)
#include "base/statistics.hh"
#include "base/trace.hh"
+class CPUExecContext;
class ExecContext;
class FunctionalMemory;
class SyscallDesc;
std::list<WaitRec> waitList;
RegFile *init_regs; // initial register contents
+ CPUExecContext *cpuXC; // XC to hold the init_regs
Addr text_base; // text (code) segment base
unsigned text_size; // text (code) size in bytes
void
arm(ExecContext *xc)
{
- xc->kernelStats->arm();
+ xc->getCpuPtr()->kernelStats->arm();
}
void
return;
xc->suspend();
- xc->kernelStats->quiesce();
+ xc->getCpuPtr()->kernelStats->quiesce();
}
void
ivlb(ExecContext *xc)
{
- xc->kernelStats->ivlb();
+ xc->getCpuPtr()->kernelStats->ivlb();
}
void
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
- xc->system->kernelSymtab->insert(addr,symbol);
+ xc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
}
void
uint64_t
readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset)
{
- const string &file = xc->cpu->system->params->readfile;
+ const string &file = xc->getCpuPtr()->system->params->readfile;
if (file.empty()) {
return ULL(0);
}
SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
{
DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
- xc->cpu->name(), name);
+ xc->getCpuPtr()->name(), name);
SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
- xc->cpu->name(), name, retval.value());
+ xc->getCpuPtr()->name(), name, retval.value());
if (!(flags & SyscallDesc::SuppressReturnValue))
xc->setSyscallReturn(retval);
int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
if (bytes_read != -1)
- bufArg.copyOut(xc->mem);
+ bufArg.copyOut(xc->getMemPtr());
return bytes_read;
}
int nbytes = xc->getSyscallArg(2);
BufferArg bufArg(xc->getSyscallArg(1), nbytes);
- bufArg.copyIn(xc->mem);
+ bufArg.copyIn(xc->getMemPtr());
int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
strncpy((char *)name.bufferPtr(), hostname, name_len);
- name.copyOut(xc->mem);
+ name.copyOut(xc->getMemPtr());
return 0;
}
{
string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return (TheISA::IntReg)-EFAULT;
int result = unlink(path.c_str());
{
string old_name;
- if (xc->mem->readString(old_name, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(old_name, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
string new_name;
- if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != NoFault)
+ if (xc->getMemPtr()->readString(new_name, xc->getSyscallArg(1)) != NoFault)
return -EFAULT;
int64_t result = rename(old_name.c_str(), new_name.c_str());
{
string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
off_t length = xc->getSyscallArg(1);
{
string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
/* XXX endianess */
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
if (path == "/dev/sysdev0") {
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
uint32_t mode = xc->getSyscallArg(1);
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct stat hostBuf;
if (result < 0)
return errno;
- OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
if (result < 0)
return errno;
- OS::copyOutStat64Buf(xc->mem, fd, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->getMemPtr(), fd, xc->getSyscallArg(1), &hostBuf);
return 0;
}
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct stat hostBuf;
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
#if BSD_HOST
if (result < 0)
return -errno;
- OS::copyOutStat64Buf(xc->mem, -1, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStat64Buf(xc->getMemPtr(), -1, xc->getSyscallArg(1), &hostBuf);
return 0;
}
if (result < 0)
return -errno;
- OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
struct statfs hostBuf;
if (result < 0)
return errno;
- OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
if (result < 0)
return errno;
- OS::copyOutStatfsBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+ OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
return 0;
}
for (int i = 0; i < count; ++i)
{
typename OS::tgt_iovec tiov;
- xc->mem->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec),
+ xc->getMemPtr()->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec),
&tiov, sizeof(typename OS::tgt_iovec));
hiov[i].iov_len = gtoh(tiov.iov_len);
hiov[i].iov_base = new char [hiov[i].iov_len];
- xc->mem->access(Read, gtoh(tiov.iov_base),
+ xc->getMemPtr()->access(Read, gtoh(tiov.iov_base),
hiov[i].iov_base, hiov[i].iov_len);
}
break;
}
- rlp.copyOut(xc->mem);
+ rlp.copyOut(xc->getMemPtr());
return 0;
}
tp->tv_sec = htog(tp->tv_sec);
tp->tv_usec = htog(tp->tv_usec);
- tp.copyOut(xc->mem);
+ tp.copyOut(xc->getMemPtr());
return 0;
}
{
std::string path;
- if (xc->mem->readString(path, xc->getSyscallArg(0)) != NoFault)
+ if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
return -EFAULT;
TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
- tp.copyIn(xc->mem);
+ tp.copyIn(xc->getMemPtr());
struct timeval hostTimeval[2];
for (int i = 0; i < 2; ++i)
rup->ru_nvcsw = 0;
rup->ru_nivcsw = 0;
- rup.copyOut(xc->mem);
+ rup.copyOut(xc->getMemPtr());
return 0;
}