提交 e826fe1b 编写于 作者: J Jeremy Fitzhardinge

xen: mask XSAVE from cpuid

Xen leaves XSAVE set in cpuid, but doesn't allow cr4.OSXSAVE
to be set.  This confuses the kernel and it ends up crashing on
an xsetbv instruction.

At boot time, try to set cr4.OSXSAVE, and mask XSAVE out of
cpuid it we can't.  This will produce a spurious error from Xen,
but allows us to support XSAVE if/when Xen does.

This also factors out the cpuid mask decisions to boot time.
Signed-off-by: NJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
上级 e9e2d1ff
...@@ -168,21 +168,23 @@ static void __init xen_banner(void) ...@@ -168,21 +168,23 @@ static void __init xen_banner(void)
xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
} }
static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
static void xen_cpuid(unsigned int *ax, unsigned int *bx, static void xen_cpuid(unsigned int *ax, unsigned int *bx,
unsigned int *cx, unsigned int *dx) unsigned int *cx, unsigned int *dx)
{ {
unsigned maskecx = ~0;
unsigned maskedx = ~0; unsigned maskedx = ~0;
/* /*
* Mask out inconvenient features, to try and disable as many * Mask out inconvenient features, to try and disable as many
* unsupported kernel subsystems as possible. * unsupported kernel subsystems as possible.
*/ */
if (*ax == 1) if (*ax == 1) {
maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */ maskecx = cpuid_leaf1_ecx_mask;
(1 << X86_FEATURE_ACPI) | /* disable ACPI */ maskedx = cpuid_leaf1_edx_mask;
(1 << X86_FEATURE_MCE) | /* disable MCE */ }
(1 << X86_FEATURE_MCA) | /* disable MCA */
(1 << X86_FEATURE_ACC)); /* thermal monitoring */
asm(XEN_EMULATE_PREFIX "cpuid" asm(XEN_EMULATE_PREFIX "cpuid"
: "=a" (*ax), : "=a" (*ax),
...@@ -190,9 +192,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, ...@@ -190,9 +192,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
"=c" (*cx), "=c" (*cx),
"=d" (*dx) "=d" (*dx)
: "0" (*ax), "2" (*cx)); : "0" (*ax), "2" (*cx));
*cx &= maskecx;
*dx &= maskedx; *dx &= maskedx;
} }
static __init void xen_init_cpuid_mask(void)
{
unsigned int ax, bx, cx, dx;
cpuid_leaf1_edx_mask =
~((1 << X86_FEATURE_MCE) | /* disable MCE */
(1 << X86_FEATURE_MCA) | /* disable MCA */
(1 << X86_FEATURE_ACC)); /* thermal monitoring */
if (!xen_initial_domain())
cpuid_leaf1_edx_mask &=
~((1 << X86_FEATURE_APIC) | /* disable local APIC */
(1 << X86_FEATURE_ACPI)); /* disable ACPI */
ax = 1;
xen_cpuid(&ax, &bx, &cx, &dx);
/* cpuid claims we support xsave; try enabling it to see what happens */
if (cx & (1 << (X86_FEATURE_XSAVE % 32))) {
unsigned long cr4;
set_in_cr4(X86_CR4_OSXSAVE);
cr4 = read_cr4();
if ((cr4 & X86_CR4_OSXSAVE) == 0)
cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32));
clear_in_cr4(X86_CR4_OSXSAVE);
}
}
static void xen_set_debugreg(int reg, unsigned long val) static void xen_set_debugreg(int reg, unsigned long val)
{ {
HYPERVISOR_set_debugreg(reg, val); HYPERVISOR_set_debugreg(reg, val);
...@@ -901,6 +937,8 @@ asmlinkage void __init xen_start_kernel(void) ...@@ -901,6 +937,8 @@ asmlinkage void __init xen_start_kernel(void)
xen_init_irq_ops(); xen_init_irq_ops();
xen_init_cpuid_mask();
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
/* /*
* set up the basic apic ops. * set up the basic apic ops.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册