x86: Fix bug when copying TSC on CPU handover
authorAndreas Sandberg <andreas@sandberg.pp.se>
Tue, 11 Jun 2013 07:24:38 +0000 (09:24 +0200)
committerAndreas Sandberg <andreas@sandberg.pp.se>
Tue, 11 Jun 2013 07:24:38 +0000 (09:24 +0200)
The TSC value stored in MISCREG_TSC is actually just an offset from
the current CPU cycle to the actual TSC value. Writes with
side-effects to the TSC subtract the current cycle count before
storing the new value, while reads add the current cycle count. When
switching CPUs, the current value is copied without side-effects. This
works as long as the source and the destination CPUs have the same
clock frequencies. The TSC will jump, sometimes backwards, if they
have different clock frequencies. Most OSes assume the TSC to be
monotonic and break when this happens.

This changeset makes sure that the TSC is copied with side-effects to
ensure that the offset is updated to match the new CPU.

src/arch/x86/utility.cc

index ae6c37be629818939bc0bfdf5531f01cb94351c8..e3d25fcdf11f9ff841aaa7316a2d158774677711 100644 (file)
@@ -209,6 +209,10 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
         dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
     }
 
+    // The TSC has to be updated with side-effects if the CPUs in a
+    // CPU switch have different frequencies.
+    dest->setMiscReg(MISCREG_TSC, src->readMiscReg(MISCREG_TSC));
+
     dest->getITBPtr()->flushAll();
     dest->getDTBPtr()->flushAll();
 }