Merge branch 'x86-xsave-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/xsave changes from Peter Anvin: "This is a patchset to support the XSAVES instruction required to support context switch of supervisor-only features in upcoming silicon. This patchset missed the 3.16 merge window, which is why it is based on 3.15-rc7" * 'x86-xsave-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, xsave: Add forgotten inline annotation x86/xsaves: Clean up code in xstate offsets computation in xsave area x86/xsave: Make it clear that the XSAVE macros use (%edi)/(%rdi) Define kernel API to get address of each state in xsave area x86/xsaves: Enable xsaves/xrstors x86/xsaves: Call booting time xsaves and xrstors in setup_init_fpu_buf x86/xsaves: Save xstate to task's xsave area in __save_fpu during booting time x86/xsaves: Add xsaves and xrstors support for booting time x86/xsaves: Clear reserved bits in xsave header x86/xsaves: Use xsave/xrstor for saving and restoring user space context x86/xsaves: Use xsaves/xrstors for context switch x86/xsaves: Use xsaves/xrstors to save and restore xsave area x86/xsaves: Define a macro for handling xsave/xrstor instruction fault x86/xsaves: Define macros for xsave instructions x86/xsaves: Change compacted format xsave area header x86/alternative: Add alternative_input_2 to support alternative with two features and input x86/xsaves: Add a kernel parameter noxsaves to disable xsaves/xrstors
This commit is contained in:
@@ -148,6 +148,7 @@ static int __init x86_xsave_setup(char *s)
|
||||
{
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVE);
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVES);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX);
|
||||
setup_clear_cpu_cap(X86_FEATURE_AVX2);
|
||||
return 1;
|
||||
@@ -161,6 +162,13 @@ static int __init x86_xsaveopt_setup(char *s)
|
||||
}
|
||||
__setup("noxsaveopt", x86_xsaveopt_setup);
|
||||
|
||||
static int __init x86_xsaves_setup(char *s)
|
||||
{
|
||||
setup_clear_cpu_cap(X86_FEATURE_XSAVES);
|
||||
return 1;
|
||||
}
|
||||
__setup("noxsaves", x86_xsaves_setup);
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
static int cachesize_override = -1;
|
||||
static int disable_x86_serial_nr = 1;
|
||||
|
@@ -375,7 +375,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
|
||||
/*
|
||||
* These bits must be zero.
|
||||
*/
|
||||
xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
|
||||
memset(xsave_hdr->reserved, 0, 48);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -93,6 +93,7 @@ void arch_task_cache_init(void)
|
||||
kmem_cache_create("task_xstate", xstate_size,
|
||||
__alignof__(union thread_xstate),
|
||||
SLAB_PANIC | SLAB_NOTRACK, NULL);
|
||||
setup_xstate_comp();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/i387.h>
|
||||
#include <asm/fpu-internal.h>
|
||||
#include <asm/sigframe.h>
|
||||
@@ -24,7 +25,9 @@ u64 pcntxt_mask;
|
||||
struct xsave_struct *init_xstate_buf;
|
||||
|
||||
static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32;
|
||||
static unsigned int *xstate_offsets, *xstate_sizes, xstate_features;
|
||||
static unsigned int *xstate_offsets, *xstate_sizes;
|
||||
static unsigned int xstate_comp_offsets[sizeof(pcntxt_mask)*8];
|
||||
static unsigned int xstate_features;
|
||||
|
||||
/*
|
||||
* If a processor implementation discern that a processor state component is
|
||||
@@ -283,7 +286,7 @@ sanitize_restored_xstate(struct task_struct *tsk,
|
||||
|
||||
if (use_xsave()) {
|
||||
/* These bits must be zero. */
|
||||
xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
|
||||
memset(xsave_hdr->reserved, 0, 48);
|
||||
|
||||
/*
|
||||
* Init the state that is not present in the memory
|
||||
@@ -478,6 +481,52 @@ static void __init setup_xstate_features(void)
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets up offsets and sizes of all extended states in
|
||||
* xsave area. This supports both standard format and compacted format
|
||||
* of the xsave aread.
|
||||
*
|
||||
* Input: void
|
||||
* Output: void
|
||||
*/
|
||||
void setup_xstate_comp(void)
|
||||
{
|
||||
unsigned int xstate_comp_sizes[sizeof(pcntxt_mask)*8];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The FP xstates and SSE xstates are legacy states. They are always
|
||||
* in the fixed offsets in the xsave area in either compacted form
|
||||
* or standard form.
|
||||
*/
|
||||
xstate_comp_offsets[0] = 0;
|
||||
xstate_comp_offsets[1] = offsetof(struct i387_fxsave_struct, xmm_space);
|
||||
|
||||
if (!cpu_has_xsaves) {
|
||||
for (i = 2; i < xstate_features; i++) {
|
||||
if (test_bit(i, (unsigned long *)&pcntxt_mask)) {
|
||||
xstate_comp_offsets[i] = xstate_offsets[i];
|
||||
xstate_comp_sizes[i] = xstate_sizes[i];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
xstate_comp_offsets[2] = FXSAVE_SIZE + XSAVE_HDR_SIZE;
|
||||
|
||||
for (i = 2; i < xstate_features; i++) {
|
||||
if (test_bit(i, (unsigned long *)&pcntxt_mask))
|
||||
xstate_comp_sizes[i] = xstate_sizes[i];
|
||||
else
|
||||
xstate_comp_sizes[i] = 0;
|
||||
|
||||
if (i > 2)
|
||||
xstate_comp_offsets[i] = xstate_comp_offsets[i-1]
|
||||
+ xstate_comp_sizes[i-1];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* setup the xstate image representing the init state
|
||||
*/
|
||||
@@ -496,15 +545,21 @@ static void __init setup_init_fpu_buf(void)
|
||||
|
||||
setup_xstate_features();
|
||||
|
||||
if (cpu_has_xsaves) {
|
||||
init_xstate_buf->xsave_hdr.xcomp_bv =
|
||||
(u64)1 << 63 | pcntxt_mask;
|
||||
init_xstate_buf->xsave_hdr.xstate_bv = pcntxt_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init all the features state with header_bv being 0x0
|
||||
*/
|
||||
xrstor_state(init_xstate_buf, -1);
|
||||
xrstor_state_booting(init_xstate_buf, -1);
|
||||
/*
|
||||
* Dump the init state again. This is to identify the init state
|
||||
* of any feature which is not represented by all zero's.
|
||||
*/
|
||||
xsave_state(init_xstate_buf, -1);
|
||||
xsave_state_booting(init_xstate_buf, -1);
|
||||
}
|
||||
|
||||
static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO;
|
||||
@@ -520,6 +575,30 @@ static int __init eager_fpu_setup(char *s)
|
||||
}
|
||||
__setup("eagerfpu=", eager_fpu_setup);
|
||||
|
||||
|
||||
/*
|
||||
* Calculate total size of enabled xstates in XCR0/pcntxt_mask.
|
||||
*/
|
||||
static void __init init_xstate_size(void)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
int i;
|
||||
|
||||
if (!cpu_has_xsaves) {
|
||||
cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
|
||||
xstate_size = ebx;
|
||||
return;
|
||||
}
|
||||
|
||||
xstate_size = FXSAVE_SIZE + XSAVE_HDR_SIZE;
|
||||
for (i = 2; i < 64; i++) {
|
||||
if (test_bit(i, (unsigned long *)&pcntxt_mask)) {
|
||||
cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
|
||||
xstate_size += eax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable and initialize the xsave feature.
|
||||
*/
|
||||
@@ -551,8 +630,7 @@ static void __init xstate_enable_boot_cpu(void)
|
||||
/*
|
||||
* Recompute the context size for enabled features
|
||||
*/
|
||||
cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
|
||||
xstate_size = ebx;
|
||||
init_xstate_size();
|
||||
|
||||
update_regset_xstate_info(xstate_size, pcntxt_mask);
|
||||
prepare_fx_sw_frame();
|
||||
@@ -572,8 +650,9 @@ static void __init xstate_enable_boot_cpu(void)
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n",
|
||||
pcntxt_mask, xstate_size);
|
||||
pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x using %s\n",
|
||||
pcntxt_mask, xstate_size,
|
||||
cpu_has_xsaves ? "compacted form" : "standard form");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -635,3 +714,26 @@ void eager_fpu_init(void)
|
||||
else
|
||||
fxrstor_checking(&init_xstate_buf->i387);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given the xsave area and a state inside, this function returns the
|
||||
* address of the state.
|
||||
*
|
||||
* This is the API that is called to get xstate address in either
|
||||
* standard format or compacted format of xsave area.
|
||||
*
|
||||
* Inputs:
|
||||
* xsave: base address of the xsave area;
|
||||
* xstate: state which is defined in xsave.h (e.g. XSTATE_FP, XSTATE_SSE,
|
||||
* etc.)
|
||||
* Output:
|
||||
* address of the state in the xsave area.
|
||||
*/
|
||||
void *get_xsave_addr(struct xsave_struct *xsave, int xstate)
|
||||
{
|
||||
int feature = fls64(xstate) - 1;
|
||||
if (!test_bit(feature, (unsigned long *)&pcntxt_mask))
|
||||
return NULL;
|
||||
|
||||
return (void *)xsave + xstate_comp_offsets[feature];
|
||||
}
|
||||
|
Reference in New Issue
Block a user