diff options
author | Andreas Sandberg <Andreas.Sandberg@ARM.com> | 2013-04-22 13:20:32 -0400 |
---|---|---|
committer | Andreas Sandberg <Andreas.Sandberg@ARM.com> | 2013-04-22 13:20:32 -0400 |
commit | 2607efded8ea856d632f017e93b40f1780046db1 (patch) | |
tree | 1d9c6072a2cc3189db43a39017fddec0af45691f /src/cpu/kvm/base.cc | |
parent | f485ad190830ab61d58ecdb8eb48621ffeb3008f (diff) | |
download | gem5-2607efded8ea856d632f017e93b40f1780046db1.tar.xz |
kvm: Avoid synchronizing the TC on every KVM exit
Reduce the number of KVM->TC synchronizations by overloading the
getContext() method and only request an update when the TC is
requested as opposed to every time KVM returns to gem5.
Diffstat (limited to 'src/cpu/kvm/base.cc')
-rw-r--r-- | src/cpu/kvm/base.cc | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc index 04e35854a..89f5e0f5d 100644 --- a/src/cpu/kvm/base.cc +++ b/src/cpu/kvm/base.cc @@ -72,7 +72,8 @@ BaseKvmCPU::BaseKvmCPU(BaseKvmCPUParams *params) _status(Idle), dataPort(name() + ".dcache_port", this), instPort(name() + ".icache_port", this), - contextDirty(true), + threadContextDirty(true), + kvmStateDirty(false), vcpuID(vm.allocVCPUID()), vcpuFD(-1), vcpuMMapSize(0), _kvmRun(NULL), mmioRing(NULL), pageSize(sysconf(_SC_PAGE_SIZE)), @@ -205,6 +206,9 @@ BaseKvmCPU::regStats() void BaseKvmCPU::serializeThread(std::ostream &os, ThreadID tid) { + // Update the thread context so we have something to serialize. + syncThreadContext(); + assert(tid == 0); assert(_status == Idle); thread->serialize(os); @@ -217,7 +221,7 @@ BaseKvmCPU::unserializeThread(Checkpoint *cp, const std::string §ion, assert(tid == 0); assert(_status == Idle); thread->unserialize(cp, section); - contextDirty = true; + threadContextDirty = true; } unsigned int @@ -263,10 +267,14 @@ BaseKvmCPU::drainResume() void BaseKvmCPU::switchOut() { - BaseCPU::switchOut(); - DPRINTF(Kvm, "switchOut\n"); + // Make sure to update the thread context in case, the new CPU + // will need to access it. + syncThreadContext(); + + BaseCPU::switchOut(); + // We should have drained prior to executing a switchOut, which // means that the tick event shouldn't be scheduled and the CPU is // idle. @@ -288,8 +296,9 @@ BaseKvmCPU::takeOverFrom(BaseCPU *cpu) assert(_status == Idle); assert(threadContexts.size() == 1); - // Force a gem5 -> KVM context synchronization - contextDirty = true; + // The BaseCPU updated the thread context, make sure that we + // synchronize next time we enter start the CPU. + threadContextDirty = true; } void @@ -368,6 +377,15 @@ BaseKvmCPU::haltContext(ThreadID thread_num) suspendContext(thread_num); } +ThreadContext * +BaseKvmCPU::getContext(int tn) +{ + assert(tn == 0); + syncThreadContext(); + return tc; +} + + Counter BaseKvmCPU::totalInsts() const { @@ -394,14 +412,8 @@ BaseKvmCPU::tick() DPRINTF(KvmRun, "Entering KVM...\n"); - if (contextDirty) { - contextDirty = false; - updateKvmState(); - } - Tick ticksToExecute(mainEventQueue.nextTick() - curTick()); Tick ticksExecuted(kvmRun(ticksToExecute)); - updateThreadContext(); Tick delay(ticksExecuted + handleKvmExit()); @@ -423,6 +435,13 @@ BaseKvmCPU::kvmRun(Tick ticks) uint64_t baseCycles(hwCycles.read()); uint64_t baseInstrs(hwInstructions.read()); + // We might need to update the KVM state. + syncKvmState(); + // Entering into KVM implies that we'll have to reload the thread + // context from KVM if we want to access it. Flag the KVM state as + // dirty with respect to the cached thread context. + kvmStateDirty = true; + if (ticks < runTimer->resolution()) { DPRINTF(KvmRun, "KVM: Adjusting tick count (%i -> %i)\n", ticks, runTimer->resolution()); @@ -604,6 +623,30 @@ BaseKvmCPU::getAndFormatOneReg(uint64_t id) const #endif } +void +BaseKvmCPU::syncThreadContext() +{ + if (!kvmStateDirty) + return; + + assert(!threadContextDirty); + + updateThreadContext(); + kvmStateDirty = false; +} + +void +BaseKvmCPU::syncKvmState() +{ + if (!threadContextDirty) + return; + + assert(!kvmStateDirty); + + updateKvmState(); + threadContextDirty = false; +} + Tick BaseKvmCPU::handleKvmExit() { |