diff options
author | Fenghua Yu <fenghua.yu@intel.com> | 2014-05-29 14:12:43 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-05-29 17:33:07 -0400 |
commit | 7e7ce87f6ad4e1730364e5e76628b43c5759b700 (patch) | |
tree | d22269d21df21bf4f10f8e7f03ffcc3ecc87be3b /arch | |
parent | 47c2f292cc8669f70644a949cadd5fa5ee0e0e07 (diff) |
x86/xsaves: Enable xsaves/xrstors
If xsaves/xrstors is enabled, compacted format of xsave area will be used
and less memory may be used for context per process. And modified
optimization implemented in xsaves/xrstors improves performance of saving
xstate.
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Link: http://lkml.kernel.org/r/1401387164-43416-16-git-send-email-fenghua.yu@intel.com
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/xsave.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 8fa7c7d4183d..f930f8ab92d1 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/bootmem.h> | 9 | #include <linux/bootmem.h> |
10 | #include <linux/compat.h> | 10 | #include <linux/compat.h> |
11 | #include <linux/cpu.h> | ||
11 | #include <asm/i387.h> | 12 | #include <asm/i387.h> |
12 | #include <asm/fpu-internal.h> | 13 | #include <asm/fpu-internal.h> |
13 | #include <asm/sigframe.h> | 14 | #include <asm/sigframe.h> |
@@ -24,7 +25,9 @@ u64 pcntxt_mask; | |||
24 | struct xsave_struct *init_xstate_buf; | 25 | struct xsave_struct *init_xstate_buf; |
25 | 26 | ||
26 | static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32; | 27 | static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32; |
27 | static unsigned int *xstate_offsets, *xstate_sizes, xstate_features; | 28 | static unsigned int *xstate_offsets, *xstate_sizes; |
29 | static unsigned int *xstate_comp_offsets, *xstate_comp_sizes; | ||
30 | static unsigned int xstate_features; | ||
28 | 31 | ||
29 | /* | 32 | /* |
30 | * If a processor implementation discern that a processor state component is | 33 | * If a processor implementation discern that a processor state component is |
@@ -283,7 +286,7 @@ sanitize_restored_xstate(struct task_struct *tsk, | |||
283 | 286 | ||
284 | if (use_xsave()) { | 287 | if (use_xsave()) { |
285 | /* These bits must be zero. */ | 288 | /* These bits must be zero. */ |
286 | xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; | 289 | memset(xsave_hdr->reserved, 0, 48); |
287 | 290 | ||
288 | /* | 291 | /* |
289 | * Init the state that is not present in the memory | 292 | * Init the state that is not present in the memory |
@@ -526,6 +529,30 @@ static int __init eager_fpu_setup(char *s) | |||
526 | } | 529 | } |
527 | __setup("eagerfpu=", eager_fpu_setup); | 530 | __setup("eagerfpu=", eager_fpu_setup); |
528 | 531 | ||
532 | |||
533 | /* | ||
534 | * Calculate total size of enabled xstates in XCR0/pcntxt_mask. | ||
535 | */ | ||
536 | static void __init init_xstate_size(void) | ||
537 | { | ||
538 | unsigned int eax, ebx, ecx, edx; | ||
539 | int i; | ||
540 | |||
541 | if (!cpu_has_xsaves) { | ||
542 | cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx); | ||
543 | xstate_size = ebx; | ||
544 | return; | ||
545 | } | ||
546 | |||
547 | xstate_size = FXSAVE_SIZE + XSAVE_HDR_SIZE; | ||
548 | for (i = 2; i < 64; i++) { | ||
549 | if (test_bit(i, (unsigned long *)&pcntxt_mask)) { | ||
550 | cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx); | ||
551 | xstate_size += eax; | ||
552 | } | ||
553 | } | ||
554 | } | ||
555 | |||
529 | /* | 556 | /* |
530 | * Enable and initialize the xsave feature. | 557 | * Enable and initialize the xsave feature. |
531 | */ | 558 | */ |
@@ -557,8 +584,7 @@ static void __init xstate_enable_boot_cpu(void) | |||
557 | /* | 584 | /* |
558 | * Recompute the context size for enabled features | 585 | * Recompute the context size for enabled features |
559 | */ | 586 | */ |
560 | cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx); | 587 | init_xstate_size(); |
561 | xstate_size = ebx; | ||
562 | 588 | ||
563 | update_regset_xstate_info(xstate_size, pcntxt_mask); | 589 | update_regset_xstate_info(xstate_size, pcntxt_mask); |
564 | prepare_fx_sw_frame(); | 590 | prepare_fx_sw_frame(); |
@@ -578,8 +604,9 @@ static void __init xstate_enable_boot_cpu(void) | |||
578 | } | 604 | } |
579 | } | 605 | } |
580 | 606 | ||
581 | pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n", | 607 | pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x using %s\n", |
582 | pcntxt_mask, xstate_size); | 608 | pcntxt_mask, xstate_size, |
609 | cpu_has_xsaves ? "compacted form" : "standard form"); | ||
583 | } | 610 | } |
584 | 611 | ||
585 | /* | 612 | /* |