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>
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