aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuergen Gross <jgross@suse.com>2017-04-12 09:12:09 -0400
committerJuergen Gross <jgross@suse.com>2017-05-02 05:14:17 -0400
commit6807cf65f5ba6f2902ab64355d71506b9c14a9dd (patch)
treef7f5341e15ce11a16060437e22318fae27f5ebe9
parente657fccb799b970bd1f152e22e13f20e0de7adb5 (diff)
x86/xen: use capabilities instead of fake cpuid values for xsave
When running as pv domain xen_cpuid() is being used instead of native_cpuid(). In xen_cpuid() the xsave feature availability is indicated by special casing the related cpuid leaf. Instead of delivering fake cpuid values set or clear the cpu capability bits for xsave instead. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Signed-off-by: Juergen Gross <jgross@suse.com>
-rw-r--r--arch/x86/xen/enlighten_pv.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 38dec28a8e6d..a732bc2b9dfc 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -165,8 +165,6 @@ xen_running_on_version_or_later(unsigned int major, unsigned int minor)
165 return false; 165 return false;
166} 166}
167 167
168static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
169
170static __read_mostly unsigned int cpuid_leaf5_ecx_val; 168static __read_mostly unsigned int cpuid_leaf5_ecx_val;
171static __read_mostly unsigned int cpuid_leaf5_edx_val; 169static __read_mostly unsigned int cpuid_leaf5_edx_val;
172 170
@@ -174,16 +172,12 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
174 unsigned int *cx, unsigned int *dx) 172 unsigned int *cx, unsigned int *dx)
175{ 173{
176 unsigned maskebx = ~0; 174 unsigned maskebx = ~0;
177 unsigned maskecx = ~0; 175
178 /* 176 /*
179 * Mask out inconvenient features, to try and disable as many 177 * Mask out inconvenient features, to try and disable as many
180 * unsupported kernel subsystems as possible. 178 * unsupported kernel subsystems as possible.
181 */ 179 */
182 switch (*ax) { 180 switch (*ax) {
183 case 1:
184 maskecx = cpuid_leaf1_ecx_mask;
185 break;
186
187 case CPUID_MWAIT_LEAF: 181 case CPUID_MWAIT_LEAF:
188 /* Synthesize the values.. */ 182 /* Synthesize the values.. */
189 *ax = 0; 183 *ax = 0;
@@ -206,7 +200,6 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
206 : "0" (*ax), "2" (*cx)); 200 : "0" (*ax), "2" (*cx));
207 201
208 *bx &= maskebx; 202 *bx &= maskebx;
209 *cx &= maskecx;
210} 203}
211STACK_FRAME_NON_STANDARD(xen_cpuid); /* XEN_EMULATE_PREFIX */ 204STACK_FRAME_NON_STANDARD(xen_cpuid); /* XEN_EMULATE_PREFIX */
212 205
@@ -281,22 +274,29 @@ static bool __init xen_check_mwait(void)
281 return false; 274 return false;
282#endif 275#endif
283} 276}
284static void __init xen_init_cpuid_mask(void)
285{
286 unsigned int ax, bx, cx, dx;
287 unsigned int xsave_mask;
288 277
289 ax = 1; 278static bool __init xen_check_xsave(void)
290 cx = 0; 279{
291 cpuid(1, &ax, &bx, &cx, &dx); 280 unsigned int err, eax, edx;
292
293 xsave_mask =
294 (1 << (X86_FEATURE_XSAVE % 32)) |
295 (1 << (X86_FEATURE_OSXSAVE % 32));
296 281
297 /* Xen will set CR4.OSXSAVE if supported and not disabled by force */ 282 /*
298 if ((cx & xsave_mask) != xsave_mask) 283 * Xen 4.0 and older accidentally leaked the host XSAVE flag into guest
299 cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */ 284 * view, despite not being able to support guests using the
285 * functionality. Probe for the actual availability of XSAVE by seeing
286 * whether xgetbv executes successfully or raises #UD.
287 */
288 asm volatile("1: .byte 0x0f,0x01,0xd0\n\t" /* xgetbv */
289 "xor %[err], %[err]\n"
290 "2:\n\t"
291 ".pushsection .fixup,\"ax\"\n\t"
292 "3: movl $1,%[err]\n\t"
293 "jmp 2b\n\t"
294 ".popsection\n\t"
295 _ASM_EXTABLE(1b, 3b)
296 : [err] "=r" (err), "=a" (eax), "=d" (edx)
297 : "c" (0));
298
299 return err == 0;
300} 300}
301 301
302static void __init xen_init_capabilities(void) 302static void __init xen_init_capabilities(void)
@@ -316,6 +316,14 @@ static void __init xen_init_capabilities(void)
316 setup_force_cpu_cap(X86_FEATURE_MWAIT); 316 setup_force_cpu_cap(X86_FEATURE_MWAIT);
317 else 317 else
318 setup_clear_cpu_cap(X86_FEATURE_MWAIT); 318 setup_clear_cpu_cap(X86_FEATURE_MWAIT);
319
320 if (xen_check_xsave()) {
321 setup_force_cpu_cap(X86_FEATURE_XSAVE);
322 setup_force_cpu_cap(X86_FEATURE_OSXSAVE);
323 } else {
324 setup_clear_cpu_cap(X86_FEATURE_XSAVE);
325 setup_clear_cpu_cap(X86_FEATURE_OSXSAVE);
326 }
319} 327}
320 328
321static void xen_set_debugreg(int reg, unsigned long val) 329static void xen_set_debugreg(int reg, unsigned long val)
@@ -1308,7 +1316,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
1308 xen_setup_gdt(0); 1316 xen_setup_gdt(0);
1309 1317
1310 xen_init_irq_ops(); 1318 xen_init_irq_ops();
1311 xen_init_cpuid_mask();
1312 xen_init_capabilities(); 1319 xen_init_capabilities();
1313 1320
1314#ifdef CONFIG_X86_LOCAL_APIC 1321#ifdef CONFIG_X86_LOCAL_APIC