diff --git a/src/cpu/kvm/base.cc b/src/cpu/kvm/base.cc index b5f64664f..a0aa511ea 100644 --- a/src/cpu/kvm/base.cc +++ b/src/cpu/kvm/base.cc @@ -456,12 +456,15 @@ BaseKvmCPU::tick() } } +uint64_t +BaseKvmCPU::getHostCycles() const +{ + return hwCycles.read(); +} + Tick 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 @@ -478,6 +481,11 @@ BaseKvmCPU::kvmRun(Tick ticks) DPRINTF(KvmRun, "KVM: Executing for %i ticks\n", ticks); timerOverflowed = false; + // Get hardware statistics after synchronizing contexts. The KVM + // state update might affect guest cycle counters. + uint64_t baseCycles(getHostCycles()); + uint64_t baseInstrs(hwInstructions.read()); + // Arm the run timer and start the cycle timer if it isn't // controlled by the overflow timer. Starting/stopping the cycle // timer automatically starts the other perf timers as they are in @@ -497,7 +505,7 @@ BaseKvmCPU::kvmRun(Tick ticks) hwCycles.stop(); - const uint64_t hostCyclesExecuted(hwCycles.read() - baseCycles); + const uint64_t hostCyclesExecuted(getHostCycles() - baseCycles); const uint64_t simCyclesExecuted(hostCyclesExecuted * hostFactor); const uint64_t instsExecuted(hwInstructions.read() - baseInstrs); const Tick ticksExecuted(runTimer->ticksFromHostCycles(hostCyclesExecuted)); diff --git a/src/cpu/kvm/base.hh b/src/cpu/kvm/base.hh index 4546b1071..c53f715e3 100644 --- a/src/cpu/kvm/base.hh +++ b/src/cpu/kvm/base.hh @@ -153,6 +153,21 @@ class BaseKvmCPU : public BaseCPU */ virtual void tick(); + /** + * Get the value of the hardware cycle counter in the guest. + * + * This method is supposed to return the total number of cycles + * executed in hardware mode relative to some arbitrary point in + * the past. It's mainly used when estimating the number of cycles + * actually executed by the CPU in kvmRun(). The default behavior + * of this method is to use the cycles performance counter, but + * some architectures may want to use internal registers instead. + * + * @return Number of host cycles executed relative to an undefined + * point in the past. + */ + virtual uint64_t getHostCycles() const; + /** * Request KVM to run the guest for a given number of ticks. The * method returns the approximate number of ticks executed.