Add support for passing FPU_KERN_NOCTX to fpu_kern_enter on arm64. This

will be used to call into UEFI from the kernel.

Sponsored by:	DARPA, AFRL
This commit is contained in:
andrew 2017-07-18 16:36:32 +00:00
parent 95bf54ddfc
commit 44e79a530d
3 changed files with 45 additions and 12 deletions

View File

@ -262,8 +262,28 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx, u_int flags)
struct pcb *pcb;
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_fpflags & PCB_FP_NOSAVE) == 0,
("recursive fpu_kern_enter while in PCB_FP_NOSAVE state"));
if ((flags & FPU_KERN_NOCTX) != 0) {
critical_enter();
if (curthread == PCPU_GET(fpcurthread)) {
vfp_save_state(curthread, pcb);
PCPU_SET(fpcurthread, NULL);
} else {
KASSERT(PCPU_GET(fpcurthread) == NULL,
("invalid fpcurthread"));
}
vfp_enable();
pcb->pcb_fpflags |= PCB_FP_KERN | PCB_FP_NOSAVE |
PCB_FP_STARTED;
return (0);
}
if ((flags & FPU_KERN_KTHR) != 0 && is_fpu_kern_thread(0)) {
ctx->flags = FPU_KERN_CTX_DUMMY | FPU_KERN_CTX_INUSE;
@ -293,19 +313,30 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx)
pcb = td->td_pcb;
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
("FPU context not inuse"));
ctx->flags &= ~FPU_KERN_CTX_INUSE;
if ((pcb->pcb_fpflags & PCB_FP_NOSAVE) != 0) {
KASSERT(ctx == NULL, ("non-null ctx after FPU_KERN_NOCTX"));
KASSERT(PCPU_GET(fpcurthread) == NULL,
("non-NULL fpcurthread for PCB_FP_NOSAVE"));
CRITICAL_ASSERT(td);
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();
vfp_discard(td);
critical_exit();
pcb->pcb_fpflags &= ~PCB_FP_STARTED;
pcb->pcb_fpusaved = ctx->prev;
vfp_disable();
pcb->pcb_fpflags &= ~(PCB_FP_NOSAVE | PCB_FP_STARTED);
critical_exit();
} else {
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
("FPU context not inuse"));
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();
vfp_discard(td);
critical_exit();
pcb->pcb_fpflags &= ~PCB_FP_STARTED;
pcb->pcb_fpusaved = ctx->prev;
}
if (pcb->pcb_fpusaved == &pcb->pcb_fpustate) {
pcb->pcb_fpflags &= ~PCB_FP_KERN;

View File

@ -56,6 +56,7 @@ struct pcb {
int pcb_fpflags;
#define PCB_FP_STARTED 0x01
#define PCB_FP_KERN 0x02
#define PCB_FP_NOSAVE 0x04
/* The bits passed to userspace in get_fpcontext */
#define PCB_FP_USERMASK (PCB_FP_STARTED)
u_int pcb_vfpcpu; /* Last cpu this thread ran VFP code */

View File

@ -56,6 +56,7 @@ struct fpu_kern_ctx;
#define FPU_KERN_NORMAL 0x0000
#define FPU_KERN_NOWAIT 0x0001
#define FPU_KERN_KTHR 0x0002
#define FPU_KERN_NOCTX 0x0004
struct fpu_kern_ctx *fpu_kern_alloc_ctx(u_int);
void fpu_kern_free_ctx(struct fpu_kern_ctx *);