1--- a/arch/x86/xen/enlighten.c
2+++ b/arch/x86/xen/enlighten.c
3@@ -168,21 +168,23 @@ static void __init xen_banner(void)
4 xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
5 }
6
7+static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
8+static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
9+
10 static void xen_cpuid(unsigned int *ax, unsigned int *bx,
11 unsigned int *cx, unsigned int *dx)
12 {
13+ unsigned maskecx = ~0;
14 unsigned maskedx = ~0;
15
16 /*
17 * Mask out inconvenient features, to try and disable as many
18 * unsupported kernel subsystems as possible.
19 */
20- if (*ax == 1)
21- maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */
22- (1 << X86_FEATURE_ACPI) | /* disable ACPI */
23- (1 << X86_FEATURE_MCE) | /* disable MCE */
24- (1 << X86_FEATURE_MCA) | /* disable MCA */
25- (1 << X86_FEATURE_ACC)); /* thermal monitoring */
26+ if (*ax == 1) {
27+ maskecx = cpuid_leaf1_ecx_mask;
28+ maskedx = cpuid_leaf1_edx_mask;
29+ }
30
31 asm(XEN_EMULATE_PREFIX "cpuid"
32 : "=a" (*ax),
33@@ -190,9 +192,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
34 "=c" (*cx),
35 "=d" (*dx)
36 : "0" (*ax), "2" (*cx));
37+
38+ *cx &= maskecx;
39 *dx &= maskedx;
40 }
41
42+static __init void xen_init_cpuid_mask(void)
43+{
44+ unsigned int ax, bx, cx, dx;
45+
46+ cpuid_leaf1_edx_mask =
47+ ~((1 << X86_FEATURE_MCE) | /* disable MCE */
48+ (1 << X86_FEATURE_MCA) | /* disable MCA */
49+ (1 << X86_FEATURE_ACC)); /* thermal monitoring */
50+
51+ if (!xen_initial_domain())
52+ cpuid_leaf1_edx_mask &=
53+ ~((1 << X86_FEATURE_APIC) | /* disable local APIC */
54+ (1 << X86_FEATURE_ACPI)); /* disable ACPI */
55+
56+ ax = 1;
57+ xen_cpuid(&ax, &bx, &cx, &dx);
58+
59+ /* cpuid claims we support xsave; try enabling it to see what happens */
60+ if (cx & (1 << (X86_FEATURE_XSAVE % 32))) {
61+ unsigned long cr4;
62+
63+ set_in_cr4(X86_CR4_OSXSAVE);
64+
65+ cr4 = read_cr4();
66+
67+ if ((cr4 & X86_CR4_OSXSAVE) == 0)
68+ cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32));
69+
70+ clear_in_cr4(X86_CR4_OSXSAVE);
71+ }
72+}
73+
74 static void xen_set_debugreg(int reg, unsigned long val)
75 {
76 HYPERVISOR_set_debugreg(reg, val);
77@@ -903,6 +939,8 @@ asmlinkage void __init xen_start_kernel(void)
78
79 xen_init_irq_ops();
80
81+ xen_init_cpuid_mask();
82+
83 #ifdef CONFIG_X86_LOCAL_APIC
84 /*
85 * set up the basic apic ops.