diff options
author | Marc Orr <morr@cs.wisc.edu> | 2014-11-06 05:42:22 -0600 |
---|---|---|
committer | Marc Orr <morr@cs.wisc.edu> | 2014-11-06 05:42:22 -0600 |
commit | bf80734b2ce080cd75f4b57be47e37465e8901f1 (patch) | |
tree | 0ba9cbba64cd017e95b5a3f637d58435208ebc3c /src/cpu/base.cc | |
parent | 3947f88d0fa35d2134fa3e999e05bb184a01e396 (diff) | |
download | gem5-bf80734b2ce080cd75f4b57be47e37465e8901f1.tar.xz |
x86 isa: This patch attempts an implementation at mwait.
Mwait works as follows:
1. A cpu monitors an address of interest (monitor instruction)
2. A cpu calls mwait - this loads the cache line into that cpu's cache.
3. The cpu goes to sleep.
4. When another processor requests write permission for the line, it is
evicted from the sleeping cpu's cache. This eviction is forwarded to the
sleeping cpu, which then wakes up.
Committed by: Nilay Vaish <nilay@cs.wisc.edu>
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) { |