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

[Xen-changelog] [xen-unstable] x86: disable AMD's C1E mode.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1192105658 -3600
# Node ID cab326925ea6896d1b623629926d0011c29d1798
# Parent  0d7d6804af2204dece108959f4fa40764bd2734f
x86: disable AMD's C1E mode.

In C1E the APIC timer stops ticking, which Xen cannot tolerate.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 xen/arch/x86/acpi/boot.c   |    8 ++++++++
 xen/arch/x86/cpu/amd.c     |   27 +++++++++++++++++++++++++++
 xen/arch/x86/traps.c       |   10 ++++++++++
 xen/include/asm-x86/acpi.h |    2 ++
 xen/include/asm-x86/io.h   |    2 ++
 5 files changed, 49 insertions(+)

diff -r 0d7d6804af22 -r cab326925ea6 xen/arch/x86/acpi/boot.c
--- a/xen/arch/x86/acpi/boot.c  Thu Oct 11 12:11:54 2007 +0100
+++ b/xen/arch/x86/acpi/boot.c  Thu Oct 11 13:27:38 2007 +0100
@@ -70,6 +70,9 @@ static u64 acpi_lapic_addr __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;
 }
 
diff -r 0d7d6804af22 -r cab326925ea6 xen/arch/x86/cpu/amd.c
--- a/xen/arch/x86/cpu/amd.c    Thu Oct 11 12:11:54 2007 +0100
+++ b/xen/arch/x86/cpu/amd.c    Thu Oct 11 13:27:38 2007 +0100
@@ -102,6 +102,29 @@ static void disable_c1_ramping(void)
 
 int force_mwait __cpuinitdata;
 
+static void disable_c1e(void *unused)
+{
+       u32 lo, hi;
+
+       /*
+        * Disable C1E mode, as the APIC timer stops in that mode.
+        * The MSR does not exist in all FamilyF CPUs (only Rev F and above),
+        * but we safely catch the #GP in that case.
+        */
+       if ((rdmsr_safe(MSR_K8_ENABLE_C1E, lo, hi) == 0) &&
+           (lo & (3u << 27)) &&
+           (wrmsr_safe(MSR_K8_ENABLE_C1E, lo & ~(3u << 27), 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)
+{
+       /* C1E is sometimes enabled during entry to ACPI mode. */
+       if ((port == acpi_smi_cmd) && (value == acpi_enable_value))
+               on_each_cpu(disable_c1e, NULL, 1, 1);
+}
+
 static void __init init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
@@ -282,6 +305,9 @@ static void __init init_amd(struct cpuin
        case 0x10:
        case 0x11:
                set_bit(X86_FEATURE_K8, c->x86_capability);
+               disable_c1e(NULL);
+               if (acpi_smi_cmd && (acpi_enable_value | acpi_disable_value))
+                       pv_post_outb_hook = check_disable_c1e;
                break;
        case 6:
                set_bit(X86_FEATURE_K7, c->x86_capability);
@@ -335,6 +361,7 @@ static void __init init_amd(struct cpuin
        }
 #endif
 
+       /* Pointless to use MWAIT on Family10 as it does not deep sleep. */
        if (c->x86 == 0x10 && !force_mwait)
                clear_bit(X86_FEATURE_MWAIT, c->x86_capability);
 
diff -r 0d7d6804af22 -r cab326925ea6 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Oct 11 12:11:54 2007 +0100
+++ b/xen/arch/x86/traps.c      Thu Oct 11 13:27:38 2007 +0100
@@ -1183,6 +1183,8 @@ void host_to_guest_gpr_switch(struct cpu
     __attribute__((__regparm__(1)));
 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)                                  \
@@ -1412,7 +1414,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;
@@ -1530,7 +1536,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;
diff -r 0d7d6804af22 -r cab326925ea6 xen/include/asm-x86/acpi.h
--- a/xen/include/asm-x86/acpi.h        Thu Oct 11 12:11:54 2007 +0100
+++ b/xen/include/asm-x86/acpi.h        Thu Oct 11 13:27:38 2007 +0100
@@ -114,6 +114,8 @@ extern int acpi_disabled;
 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;
diff -r 0d7d6804af22 -r cab326925ea6 xen/include/asm-x86/io.h
--- a/xen/include/asm-x86/io.h  Thu Oct 11 12:11:54 2007 +0100
+++ b/xen/include/asm-x86/io.h  Thu Oct 11 13:27:38 2007 +0100
@@ -50,4 +50,6 @@ __OUT(w,"w",short)
 __OUT(w,"w",short)
 __OUT(l,,int)
 
+extern void (*pv_post_outb_hook)(unsigned int port, u8 value);
+
 #endif

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


 


Rackspace

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