diff options
Diffstat (limited to 'src/cpu/base.cc')
-rw-r--r-- | src/cpu/base.cc | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/src/cpu/base.cc b/src/cpu/base.cc index ea4df2aa8..2f4745ee3 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -55,12 +55,14 @@ #include "base/misc.hh" #include "base/output.hh" #include "base/trace.hh" -#include "cpu/base.hh" #include "cpu/checker/cpu.hh" +#include "cpu/base.hh" #include "cpu/cpuevent.hh" #include "cpu/profile.hh" #include "cpu/thread_context.hh" +#include "debug/Mwait.hh" #include "debug/SyscallVerbose.hh" +#include "mem/page_table.hh" #include "params/BaseCPU.hh" #include "sim/full_system.hh" #include "sim/process.hh" @@ -123,7 +125,8 @@ BaseCPU::BaseCPU(Params *p, bool is_checker) _taskId(ContextSwitchTaskId::Unknown), _pid(Request::invldPid), _switchedOut(p->switched_out), _cacheLineSize(p->system->cacheLineSize()), interrupts(p->interrupts), profileEvent(NULL), - numThreads(p->numThreads), system(p->system) + numThreads(p->numThreads), system(p->system), + addressMonitor() { // if Python did not provide a valid ID, do it here if (_cpuId == -1 ) { @@ -261,6 +264,63 @@ BaseCPU::~BaseCPU() } void +BaseCPU::armMonitor(Addr address) +{ + addressMonitor.armed = true; + addressMonitor.vAddr = address; + addressMonitor.pAddr = 0x0; + DPRINTF(Mwait,"Armed monitor (vAddr=0x%lx)\n", address); +} + +bool +BaseCPU::mwait(PacketPtr pkt) +{ + if(addressMonitor.gotWakeup == false) { + int block_size = cacheLineSize(); + uint64_t mask = ~((uint64_t)(block_size - 1)); + + assert(pkt->req->hasPaddr()); + addressMonitor.pAddr = pkt->getAddr() & mask; + addressMonitor.waiting = true; + + DPRINTF(Mwait,"mwait called (vAddr=0x%lx, line's paddr=0x%lx)\n", + addressMonitor.vAddr, addressMonitor.pAddr); + return true; + } else { + addressMonitor.gotWakeup = false; + return false; + } +} + +void +BaseCPU::mwaitAtomic(ThreadContext *tc, TheISA::TLB *dtb) +{ + Request req; + Addr addr = addressMonitor.vAddr; + int block_size = cacheLineSize(); + uint64_t mask = ~((uint64_t)(block_size - 1)); + int size = block_size; + + //The address of the next line if it crosses a cache line boundary. + Addr secondAddr = roundDown(addr + size - 1, block_size); + + if (secondAddr > addr) + size = secondAddr - addr; + + req.setVirt(0, addr, size, 0x0, dataMasterId(), tc->instAddr()); + + // translate to physical address + Fault fault = dtb->translateAtomic(&req, tc, BaseTLB::Read); + assert(fault == NoFault); + + addressMonitor.pAddr = req.getPaddr() & mask; + addressMonitor.waiting = true; + + DPRINTF(Mwait,"mwait called (vAddr=0x%lx, line's paddr=0x%lx)\n", + addressMonitor.vAddr, addressMonitor.pAddr); +} + +void BaseCPU::init() { if (!params()->switched_out) { @@ -618,6 +678,25 @@ BaseCPU::scheduleInstStop(ThreadID tid, Counter insts, const char *cause) comInstEventQueue[tid]->schedule(event, now + insts); } +AddressMonitor::AddressMonitor() { + armed = false; + waiting = false; + gotWakeup = false; +} + +bool AddressMonitor::doMonitor(PacketPtr pkt) { + assert(pkt->req->hasPaddr()); + if(armed && waiting) { + if(pAddr == pkt->getAddr()) { + DPRINTF(Mwait,"pAddr=0x%lx invalidated: waking up core\n", + pkt->getAddr()); + waiting = false; + return true; + } + } + return false; +} + void BaseCPU::scheduleLoadStop(ThreadID tid, Counter loads, const char *cause) { |