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