In C1E the APIC timer stops ticking, which Xen cannot tolerate.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
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
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;
}
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;
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);
}
#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);
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); \
{
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;
{
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;
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;
__OUT(w,"w",short)
__OUT(l,,int)
+extern void (*pv_post_outb_hook)(unsigned int port, u8 value);
+
#endif