summaryrefslogtreecommitdiff
path: root/i386
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2020-11-28 17:57:21 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-11-28 18:35:40 +0100
commit0e59d87e06f967680d250b9a74d08da1389b6212 (patch)
treef1daffaca55b607ba9c60a4ae04444e52b95a362 /i386
parentb885c5ea26fb3c2f2d91b6e9a1495070da429ea4 (diff)
x86: Extend XSAVE support to unbound state
* i386/i386/fpu.c (fp_xsave_size): New variable. (init_fpu): Save XSAVE size to fp_xsave_size. (fpu_module_init): Pass fp_xsave_size as size to kmem_cache_init. (fpu_set_state, fp_load, fp_state_alloc): Use fp_xsave_size to clear ifps. * i386/include/mach/i386/fp_reg.h (struct i386_xfp_save): Replace static fp_yreg_word with extended field. * i386/i386/thread.h (struct i386_fpsave_state): Make fp_valid field first in the structure to let the extended finish the structure.
Diffstat (limited to 'i386')
-rw-r--r--i386/i386/fpu.c25
-rw-r--r--i386/i386/thread.h3
-rw-r--r--i386/include/mach/i386/fp_reg.h7
3 files changed, 12 insertions, 23 deletions
diff --git a/i386/i386/fpu.c b/i386/i386/fpu.c
index 517764d6..3961f17b 100644
--- a/i386/i386/fpu.c
+++ b/i386/i386/fpu.c
@@ -71,6 +71,7 @@
int fp_kind = FP_387; /* 80387 present */
uint64_t fp_xsave_support; /* Bitmap of supported XSAVE save areas */
+unsigned fp_xsave_size = sizeof(struct i386_fpsave_state);
struct kmem_cache ifps_cache; /* cache for FPU save area */
static unsigned long mxcsr_feature_mask = 0xffffffff; /* Always AND user-provided mxcsr with this security mask */
@@ -168,22 +169,12 @@ init_fpu(void)
eax = 0xd;
ecx = 0x0;
cpuid(eax, ebx, ecx, edx);
+ fp_xsave_size = offsetof(struct i386_fpsave_state, xfp_save_state) + ebx;
- if (ebx > sizeof(struct i386_xfp_save)) {
- /* TODO: rather make struct unbound and set size
- * in fpu_module_init */
- printf("XSAVE area size %u larger than provisioned "
- "%u, not enabling XSAVE\n",
- ebx, sizeof(struct i386_xfp_save));
-#ifndef MACH_RING1
- set_cr4(get_cr4() & ~(CR4_OSFXSR | CR4_OSXSAVE));
-#endif /* MACH_RING1 */
- } else {
- fp_kind = FP_387X;
- }
+ fp_kind = FP_387X;
}
- if (fp_kind == FP_387 && CPU_HAS_FEATURE(CPU_FEATURE_FXSR)) {
+ else if (CPU_HAS_FEATURE(CPU_FEATURE_FXSR)) {
#ifndef MACH_RING1
set_cr4(get_cr4() | CR4_OSFXSR);
#endif /* MACH_RING1 */
@@ -226,7 +217,7 @@ void
fpu_module_init(void)
{
kmem_cache_init(&ifps_cache, "i386_fpsave_state",
- sizeof(struct i386_fpsave_state),
+ fp_xsave_size,
alignof(struct i386_fpsave_state),
NULL, 0);
}
@@ -398,7 +389,7 @@ ASSERT_IPL(SPL0);
/*
* Ensure that reserved parts of the environment are 0.
*/
- memset(ifps, 0, sizeof(*ifps));
+ memset(ifps, 0, fp_xsave_size);
if (fp_kind == FP_387X || fp_kind == FP_387FX) {
int i;
@@ -842,7 +833,7 @@ ASSERT_IPL(SPL0);
ifps = pcb->ims.ifps;
if (ifps == 0) {
ifps = (struct i386_fpsave_state *) kmem_cache_alloc(&ifps_cache);
- memset(ifps, 0, sizeof *ifps);
+ memset(ifps, 0, fp_xsave_size);
pcb->ims.ifps = ifps;
fpinit(thread);
#if 1
@@ -895,7 +886,7 @@ fp_state_alloc(void)
struct i386_fpsave_state *ifps;
ifps = (struct i386_fpsave_state *)kmem_cache_alloc(&ifps_cache);
- memset(ifps, 0, sizeof *ifps);
+ memset(ifps, 0, fp_xsave_size);
pcb->ims.ifps = ifps;
ifps->fp_valid = TRUE;
diff --git a/i386/i386/thread.h b/i386/i386/thread.h
index 3d4808c7..4a9c1987 100644
--- a/i386/i386/thread.h
+++ b/i386/i386/thread.h
@@ -129,6 +129,8 @@ struct i386_kernel_state {
*/
struct i386_fpsave_state {
+ boolean_t fp_valid;
+
union {
struct {
struct i386_fp_save fp_save_state;
@@ -136,7 +138,6 @@ struct i386_fpsave_state {
};
struct i386_xfp_save xfp_save_state;
};
- boolean_t fp_valid;
};
/*
diff --git a/i386/include/mach/i386/fp_reg.h b/i386/include/mach/i386/fp_reg.h
index 5992ea78..41301ec4 100644
--- a/i386/include/mach/i386/fp_reg.h
+++ b/i386/include/mach/i386/fp_reg.h
@@ -79,12 +79,9 @@ struct i386_xfp_save {
/* space for 16 128-bit XMM registers */
unsigned int padding[24];
struct i386_xfp_xstate_header header;
-
- unsigned char fp_yreg_word[16][16];
- /* space for the high part of the
- * 16 256-bit YMM registers */
+ unsigned char extended[0]; /* Extended region */
} __attribute__((packed, aligned(64)));
-_Static_assert(sizeof(struct i386_xfp_save) == 512 + 8*8 + 16*16);
+_Static_assert(sizeof(struct i386_xfp_save) == 512 + 8*8);
/*
* Control register