ia64/xen-unstable

changeset 8889:eb6d2472ea1a

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>
author kaf24@firebug.cl.cam.ac.uk
date Fri Feb 17 20:41:30 2006 +0100 (2006-02-17)
parents 34f6a1efe52d
children 8d1354cf7795
files xen/arch/x86/cpu/amd.c
line diff
     1.1 --- a/xen/arch/x86/cpu/amd.c	Fri Feb 17 19:35:38 2006 +0100
     1.2 +++ b/xen/arch/x86/cpu/amd.c	Fri Feb 17 20:41:30 2006 +0100
     1.3 @@ -42,6 +42,62 @@ custom_param("amd_flush_filter", flush_f
     1.4  extern void vide(void);
     1.5  __asm__(".text\n.align 4\nvide: ret");
     1.6  
     1.7 +/* Can this system suffer from TSC drift due to C1 clock ramping? */
     1.8 +static int c1_ramping_may_cause_clock_drift(struct cpuinfo_x86 *c) 
     1.9 +{ 
    1.10 +	if (c->x86 < 0xf) {
    1.11 +		/*
    1.12 +		 * TSC drift doesn't exist on 7th Gen or less
    1.13 +		 * However, OS still needs to consider effects
    1.14 +		 * of P-state changes on TSC
    1.15 +		 */
    1.16 +		return 0;
    1.17 +	} else if (cpuid_edx(0x80000007) & (1<<8)) {
    1.18 +		/*
    1.19 +		 * CPUID.AdvPowerMgmtInfo.TscInvariant
    1.20 +		 * EDX bit 8, 8000_0007
    1.21 +		 * Invariant TSC on 8th Gen or newer, use it
    1.22 +		 * (assume all cores have invariant TSC)
    1.23 +		 */
    1.24 +		return 0;
    1.25 +	}
    1.26 +	return 1;
    1.27 +}
    1.28 +
    1.29 +/* PCI access functions. Should be safe to use 0xcf8/0xcfc port accesses here. */
    1.30 +static u8 pci_read_byte(u32 bus, u32 dev, u32 fn, u32 reg)
    1.31 +{
    1.32 +	outl((1U<<31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3), 0xcf8);
    1.33 +	return inb(0xcfc + (reg & 3));
    1.34 +}
    1.35 +
    1.36 +static void pci_write_byte(u32 bus, u32 dev, u32 fn, u32 reg, u8 val)
    1.37 +{
    1.38 +	outl((1U<<31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3), 0xcf8);
    1.39 +	outb(val, 0xcfc + (reg & 3));
    1.40 +}
    1.41 +
    1.42 +/*
    1.43 + * Disable C1-Clock ramping if enabled in PMM7.CpuLowPwrEnh on 8th-generation
    1.44 + * cores only. Assume BIOS has setup all Northbridges equivalently.
    1.45 + */
    1.46 +static void disable_c1_ramping(void) 
    1.47 +{
    1.48 +	u8 pmm7;
    1.49 +	int node;
    1.50 +
    1.51 +	for (node=0; node < NR_CPUS; node++) {
    1.52 +		/* PMM7: bus=0, dev=0x18+node, function=0x3, register=0x87. */
    1.53 +		pmm7 = pci_read_byte(0, 0x18+node, 0x3, 0x87);
    1.54 +		/* Invalid read means we've updated every Northbridge. */
    1.55 +		if (pmm7 == 0xFF)
    1.56 +			break;
    1.57 +		pmm7 &= 0xFC; /* clear pmm7[1:0] */
    1.58 +		pci_write_byte(0, 0x18+node, 0x3, 0x87, pmm7);
    1.59 +		printk ("AMD: Disabling C1 Clock Ramping Node #%x\n", node);
    1.60 +	}
    1.61 +}
    1.62 +
    1.63  static void __init init_amd(struct cpuinfo_x86 *c)
    1.64  {
    1.65  	u32 l, h;
    1.66 @@ -275,6 +331,10 @@ static void __init init_amd(struct cpuin
    1.67  	}
    1.68  #endif
    1.69  
    1.70 +	/* Prevent TSC drift in non single-processor, single-core platforms. */
    1.71 +	if ((smp_processor_id() == 1) && c1_ramping_may_cause_clock_drift(c))
    1.72 +		disable_c1_ramping();
    1.73 +
    1.74  	start_svm();
    1.75  }
    1.76