svn commit: r337245 - in stable/10/sys: amd64/amd64 i386/i386 i386/isa
Konstantin Belousov
kib at FreeBSD.org
Fri Aug 3 14:12:39 UTC 2018
Author: kib
Date: Fri Aug 3 14:12:37 2018
New Revision: 337245
URL: https://svnweb.freebsd.org/changeset/base/337245
Log:
MFC r336683:
Extend ranges of the critical sections to ensure that context switch
code never sees FPU pcb flags not consistent with the hardware state.
Modified:
stable/10/sys/amd64/amd64/fpu.c
stable/10/sys/amd64/amd64/machdep.c
stable/10/sys/i386/i386/machdep.c
stable/10/sys/i386/isa/npx.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/amd64/amd64/fpu.c
==============================================================================
--- stable/10/sys/amd64/amd64/fpu.c Fri Aug 3 14:08:39 2018 (r337244)
+++ stable/10/sys/amd64/amd64/fpu.c Fri Aug 3 14:12:37 2018 (r337245)
@@ -741,22 +741,22 @@ fpugetregs(struct thread *td)
int max_ext_n, i, owned;
pcb = td->td_pcb;
+ critical_enter();
if ((pcb->pcb_flags & PCB_USERFPUINITDONE) == 0) {
bcopy(fpu_initialstate, get_pcb_user_save_pcb(pcb),
cpu_max_ext_state_size);
get_pcb_user_save_pcb(pcb)->sv_env.en_cw =
pcb->pcb_initial_fpucw;
fpuuserinited(td);
+ critical_exit();
return (_MC_FPOWNED_PCB);
}
- critical_enter();
if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
fpusave(get_pcb_user_save_pcb(pcb));
owned = _MC_FPOWNED_FPU;
} else {
owned = _MC_FPOWNED_PCB;
}
- critical_exit();
if (use_xsave) {
/*
* Handle partially saved state.
@@ -776,6 +776,7 @@ fpugetregs(struct thread *td)
*xstate_bv |= bit;
}
}
+ critical_exit();
return (owned);
}
@@ -784,6 +785,7 @@ fpuuserinited(struct thread *td)
{
struct pcb *pcb;
+ CRITICAL_ASSERT(td);
pcb = td->td_pcb;
if (PCB_USER_FPU(pcb))
set_pcb_flags(pcb,
@@ -842,26 +844,25 @@ fpusetregs(struct thread *td, struct savefpu *addr, ch
addr->sv_env.en_mxcsr &= cpu_mxcsr_mask;
pcb = td->td_pcb;
+ error = 0;
critical_enter();
if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
error = fpusetxstate(td, xfpustate, xfpustate_size);
- if (error != 0) {
- critical_exit();
- return (error);
+ if (error == 0) {
+ bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
+ fpurestore(get_pcb_user_save_td(td));
+ set_pcb_flags(pcb, PCB_FPUINITDONE |
+ PCB_USERFPUINITDONE);
}
- bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
- fpurestore(get_pcb_user_save_td(td));
- critical_exit();
- set_pcb_flags(pcb, PCB_FPUINITDONE | PCB_USERFPUINITDONE);
} else {
- critical_exit();
error = fpusetxstate(td, xfpustate, xfpustate_size);
- if (error != 0)
- return (error);
- bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
- fpuuserinited(td);
+ if (error == 0) {
+ bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
+ fpuuserinited(td);
+ }
}
- return (0);
+ critical_exit();
+ return (error);
}
/*
@@ -1004,6 +1005,7 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx
return (0);
}
pcb = td->td_pcb;
+ critical_enter();
KASSERT(!PCB_USER_FPU(pcb) || pcb->pcb_save ==
get_pcb_user_save_pcb(pcb), ("mangled pcb_save"));
ctx->flags = 0;
@@ -1014,6 +1016,7 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx
pcb->pcb_save = fpu_kern_ctx_savefpu(ctx);
set_pcb_flags(pcb, PCB_KERNFPU);
clear_pcb_flags(pcb, PCB_FPUINITDONE);
+ critical_exit();
return (0);
}
@@ -1029,7 +1032,6 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx
critical_enter();
if (curthread == PCPU_GET(fpcurthread))
fpudrop();
- critical_exit();
pcb->pcb_save = ctx->prev;
if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
if ((pcb->pcb_flags & PCB_USERFPUINITDONE) != 0) {
@@ -1044,6 +1046,7 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx
clear_pcb_flags(pcb, PCB_FPUINITDONE);
KASSERT(!PCB_USER_FPU(pcb), ("unpaired fpu_kern_leave"));
}
+ critical_exit();
return (0);
}
Modified: stable/10/sys/amd64/amd64/machdep.c
==============================================================================
--- stable/10/sys/amd64/amd64/machdep.c Fri Aug 3 14:08:39 2018 (r337244)
+++ stable/10/sys/amd64/amd64/machdep.c Fri Aug 3 14:12:37 2018 (r337245)
@@ -2380,8 +2380,10 @@ int
set_fpregs(struct thread *td, struct fpreg *fpregs)
{
+ critical_enter();
set_fpregs_xmm(fpregs, get_pcb_user_save_td(td));
fpuuserinited(td);
+ critical_exit();
return (0);
}
Modified: stable/10/sys/i386/i386/machdep.c
==============================================================================
--- stable/10/sys/i386/i386/machdep.c Fri Aug 3 14:08:39 2018 (r337244)
+++ stable/10/sys/i386/i386/machdep.c Fri Aug 3 14:12:37 2018 (r337245)
@@ -3780,6 +3780,7 @@ int
set_fpregs(struct thread *td, struct fpreg *fpregs)
{
+ critical_enter();
#ifdef CPU_ENABLE_SSE
if (cpu_fxsr)
set_fpregs_xmm((struct save87 *)fpregs,
@@ -3791,6 +3792,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
#ifdef DEV_NPX
npxuserinited(td);
#endif
+ critical_exit();
return (0);
}
Modified: stable/10/sys/i386/isa/npx.c
==============================================================================
--- stable/10/sys/i386/isa/npx.c Fri Aug 3 14:08:39 2018 (r337244)
+++ stable/10/sys/i386/isa/npx.c Fri Aug 3 14:12:37 2018 (r337245)
@@ -1037,14 +1037,15 @@ npxgetregs(struct thread *td)
return (_MC_FPOWNED_NONE);
pcb = td->td_pcb;
+ critical_enter();
if ((pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
bcopy(npx_initialstate, get_pcb_user_save_pcb(pcb),
cpu_max_ext_state_size);
SET_FPU_CW(get_pcb_user_save_pcb(pcb), pcb->pcb_initial_npxcw);
npxuserinited(td);
+ critical_exit();
return (_MC_FPOWNED_PCB);
}
- critical_enter();
if (td == PCPU_GET(fpcurthread)) {
fpusave(get_pcb_user_save_pcb(pcb));
#ifdef CPU_ENABLE_SSE
@@ -1060,7 +1061,6 @@ npxgetregs(struct thread *td)
} else {
owned = _MC_FPOWNED_PCB;
}
- critical_exit();
#ifdef CPU_ENABLE_SSE
if (use_xsave) {
/*
@@ -1085,6 +1085,7 @@ npxgetregs(struct thread *td)
}
}
#endif
+ critical_exit();
return (owned);
}
@@ -1093,6 +1094,7 @@ npxuserinited(struct thread *td)
{
struct pcb *pcb;
+ CRITICAL_ASSERT(td);
pcb = td->td_pcb;
if (PCB_USER_FPU(pcb))
pcb->pcb_flags |= PCB_NPXINITDONE;
@@ -1156,32 +1158,32 @@ npxsetregs(struct thread *td, union savefpu *addr, cha
addr->sv_xmm.sv_env.en_mxcsr &= cpu_mxcsr_mask;
#endif
pcb = td->td_pcb;
+ error = 0;
critical_enter();
if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
#ifdef CPU_ENABLE_SSE
error = npxsetxstate(td, xfpustate, xfpustate_size);
- if (error != 0) {
- critical_exit();
- return (error);
- }
- if (!cpu_fxsr)
#endif
- fnclex(); /* As in npxdrop(). */
- bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
- fpurstor(get_pcb_user_save_td(td));
- critical_exit();
- pcb->pcb_flags |= PCB_NPXUSERINITDONE | PCB_NPXINITDONE;
+ if (error == 0) {
+#ifdef CPU_ENABLE_SSE
+ if (!cpu_fxsr)
+#endif
+ fnclex(); /* As in npxdrop(). */
+ bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
+ fpurstor(get_pcb_user_save_td(td));
+ pcb->pcb_flags |= PCB_NPXUSERINITDONE | PCB_NPXINITDONE;
+ }
} else {
- critical_exit();
#ifdef CPU_ENABLE_SSE
error = npxsetxstate(td, xfpustate, xfpustate_size);
- if (error != 0)
- return (error);
#endif
- bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
- npxuserinited(td);
+ if (error == 0) {
+ bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
+ npxuserinited(td);
+ }
}
- return (0);
+ critical_exit();
+ return (error);
}
static void
@@ -1350,6 +1352,7 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx
return (0);
}
pcb = td->td_pcb;
+ critical_enter();
KASSERT(!PCB_USER_FPU(pcb) || pcb->pcb_save ==
get_pcb_user_save_pcb(pcb), ("mangled pcb_save"));
ctx->flags = 0;
@@ -1360,6 +1363,7 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx
pcb->pcb_save = fpu_kern_ctx_savefpu(ctx);
pcb->pcb_flags |= PCB_KERNNPX;
pcb->pcb_flags &= ~PCB_NPXINITDONE;
+ critical_exit();
return (0);
}
@@ -1374,7 +1378,6 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx
critical_enter();
if (curthread == PCPU_GET(fpcurthread))
npxdrop();
- critical_exit();
pcb->pcb_save = ctx->prev;
if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
if ((pcb->pcb_flags & PCB_NPXUSERINITDONE) != 0)
@@ -1389,6 +1392,7 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx
pcb->pcb_flags &= ~PCB_NPXINITDONE;
KASSERT(!PCB_USER_FPU(pcb), ("unpaired fpu_kern_leave"));
}
+ critical_exit();
return (0);
}
More information about the svn-src-stable-10
mailing list