aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYu-cheng Yu <yu-cheng.yu@intel.com>2016-06-17 16:07:16 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-10 11:12:10 -0400
commit1499ce2dd45afddea2e84f9f920890cf88384c4e (patch)
tree7e16a59bacb5752087ea420debf041c84f92e991
parent03482e08a87d24e5c8c23e6981c482e832cf3bdc (diff)
x86/fpu/xstate: Fix supervisor xstate component offset
CPUID function 0x0d, sub function (i, i > 1) returns in ebx the offset of xstate component i. Zero is returned for a supervisor state. A supervisor state can only be saved by XSAVES and XSAVES uses a compacted format. There is no fixed offset for a supervisor state. This patch checks and makes sure a supervisor state offset is not recorded or mis-used. This has no effect in practice as we currently use no supervisor states, but it would be good to fix. Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com> Reviewed-by: Dave Hansen <dave.hansen@intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Quentin Casasnovas <quentin.casasnovas@oracle.com> Cc: Ravi V. Shankar <ravi.v.shankar@intel.com> Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/81b29e40d35d4cec9f2511a856fe769f34935a3f.1466179491.git.yu-cheng.yu@intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/fpu/types.h1
-rw-r--r--arch/x86/include/asm/fpu/xstate.h3
-rw-r--r--arch/x86/kernel/fpu/xstate.c62
3 files changed, 43 insertions, 23 deletions
diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h
index 36b90bbfc69f..12dd648735b6 100644
--- a/arch/x86/include/asm/fpu/types.h
+++ b/arch/x86/include/asm/fpu/types.h
@@ -122,6 +122,7 @@ enum xfeature {
122#define XFEATURE_MASK_OPMASK (1 << XFEATURE_OPMASK) 122#define XFEATURE_MASK_OPMASK (1 << XFEATURE_OPMASK)
123#define XFEATURE_MASK_ZMM_Hi256 (1 << XFEATURE_ZMM_Hi256) 123#define XFEATURE_MASK_ZMM_Hi256 (1 << XFEATURE_ZMM_Hi256)
124#define XFEATURE_MASK_Hi16_ZMM (1 << XFEATURE_Hi16_ZMM) 124#define XFEATURE_MASK_Hi16_ZMM (1 << XFEATURE_Hi16_ZMM)
125#define XFEATURE_MASK_PT (1 << XFEATURE_PT_UNIMPLEMENTED_SO_FAR)
125#define XFEATURE_MASK_PKRU (1 << XFEATURE_PKRU) 126#define XFEATURE_MASK_PKRU (1 << XFEATURE_PKRU)
126 127
127#define XFEATURE_MASK_FPSSE (XFEATURE_MASK_FP | XFEATURE_MASK_SSE) 128#define XFEATURE_MASK_FPSSE (XFEATURE_MASK_FP | XFEATURE_MASK_SSE)
diff --git a/arch/x86/include/asm/fpu/xstate.h b/arch/x86/include/asm/fpu/xstate.h
index d812cf361282..92f376ccc999 100644
--- a/arch/x86/include/asm/fpu/xstate.h
+++ b/arch/x86/include/asm/fpu/xstate.h
@@ -18,6 +18,9 @@
18#define XSAVE_YMM_SIZE 256 18#define XSAVE_YMM_SIZE 256
19#define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET) 19#define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET)
20 20
21/* Supervisor features */
22#define XFEATURE_MASK_SUPERVISOR (XFEATURE_MASK_PT)
23
21/* Supported features which support lazy state saving */ 24/* Supported features which support lazy state saving */
22#define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ 25#define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \
23 XFEATURE_MASK_SSE | \ 26 XFEATURE_MASK_SSE | \
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 7963029cb4ad..02786fb7a1e8 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -112,6 +112,27 @@ int cpu_has_xfeatures(u64 xfeatures_needed, const char **feature_name)
112} 112}
113EXPORT_SYMBOL_GPL(cpu_has_xfeatures); 113EXPORT_SYMBOL_GPL(cpu_has_xfeatures);
114 114
115static int xfeature_is_supervisor(int xfeature_nr)
116{
117 /*
118 * We currently do not support supervisor states, but if
119 * we did, we could find out like this.
120 *
121 * SDM says: If state component 'i' is a user state component,
122 * ECX[0] return 0; if state component i is a supervisor
123 * state component, ECX[0] returns 1.
124 */
125 u32 eax, ebx, ecx, edx;
126
127 cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
128 return !!(ecx & 1);
129}
130
131static int xfeature_is_user(int xfeature_nr)
132{
133 return !xfeature_is_supervisor(xfeature_nr);
134}
135
115/* 136/*
116 * When executing XSAVEOPT (or other optimized XSAVE instructions), if 137 * When executing XSAVEOPT (or other optimized XSAVE instructions), if
117 * a processor implementation detects that an FPU state component is still 138 * a processor implementation detects that an FPU state component is still
@@ -230,7 +251,14 @@ static void __init setup_xstate_features(void)
230 continue; 251 continue;
231 252
232 cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx); 253 cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
233 xstate_offsets[i] = ebx; 254
255 /*
256 * If an xfeature is supervisor state, the offset
257 * in EBX is invalid. We leave it to -1.
258 */
259 if (xfeature_is_user(i))
260 xstate_offsets[i] = ebx;
261
234 xstate_sizes[i] = eax; 262 xstate_sizes[i] = eax;
235 /* 263 /*
236 * In our xstate size checks, we assume that the 264 * In our xstate size checks, we assume that the
@@ -375,32 +403,20 @@ static void __init setup_init_fpu_buf(void)
375 copy_xregs_to_kernel_booting(&init_fpstate.xsave); 403 copy_xregs_to_kernel_booting(&init_fpstate.xsave);
376} 404}
377 405
378static int xfeature_is_supervisor(int xfeature_nr)
379{
380 /*
381 * We currently do not support supervisor states, but if
382 * we did, we could find out like this.
383 *
384 * SDM says: If state component i is a user state component,
385 * ECX[0] return 0; if state component i is a supervisor
386 * state component, ECX[0] returns 1.
387 u32 eax, ebx, ecx, edx;
388 cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx;
389 return !!(ecx & 1);
390 */
391 return 0;
392}
393/*
394static int xfeature_is_user(int xfeature_nr)
395{
396 return !xfeature_is_supervisor(xfeature_nr);
397}
398*/
399
400static int xfeature_uncompacted_offset(int xfeature_nr) 406static int xfeature_uncompacted_offset(int xfeature_nr)
401{ 407{
402 u32 eax, ebx, ecx, edx; 408 u32 eax, ebx, ecx, edx;
403 409
410 /*
411 * Only XSAVES supports supervisor states and it uses compacted
412 * format. Checking a supervisor state's uncompacted offset is
413 * an error.
414 */
415 if (XFEATURE_MASK_SUPERVISOR & (1 << xfeature_nr)) {
416 WARN_ONCE(1, "No fixed offset for xstate %d\n", xfeature_nr);
417 return -1;
418 }
419
404 CHECK_XFEATURE(xfeature_nr); 420 CHECK_XFEATURE(xfeature_nr);
405 cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx); 421 cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
406 return ebx; 422 return ebx;