aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2009-03-07 20:09:27 -0500
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2009-03-30 12:25:28 -0400
commite826fe1ba1563a9272345da8e3279a930ac160a7 (patch)
treed92e3d019424a4d2cf7bcd76b252fd6ff57b1eab /arch/x86/xen
parente9e2d1ffcfdb38bed11a3064aa74bea9ee38ed80 (diff)
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: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Diffstat (limited to 'arch/x86/xen')
-rw-r--r--arch/x86/xen/enlighten.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 75b7a0f90380..da33e0c5870d 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -168,21 +168,23 @@ static void __init xen_banner(void)
168 xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); 168 xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
169} 169}
170 170
171static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
172static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
173
171static void xen_cpuid(unsigned int *ax, unsigned int *bx, 174static void xen_cpuid(unsigned int *ax, unsigned int *bx,
172 unsigned int *cx, unsigned int *dx) 175 unsigned int *cx, unsigned int *dx)
173{ 176{
177 unsigned maskecx = ~0;
174 unsigned maskedx = ~0; 178 unsigned maskedx = ~0;
175 179
176 /* 180 /*
177 * Mask out inconvenient features, to try and disable as many 181 * Mask out inconvenient features, to try and disable as many
178 * unsupported kernel subsystems as possible. 182 * unsupported kernel subsystems as possible.
179 */ 183 */
180 if (*ax == 1) 184 if (*ax == 1) {
181 maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */ 185 maskecx = cpuid_leaf1_ecx_mask;
182 (1 << X86_FEATURE_ACPI) | /* disable ACPI */ 186 maskedx = cpuid_leaf1_edx_mask;
183 (1 << X86_FEATURE_MCE) | /* disable MCE */ 187 }
184 (1 << X86_FEATURE_MCA) | /* disable MCA */
185 (1 << X86_FEATURE_ACC)); /* thermal monitoring */
186 188
187 asm(XEN_EMULATE_PREFIX "cpuid" 189 asm(XEN_EMULATE_PREFIX "cpuid"
188 : "=a" (*ax), 190 : "=a" (*ax),
@@ -190,9 +192,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
190 "=c" (*cx), 192 "=c" (*cx),
191 "=d" (*dx) 193 "=d" (*dx)
192 : "0" (*ax), "2" (*cx)); 194 : "0" (*ax), "2" (*cx));
195
196 *cx &= maskecx;
193 *dx &= maskedx; 197 *dx &= maskedx;
194} 198}
195 199
200static __init void xen_init_cpuid_mask(void)
201{
202 unsigned int ax, bx, cx, dx;
203
204 cpuid_leaf1_edx_mask =
205 ~((1 << X86_FEATURE_MCE) | /* disable MCE */
206 (1 << X86_FEATURE_MCA) | /* disable MCA */
207 (1 << X86_FEATURE_ACC)); /* thermal monitoring */
208
209 if (!xen_initial_domain())
210 cpuid_leaf1_edx_mask &=
211 ~((1 << X86_FEATURE_APIC) | /* disable local APIC */
212 (1 << X86_FEATURE_ACPI)); /* disable ACPI */
213
214 ax = 1;
215 xen_cpuid(&ax, &bx, &cx, &dx);
216
217 /* cpuid claims we support xsave; try enabling it to see what happens */
218 if (cx & (1 << (X86_FEATURE_XSAVE % 32))) {
219 unsigned long cr4;
220
221 set_in_cr4(X86_CR4_OSXSAVE);
222
223 cr4 = read_cr4();
224
225 if ((cr4 & X86_CR4_OSXSAVE) == 0)
226 cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32));
227
228 clear_in_cr4(X86_CR4_OSXSAVE);
229 }
230}
231
196static void xen_set_debugreg(int reg, unsigned long val) 232static void xen_set_debugreg(int reg, unsigned long val)
197{ 233{
198 HYPERVISOR_set_debugreg(reg, val); 234 HYPERVISOR_set_debugreg(reg, val);
@@ -901,6 +937,8 @@ asmlinkage void __init xen_start_kernel(void)
901 937
902 xen_init_irq_ops(); 938 xen_init_irq_ops();
903 939
940 xen_init_cpuid_mask();
941
904#ifdef CONFIG_X86_LOCAL_APIC 942#ifdef CONFIG_X86_LOCAL_APIC
905 /* 943 /*
906 * set up the basic apic ops. 944 * set up the basic apic ops.