Changeset View
Changeset View
Standalone View
Standalone View
head/sys/i386/isa/npx.c
Show First 20 Lines • Show All 1,353 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
#endif /* DEV_ISA */ | #endif /* DEV_ISA */ | ||||
static MALLOC_DEFINE(M_FPUKERN_CTX, "fpukern_ctx", | static MALLOC_DEFINE(M_FPUKERN_CTX, "fpukern_ctx", | ||||
"Kernel contexts for FPU state"); | "Kernel contexts for FPU state"); | ||||
#define FPU_KERN_CTX_NPXINITDONE 0x01 | #define FPU_KERN_CTX_NPXINITDONE 0x01 | ||||
#define FPU_KERN_CTX_DUMMY 0x02 | #define FPU_KERN_CTX_DUMMY 0x02 | ||||
#define FPU_KERN_CTX_INUSE 0x04 | |||||
struct fpu_kern_ctx { | struct fpu_kern_ctx { | ||||
union savefpu *prev; | union savefpu *prev; | ||||
uint32_t flags; | uint32_t flags; | ||||
char hwstate1[]; | char hwstate1[]; | ||||
}; | }; | ||||
struct fpu_kern_ctx * | struct fpu_kern_ctx * | ||||
fpu_kern_alloc_ctx(u_int flags) | fpu_kern_alloc_ctx(u_int flags) | ||||
{ | { | ||||
struct fpu_kern_ctx *res; | struct fpu_kern_ctx *res; | ||||
size_t sz; | size_t sz; | ||||
sz = sizeof(struct fpu_kern_ctx) + XSAVE_AREA_ALIGN + | sz = sizeof(struct fpu_kern_ctx) + XSAVE_AREA_ALIGN + | ||||
cpu_max_ext_state_size; | cpu_max_ext_state_size; | ||||
res = malloc(sz, M_FPUKERN_CTX, ((flags & FPU_KERN_NOWAIT) ? | res = malloc(sz, M_FPUKERN_CTX, ((flags & FPU_KERN_NOWAIT) ? | ||||
M_NOWAIT : M_WAITOK) | M_ZERO); | M_NOWAIT : M_WAITOK) | M_ZERO); | ||||
return (res); | return (res); | ||||
} | } | ||||
void | void | ||||
fpu_kern_free_ctx(struct fpu_kern_ctx *ctx) | fpu_kern_free_ctx(struct fpu_kern_ctx *ctx) | ||||
{ | { | ||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) == 0, ("free'ing inuse ctx")); | |||||
/* XXXKIB clear the memory ? */ | /* XXXKIB clear the memory ? */ | ||||
free(ctx, M_FPUKERN_CTX); | free(ctx, M_FPUKERN_CTX); | ||||
} | } | ||||
static union savefpu * | static union savefpu * | ||||
fpu_kern_ctx_savefpu(struct fpu_kern_ctx *ctx) | fpu_kern_ctx_savefpu(struct fpu_kern_ctx *ctx) | ||||
{ | { | ||||
vm_offset_t p; | vm_offset_t p; | ||||
p = (vm_offset_t)&ctx->hwstate1; | p = (vm_offset_t)&ctx->hwstate1; | ||||
p = roundup2(p, XSAVE_AREA_ALIGN); | p = roundup2(p, XSAVE_AREA_ALIGN); | ||||
return ((union savefpu *)p); | return ((union savefpu *)p); | ||||
} | } | ||||
int | int | ||||
fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx, u_int flags) | fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx, u_int flags) | ||||
{ | { | ||||
struct pcb *pcb; | struct pcb *pcb; | ||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) == 0, ("using inuse ctx")); | |||||
if ((flags & FPU_KERN_KTHR) != 0 && is_fpu_kern_thread(0)) { | if ((flags & FPU_KERN_KTHR) != 0 && is_fpu_kern_thread(0)) { | ||||
ctx->flags = FPU_KERN_CTX_DUMMY; | ctx->flags = FPU_KERN_CTX_DUMMY | FPU_KERN_CTX_INUSE; | ||||
return (0); | return (0); | ||||
} | } | ||||
pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
KASSERT(!PCB_USER_FPU(pcb) || pcb->pcb_save == | KASSERT(!PCB_USER_FPU(pcb) || pcb->pcb_save == | ||||
get_pcb_user_save_pcb(pcb), ("mangled pcb_save")); | get_pcb_user_save_pcb(pcb), ("mangled pcb_save")); | ||||
ctx->flags = 0; | ctx->flags = FPU_KERN_CTX_INUSE; | ||||
if ((pcb->pcb_flags & PCB_NPXINITDONE) != 0) | if ((pcb->pcb_flags & PCB_NPXINITDONE) != 0) | ||||
ctx->flags |= FPU_KERN_CTX_NPXINITDONE; | ctx->flags |= FPU_KERN_CTX_NPXINITDONE; | ||||
npxexit(td); | npxexit(td); | ||||
ctx->prev = pcb->pcb_save; | ctx->prev = pcb->pcb_save; | ||||
pcb->pcb_save = fpu_kern_ctx_savefpu(ctx); | pcb->pcb_save = fpu_kern_ctx_savefpu(ctx); | ||||
pcb->pcb_flags |= PCB_KERNNPX; | pcb->pcb_flags |= PCB_KERNNPX; | ||||
pcb->pcb_flags &= ~PCB_NPXINITDONE; | pcb->pcb_flags &= ~PCB_NPXINITDONE; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx) | fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx) | ||||
{ | { | ||||
struct pcb *pcb; | 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) | if (is_fpu_kern_thread(0) && (ctx->flags & FPU_KERN_CTX_DUMMY) != 0) | ||||
return (0); | return (0); | ||||
pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
critical_enter(); | critical_enter(); | ||||
if (curthread == PCPU_GET(fpcurthread)) | if (curthread == PCPU_GET(fpcurthread)) | ||||
npxdrop(); | npxdrop(); | ||||
critical_exit(); | critical_exit(); | ||||
▲ Show 20 Lines • Show All 63 Lines • Show Last 20 Lines |