summary refs log tree commit diff
path: root/pkgs/os-specific/linux/kernel/no-xsave.patch
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/os-specific/linux/kernel/no-xsave.patch')
-rw-r--r--pkgs/os-specific/linux/kernel/no-xsave.patch85
1 files changed, 85 insertions, 0 deletions
diff --git a/pkgs/os-specific/linux/kernel/no-xsave.patch b/pkgs/os-specific/linux/kernel/no-xsave.patch
new file mode 100644
index 000000000000..dde96d7dccd4
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/no-xsave.patch
@@ -0,0 +1,85 @@
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -168,21 +168,23 @@ static void __init xen_banner(void)
+ 	       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,
+ 		      unsigned int *cx, unsigned int *dx)
+ {
++	unsigned maskecx = ~0;
+ 	unsigned maskedx = ~0;
+ 
+ 	/*
+ 	 * Mask out inconvenient features, to try and disable as many
+ 	 * unsupported kernel subsystems as possible.
+ 	 */
+-	if (*ax == 1)
+-		maskedx = ~((1 << X86_FEATURE_APIC) |  /* disable APIC */
+-			    (1 << X86_FEATURE_ACPI) |  /* disable ACPI */
+-			    (1 << X86_FEATURE_MCE)  |  /* disable MCE */
+-			    (1 << X86_FEATURE_MCA)  |  /* disable MCA */
+-			    (1 << X86_FEATURE_ACC));   /* thermal monitoring */
++	if (*ax == 1) {
++		maskecx = cpuid_leaf1_ecx_mask;
++		maskedx = cpuid_leaf1_edx_mask;
++	}
+ 
+ 	asm(XEN_EMULATE_PREFIX "cpuid"
+ 		: "=a" (*ax),
+@@ -190,9 +192,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
+ 		  "=c" (*cx),
+ 		  "=d" (*dx)
+ 		: "0" (*ax), "2" (*cx));
++
++	*cx &= maskecx;
+ 	*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)
+ {
+ 	HYPERVISOR_set_debugreg(reg, val);
+@@ -903,6 +939,8 @@ asmlinkage void __init xen_start_kernel(void)
+ 
+ 	xen_init_irq_ops();
+ 
++	xen_init_cpuid_mask();
++
+ #ifdef CONFIG_X86_LOCAL_APIC
+ 	/*
+ 	 * set up the basic apic ops.