[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86: disable AMD's C1E mode



In C1E the APIC timer stops ticking, which Xen cannot tolerate. (As I
don't have a system that's affected, the patch must be considered
untested).

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-10-10/xen/arch/x86/acpi/boot.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/acpi/boot.c    2007-09-27 10:42:44.000000000 
+0200
+++ 2007-10-10/xen/arch/x86/acpi/boot.c 2007-10-10 17:14:46.000000000 +0200
@@ -70,6 +70,9 @@ int acpi_skip_timer_override __initdata;
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
 
+u32 acpi_smi_cmd;
+u8 acpi_enable_value, acpi_disable_value;
+
 #ifndef __HAVE_ARCH_CMPXCHG
 #warning ACPI uses CMPXCHG, i486 and later hardware
 #endif
@@ -509,9 +512,14 @@ static int __init acpi_parse_fadt(unsign
                       pmtmr_ioport);
 #endif
 
+       acpi_smi_cmd       = fadt->smi_cmd;
+       acpi_enable_value  = fadt->acpi_enable;
+       acpi_disable_value = fadt->acpi_disable;
+
 #ifdef CONFIG_ACPI_SLEEP
        acpi_fadt_parse_sleep_info(fadt);
 #endif
+
        return 0;
 }
 
Index: 2007-10-10/xen/arch/x86/cpu/amd.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/cpu/amd.c      2007-10-10 17:12:29.000000000 
+0200
+++ 2007-10-10/xen/arch/x86/cpu/amd.c   2007-10-10 17:14:05.000000000 +0200
@@ -100,6 +100,32 @@ static void disable_c1_ramping(void) 
        }
 }
 
+#ifdef CONFIG_SMP
+/*
+ * Disable C1E mode, as the APIC timer stops in that mode.
+ */
+static void disable_c1e(void *unused)
+{
+       u32 lo, hi;
+
+       if (rdmsr_safe(0xC0010055, lo, hi) == 0
+           && (lo & ((1 << 27) | (1 << 28)))
+           && wrmsr_safe(0xC0010055,
+                         lo & ~((1 << 27) | (1 << 28)),
+                         hi) != 0)
+               printk(KERN_ERR "Failed to disable C1E on CPU#%u (%08x)\n",
+                      smp_processor_id(), lo);
+}
+
+static void check_disable_c1e(unsigned int port, u8 value)
+{
+       if (port == acpi_smi_cmd && value == acpi_enable_value)
+               on_each_cpu(disable_c1e, NULL, 1, 1);
+}
+#else
+#define check_disable_c1e NULL
+#endif
+
 static void __init init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
@@ -280,6 +306,10 @@ static void __init init_amd(struct cpuin
        switch (c->x86) {
        case 15 ... 17:
                set_bit(X86_FEATURE_K8, c->x86_capability);
+               if (acpi_smi_cmd && (acpi_enable_value | acpi_disable_value)) {
+                       disable_c1e(NULL);
+                       pv_post_outb_hook = check_disable_c1e;
+               }
                break;
        case 6:
                set_bit(X86_FEATURE_K7, c->x86_capability);
Index: 2007-10-10/xen/arch/x86/traps.c
===================================================================
--- 2007-10-10.orig/xen/arch/x86/traps.c        2007-10-10 17:11:34.000000000 
+0200
+++ 2007-10-10/xen/arch/x86/traps.c     2007-10-10 17:14:05.000000000 +0200
@@ -1191,6 +1191,8 @@ void host_to_guest_gpr_switch(struct cpu
 unsigned long guest_to_host_gpr_switch(unsigned long)
     __attribute__((__regparm__(1)));
 
+void (*pv_post_outb_hook)(unsigned int port, u8 value);
+
 /* Instruction fetch with error handling. */
 #define insn_fetch(type, base, eip, limit)                                  \
 ({  unsigned long _rc, _ptr = (base) + (eip);                               \
@@ -1419,7 +1421,11 @@ static int emulate_privileged_op(struct 
             {
             case 1:
                 if ( guest_outb_okay(port, v, regs) )
+                {
                     outb((u8)data, port);
+                    if ( pv_post_outb_hook )
+                        pv_post_outb_hook(port, data);
+                }
                 else if ( port == 0x42 || port == 0x43 || port == 0x61 )
                     pv_pit_handler(port, data, 1);
                 break;
@@ -1537,7 +1543,11 @@ static int emulate_privileged_op(struct 
         {
         case 1:
             if ( guest_outb_okay(port, v, regs) )
+            {
                 io_emul(regs);
+                if ( pv_post_outb_hook )
+                    pv_post_outb_hook(port, regs->eax);
+            }
             else if ( port == 0x42 || port == 0x43 || port == 0x61 )
                 pv_pit_handler(port, regs->eax, 1);
             break;
Index: 2007-10-10/xen/include/asm-x86/acpi.h
===================================================================
--- 2007-10-10.orig/xen/include/asm-x86/acpi.h  2007-09-27 10:42:44.000000000 
+0200
+++ 2007-10-10/xen/include/asm-x86/acpi.h       2007-10-10 17:14:05.000000000 
+0200
@@ -114,6 +114,8 @@ extern int acpi_strict;
 extern int acpi_disabled;
 extern int acpi_ht;
 extern int acpi_pci_disabled;
+extern u32 acpi_smi_cmd;
+extern u8 acpi_enable_value, acpi_disable_value;
 static inline void disable_acpi(void) 
 { 
        acpi_disabled = 1;
Index: 2007-10-10/xen/include/asm-x86/io.h
===================================================================
--- 2007-10-10.orig/xen/include/asm-x86/io.h    2006-08-21 18:02:24.000000000 
+0200
+++ 2007-10-10/xen/include/asm-x86/io.h 2007-10-10 17:14:05.000000000 +0200
@@ -50,4 +50,6 @@ __OUT(b,"b",char)
 __OUT(w,"w",short)
 __OUT(l,,int)
 
+extern void (*pv_post_outb_hook)(unsigned int port, u8 value);
+
 #endif



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.