summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-05-01 20:08:33 +0000
committerkib <kib@FreeBSD.org>2013-05-01 20:08:33 +0000
commit19e5409088a95e1f704e9a1b2e7737b3e76608e9 (patch)
tree730a74a31b960be15b91ca3be2da88007568ab74 /sys/amd64
parentf2ccbf32fb7a03af96b0eea6b63aebb4591a37ea (diff)
downloadFreeBSD-src-19e5409088a95e1f704e9a1b2e7737b3e76608e9.zip
FreeBSD-src-19e5409088a95e1f704e9a1b2e7737b3e76608e9.tar.gz
Partially saved extended state must be handled always, i.e. for both
fpu-owned context, and for pcb-saved one. More, the XSAVE could do partial save, same as XSAVEOPT, so qualifier for the handler should be use_xsave and not use_xsaveopt. Since xsave_area_desc is now needed regardless of the XSAVEOPT use, remove the write-only use_xsaveopt variable. In collaboration with: jhb MFC after: 1 week
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/fpu.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index 7bc0a6f..de79baa 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -132,7 +132,6 @@ static void fpu_clean_state(void);
SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
NULL, 1, "Floating point instructions executed in hardware");
-static int use_xsaveopt;
int use_xsave; /* non-static for cpu_switch.S */
uint64_t xsave_mask; /* the same */
static uma_zone_t fpu_save_area_zone;
@@ -198,7 +197,6 @@ fpuinit_bsp1(void)
* REX byte, and set the bit 4 of the r/m byte.
*/
ctx_switch_xsave[3] |= 0x10;
- use_xsaveopt = 1;
}
}
@@ -296,7 +294,7 @@ fpuinitstate(void *arg __unused)
* Create a table describing the layout of the CPU Extended
* Save Area.
*/
- if (use_xsaveopt) {
+ if (use_xsave) {
max_ext_n = flsl(xsave_mask);
xsave_area_desc = malloc(max_ext_n * sizeof(struct
xsave_area_elm_descr), M_DEVBUF, M_WAITOK | M_ZERO);
@@ -661,7 +659,7 @@ fpugetregs(struct thread *td)
struct pcb *pcb;
uint64_t *xstate_bv, bit;
char *sa;
- int max_ext_n, i;
+ int max_ext_n, i, owned;
pcb = td->td_pcb;
if ((pcb->pcb_flags & PCB_USERFPUINITDONE) == 0) {
@@ -675,31 +673,31 @@ fpugetregs(struct thread *td)
critical_enter();
if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
fpusave(get_pcb_user_save_pcb(pcb));
- critical_exit();
- return (_MC_FPOWNED_FPU);
+ owned = _MC_FPOWNED_FPU;
} else {
- critical_exit();
- if (use_xsaveopt) {
- /*
- * Handle partially saved state.
- */
- sa = (char *)get_pcb_user_save_pcb(pcb);
- xstate_bv = (uint64_t *)(sa + sizeof(struct savefpu) +
- offsetof(struct xstate_hdr, xstate_bv));
- max_ext_n = flsl(xsave_mask);
- for (i = 0; i < max_ext_n; i++) {
- bit = 1 << i;
- if ((*xstate_bv & bit) != 0)
- continue;
- bcopy((char *)fpu_initialstate +
- xsave_area_desc[i].offset,
- sa + xsave_area_desc[i].offset,
- xsave_area_desc[i].size);
- *xstate_bv |= bit;
- }
+ owned = _MC_FPOWNED_PCB;
+ }
+ critical_exit();
+ if (use_xsave) {
+ /*
+ * Handle partially saved state.
+ */
+ sa = (char *)get_pcb_user_save_pcb(pcb);
+ xstate_bv = (uint64_t *)(sa + sizeof(struct savefpu) +
+ offsetof(struct xstate_hdr, xstate_bv));
+ max_ext_n = flsl(xsave_mask);
+ for (i = 0; i < max_ext_n; i++) {
+ bit = 1 << i;
+ if ((*xstate_bv & bit) != 0)
+ continue;
+ bcopy((char *)fpu_initialstate +
+ xsave_area_desc[i].offset,
+ sa + xsave_area_desc[i].offset,
+ xsave_area_desc[i].size);
+ *xstate_bv |= bit;
}
- return (_MC_FPOWNED_PCB);
}
+ return (owned);
}
void
OpenPOWER on IntegriCloud