diff options
author | Juergen Gross <jgross@suse.com> | 2017-04-12 09:12:09 -0400 |
---|---|---|
committer | Juergen Gross <jgross@suse.com> | 2017-05-02 05:14:17 -0400 |
commit | 6807cf65f5ba6f2902ab64355d71506b9c14a9dd (patch) | |
tree | f7f5341e15ce11a16060437e22318fae27f5ebe9 | |
parent | e657fccb799b970bd1f152e22e13f20e0de7adb5 (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.c | 53 |
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 | ||
168 | static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; | ||
169 | |||
170 | static __read_mostly unsigned int cpuid_leaf5_ecx_val; | 168 | static __read_mostly unsigned int cpuid_leaf5_ecx_val; |
171 | static __read_mostly unsigned int cpuid_leaf5_edx_val; | 169 | static __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 | } |
211 | STACK_FRAME_NON_STANDARD(xen_cpuid); /* XEN_EMULATE_PREFIX */ | 204 | STACK_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 | } |
284 | static 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; | 278 | static 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 | ||
302 | static void __init xen_init_capabilities(void) | 302 | static 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 | ||
321 | static void xen_set_debugreg(int reg, unsigned long val) | 329 | static 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 |