Mailing List Archive

Disable C1 clock ramping on AMD 8th gen CPUs.
# HG changeset patch
# User kaf24@firebug.cl.cam.ac.uk
# Node ID eb6d2472ea1ac1275b2382735959217d26cc7933
# Parent 34f6a1efe52d8c5c722a2d423a0b26b469540a3a
Disable C1 clock ramping on AMD 8th gen CPUs.

This reverts a previous changeset that removed this code.
It is currently required for good TSC behaviour in SVM
(fully virtualised) guests.

Signed-off-by: Keir Fraser <keir@xensource.com>

diff -r 34f6a1efe52d -r eb6d2472ea1a xen/arch/x86/cpu/amd.c
--- a/xen/arch/x86/cpu/amd.c Fri Feb 17 18:35:38 2006
+++ b/xen/arch/x86/cpu/amd.c Fri Feb 17 19:41:30 2006
@@ -41,6 +41,62 @@

extern void vide(void);
__asm__(".text\n.align 4\nvide: ret");
+
+/* Can this system suffer from TSC drift due to C1 clock ramping? */
+static int c1_ramping_may_cause_clock_drift(struct cpuinfo_x86 *c)
+{
+ if (c->x86 < 0xf) {
+ /*
+ * TSC drift doesn't exist on 7th Gen or less
+ * However, OS still needs to consider effects
+ * of P-state changes on TSC
+ */
+ return 0;
+ } else if (cpuid_edx(0x80000007) & (1<<8)) {
+ /*
+ * CPUID.AdvPowerMgmtInfo.TscInvariant
+ * EDX bit 8, 8000_0007
+ * Invariant TSC on 8th Gen or newer, use it
+ * (assume all cores have invariant TSC)
+ */
+ return 0;
+ }
+ return 1;
+}
+
+/* PCI access functions. Should be safe to use 0xcf8/0xcfc port accesses here. */
+static u8 pci_read_byte(u32 bus, u32 dev, u32 fn, u32 reg)
+{
+ outl((1U<<31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3), 0xcf8);
+ return inb(0xcfc + (reg & 3));
+}
+
+static void pci_write_byte(u32 bus, u32 dev, u32 fn, u32 reg, u8 val)
+{
+ outl((1U<<31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3), 0xcf8);
+ outb(val, 0xcfc + (reg & 3));
+}
+
+/*
+ * Disable C1-Clock ramping if enabled in PMM7.CpuLowPwrEnh on 8th-generation
+ * cores only. Assume BIOS has setup all Northbridges equivalently.
+ */
+static void disable_c1_ramping(void)
+{
+ u8 pmm7;
+ int node;
+
+ for (node=0; node < NR_CPUS; node++) {
+ /* PMM7: bus=0, dev=0x18+node, function=0x3, register=0x87. */
+ pmm7 = pci_read_byte(0, 0x18+node, 0x3, 0x87);
+ /* Invalid read means we've updated every Northbridge. */
+ if (pmm7 == 0xFF)
+ break;
+ pmm7 &= 0xFC; /* clear pmm7[1:0] */
+ pci_write_byte(0, 0x18+node, 0x3, 0x87, pmm7);
+ printk ("AMD: Disabling C1 Clock Ramping Node #%x\n", node);
+ }
+}

static void __init init_amd(struct cpuinfo_x86 *c)
{
@@ -274,6 +330,10 @@
cpu, c->x86_max_cores, cpu_core_id[cpu]);
}
#endif
+
+ /* Prevent TSC drift in non single-processor, single-core platforms. */
+ if ((smp_processor_id() == 1) && c1_ramping_may_cause_clock_drift(c))
+ disable_c1_ramping();

start_svm();
}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog