ia64/xen-unstable
changeset 16094:cab326925ea6
x86: disable AMD's C1E mode.
In C1E the APIC timer stops ticking, which Xen cannot tolerate.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
In C1E the APIC timer stops ticking, which Xen cannot tolerate.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
author | Keir Fraser <keir@xensource.com> |
---|---|
date | Thu Oct 11 13:27:38 2007 +0100 (2007-10-11) |
parents | 0d7d6804af22 |
children | 034df2dca608 |
files | xen/arch/x86/acpi/boot.c xen/arch/x86/cpu/amd.c xen/arch/x86/traps.c xen/include/asm-x86/acpi.h xen/include/asm-x86/io.h |
line diff
1.1 --- a/xen/arch/x86/acpi/boot.c Thu Oct 11 12:11:54 2007 +0100 1.2 +++ b/xen/arch/x86/acpi/boot.c Thu Oct 11 13:27:38 2007 +0100 1.3 @@ -70,6 +70,9 @@ int acpi_skip_timer_override __initdata; 1.4 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; 1.5 #endif 1.6 1.7 +u32 acpi_smi_cmd; 1.8 +u8 acpi_enable_value, acpi_disable_value; 1.9 + 1.10 #ifndef __HAVE_ARCH_CMPXCHG 1.11 #warning ACPI uses CMPXCHG, i486 and later hardware 1.12 #endif 1.13 @@ -509,9 +512,14 @@ static int __init acpi_parse_fadt(unsign 1.14 pmtmr_ioport); 1.15 #endif 1.16 1.17 + acpi_smi_cmd = fadt->smi_cmd; 1.18 + acpi_enable_value = fadt->acpi_enable; 1.19 + acpi_disable_value = fadt->acpi_disable; 1.20 + 1.21 #ifdef CONFIG_ACPI_SLEEP 1.22 acpi_fadt_parse_sleep_info(fadt); 1.23 #endif 1.24 + 1.25 return 0; 1.26 } 1.27
2.1 --- a/xen/arch/x86/cpu/amd.c Thu Oct 11 12:11:54 2007 +0100 2.2 +++ b/xen/arch/x86/cpu/amd.c Thu Oct 11 13:27:38 2007 +0100 2.3 @@ -102,6 +102,29 @@ static void disable_c1_ramping(void) 2.4 2.5 int force_mwait __cpuinitdata; 2.6 2.7 +static void disable_c1e(void *unused) 2.8 +{ 2.9 + u32 lo, hi; 2.10 + 2.11 + /* 2.12 + * Disable C1E mode, as the APIC timer stops in that mode. 2.13 + * The MSR does not exist in all FamilyF CPUs (only Rev F and above), 2.14 + * but we safely catch the #GP in that case. 2.15 + */ 2.16 + if ((rdmsr_safe(MSR_K8_ENABLE_C1E, lo, hi) == 0) && 2.17 + (lo & (3u << 27)) && 2.18 + (wrmsr_safe(MSR_K8_ENABLE_C1E, lo & ~(3u << 27), hi) != 0)) 2.19 + printk(KERN_ERR "Failed to disable C1E on CPU#%u (%08x)\n", 2.20 + smp_processor_id(), lo); 2.21 +} 2.22 + 2.23 +static void check_disable_c1e(unsigned int port, u8 value) 2.24 +{ 2.25 + /* C1E is sometimes enabled during entry to ACPI mode. */ 2.26 + if ((port == acpi_smi_cmd) && (value == acpi_enable_value)) 2.27 + on_each_cpu(disable_c1e, NULL, 1, 1); 2.28 +} 2.29 + 2.30 static void __init init_amd(struct cpuinfo_x86 *c) 2.31 { 2.32 u32 l, h; 2.33 @@ -282,6 +305,9 @@ static void __init init_amd(struct cpuin 2.34 case 0x10: 2.35 case 0x11: 2.36 set_bit(X86_FEATURE_K8, c->x86_capability); 2.37 + disable_c1e(NULL); 2.38 + if (acpi_smi_cmd && (acpi_enable_value | acpi_disable_value)) 2.39 + pv_post_outb_hook = check_disable_c1e; 2.40 break; 2.41 case 6: 2.42 set_bit(X86_FEATURE_K7, c->x86_capability); 2.43 @@ -335,6 +361,7 @@ static void __init init_amd(struct cpuin 2.44 } 2.45 #endif 2.46 2.47 + /* Pointless to use MWAIT on Family10 as it does not deep sleep. */ 2.48 if (c->x86 == 0x10 && !force_mwait) 2.49 clear_bit(X86_FEATURE_MWAIT, c->x86_capability); 2.50
3.1 --- a/xen/arch/x86/traps.c Thu Oct 11 12:11:54 2007 +0100 3.2 +++ b/xen/arch/x86/traps.c Thu Oct 11 13:27:38 2007 +0100 3.3 @@ -1184,6 +1184,8 @@ void host_to_guest_gpr_switch(struct cpu 3.4 unsigned long guest_to_host_gpr_switch(unsigned long) 3.5 __attribute__((__regparm__(1))); 3.6 3.7 +void (*pv_post_outb_hook)(unsigned int port, u8 value); 3.8 + 3.9 /* Instruction fetch with error handling. */ 3.10 #define insn_fetch(type, base, eip, limit) \ 3.11 ({ unsigned long _rc, _ptr = (base) + (eip); \ 3.12 @@ -1412,7 +1414,11 @@ static int emulate_privileged_op(struct 3.13 { 3.14 case 1: 3.15 if ( guest_outb_okay(port, v, regs) ) 3.16 + { 3.17 outb((u8)data, port); 3.18 + if ( pv_post_outb_hook ) 3.19 + pv_post_outb_hook(port, data); 3.20 + } 3.21 else if ( port == 0x42 || port == 0x43 || port == 0x61 ) 3.22 pv_pit_handler(port, data, 1); 3.23 break; 3.24 @@ -1530,7 +1536,11 @@ static int emulate_privileged_op(struct 3.25 { 3.26 case 1: 3.27 if ( guest_outb_okay(port, v, regs) ) 3.28 + { 3.29 io_emul(regs); 3.30 + if ( pv_post_outb_hook ) 3.31 + pv_post_outb_hook(port, regs->eax); 3.32 + } 3.33 else if ( port == 0x42 || port == 0x43 || port == 0x61 ) 3.34 pv_pit_handler(port, regs->eax, 1); 3.35 break;
4.1 --- a/xen/include/asm-x86/acpi.h Thu Oct 11 12:11:54 2007 +0100 4.2 +++ b/xen/include/asm-x86/acpi.h Thu Oct 11 13:27:38 2007 +0100 4.3 @@ -114,6 +114,8 @@ extern int acpi_strict; 4.4 extern int acpi_disabled; 4.5 extern int acpi_ht; 4.6 extern int acpi_pci_disabled; 4.7 +extern u32 acpi_smi_cmd; 4.8 +extern u8 acpi_enable_value, acpi_disable_value; 4.9 static inline void disable_acpi(void) 4.10 { 4.11 acpi_disabled = 1;
5.1 --- a/xen/include/asm-x86/io.h Thu Oct 11 12:11:54 2007 +0100 5.2 +++ b/xen/include/asm-x86/io.h Thu Oct 11 13:27:38 2007 +0100 5.3 @@ -50,4 +50,6 @@ static inline RETURN_TYPE in##s(unsigned 5.4 __OUT(w,"w",short) 5.5 __OUT(l,,int) 5.6 5.7 +extern void (*pv_post_outb_hook)(unsigned int port, u8 value); 5.8 + 5.9 #endif