Add support for FPU_KERN_NOCTX.
This mirrors the implementation on amd64. Reviewed by: kib Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D26754
This commit is contained in:
parent
4ef6ea38fc
commit
1775215f88
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=366673
@ -886,6 +886,9 @@ npxdna(void)
|
||||
return (0);
|
||||
td = curthread;
|
||||
critical_enter();
|
||||
|
||||
KASSERT((curpcb->pcb_flags & PCB_NPXNOSAVE) == 0,
|
||||
("npxdna while in fpu_kern_enter(FPU_KERN_NOCTX)"));
|
||||
if (__predict_false(PCPU_GET(fpcurthread) == td)) {
|
||||
/*
|
||||
* Some virtual machines seems to set %cr0.TS at
|
||||
@ -1390,8 +1393,34 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx, u_int flags)
|
||||
{
|
||||
struct pcb *pcb;
|
||||
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) == 0, ("using inuse ctx"));
|
||||
pcb = td->td_pcb;
|
||||
KASSERT((flags & FPU_KERN_NOCTX) != 0 || ctx != NULL,
|
||||
("ctx is required when !FPU_KERN_NOCTX"));
|
||||
KASSERT(ctx == NULL || (ctx->flags & FPU_KERN_CTX_INUSE) == 0,
|
||||
("using inuse ctx"));
|
||||
KASSERT((pcb->pcb_flags & PCB_NPXNOSAVE) == 0,
|
||||
("recursive fpu_kern_enter while in PCB_NPXNOSAVE state"));
|
||||
|
||||
if ((flags & FPU_KERN_NOCTX) != 0) {
|
||||
critical_enter();
|
||||
stop_emulating();
|
||||
if (curthread == PCPU_GET(fpcurthread)) {
|
||||
fpusave(curpcb->pcb_save);
|
||||
PCPU_SET(fpcurthread, NULL);
|
||||
} else {
|
||||
KASSERT(PCPU_GET(fpcurthread) == NULL,
|
||||
("invalid fpcurthread"));
|
||||
}
|
||||
|
||||
/*
|
||||
* This breaks XSAVEOPT tracker, but
|
||||
* PCB_NPXNOSAVE state is supposed to never need to
|
||||
* save FPU context at all.
|
||||
*/
|
||||
fpurstor(npx_initialstate);
|
||||
pcb->pcb_flags |= PCB_KERNNPX | PCB_NPXNOSAVE | PCB_NPXINITDONE;
|
||||
return;
|
||||
}
|
||||
if ((flags & FPU_KERN_KTHR) != 0 && is_fpu_kern_thread(0)) {
|
||||
ctx->flags = FPU_KERN_CTX_DUMMY | FPU_KERN_CTX_INUSE;
|
||||
return;
|
||||
@ -1416,17 +1445,32 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx)
|
||||
{
|
||||
struct pcb *pcb;
|
||||
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
|
||||
("leaving not inuse ctx"));
|
||||
ctx->flags &= ~FPU_KERN_CTX_INUSE;
|
||||
|
||||
if (is_fpu_kern_thread(0) && (ctx->flags & FPU_KERN_CTX_DUMMY) != 0)
|
||||
return (0);
|
||||
pcb = td->td_pcb;
|
||||
critical_enter();
|
||||
if (curthread == PCPU_GET(fpcurthread))
|
||||
npxdrop();
|
||||
pcb->pcb_save = ctx->prev;
|
||||
|
||||
if ((pcb->pcb_flags & PCB_NPXNOSAVE) != 0) {
|
||||
KASSERT(ctx == NULL, ("non-null ctx after FPU_KERN_NOCTX"));
|
||||
KASSERT(PCPU_GET(fpcurthread) == NULL,
|
||||
("non-NULL fpcurthread for PCB_NPXNOSAVE"));
|
||||
CRITICAL_ASSERT(td);
|
||||
|
||||
pcb->pcb_flags &= ~(PCB_NPXNOSAVE | PCB_NPXINITDONE);
|
||||
start_emulating();
|
||||
} else {
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
|
||||
("leaving not inuse ctx"));
|
||||
ctx->flags &= ~FPU_KERN_CTX_INUSE;
|
||||
|
||||
if (is_fpu_kern_thread(0) &&
|
||||
(ctx->flags & FPU_KERN_CTX_DUMMY) != 0)
|
||||
return (0);
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_DUMMY) == 0,
|
||||
("dummy ctx"));
|
||||
critical_enter();
|
||||
if (curthread == PCPU_GET(fpcurthread))
|
||||
npxdrop();
|
||||
pcb->pcb_save = ctx->prev;
|
||||
}
|
||||
|
||||
if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
|
||||
if ((pcb->pcb_flags & PCB_NPXUSERINITDONE) != 0)
|
||||
pcb->pcb_flags |= PCB_NPXINITDONE;
|
||||
|
@ -92,6 +92,7 @@ void fpu_save_area_reset(union savefpu *fsa);
|
||||
#define FPU_KERN_NORMAL 0x0000
|
||||
#define FPU_KERN_NOWAIT 0x0001
|
||||
#define FPU_KERN_KTHR 0x0002
|
||||
#define FPU_KERN_NOCTX 0x0004
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -86,6 +86,7 @@ struct pcb {
|
||||
#define PCB_VM86CALL 0x10 /* in vm86 call */
|
||||
#define PCB_NPXUSERINITDONE 0x20 /* user fpu state is initialized */
|
||||
#define PCB_KERNNPX 0x40 /* kernel uses npx */
|
||||
#define PCB_NPXNOSAVE 0x80 /* no save area for current FPU ctx */
|
||||
|
||||
uint16_t pcb_initial_npxcw;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user