kvm: Allow architectures to override the cycle accounting mechanism
authorAndreas Sandberg <andreas@sandberg.pp.se>
Mon, 3 Jun 2013 11:39:11 +0000 (13:39 +0200)
committerAndreas Sandberg <andreas@sandberg.pp.se>
Mon, 3 Jun 2013 11:39:11 +0000 (13:39 +0200)
Some architectures have special registers in the guest that can be
used to do cycle accounting. This is generally preferrable since the
prevents the guest from seeing a non-monotonic clock. This changeset
adds a virtual method, getHostCycles(), that the architecture-specific
code can override to implement this functionallity. The default
implementation uses the hwCycles counter.

src/cpu/kvm/base.cc
src/cpu/kvm/base.hh

index b5f64664f13be6fc735e4c55c30316a87102fdb2..a0aa511eaa09a607b4e65aec59ff730cd71210e7 100644 (file)
@@ -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));
index 4546b10711c875aa751ae112f54c99c36783ecc5..c53f715e36d269dc72417d15631fcb67627b6fcd 100644 (file)
@@ -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.