diff --git a/sys/arm/arm/undefined.c b/sys/arm/arm/undefined.c --- a/sys/arm/arm/undefined.c +++ b/sys/arm/arm/undefined.c @@ -345,9 +345,19 @@ #endif return; } +#ifdef VFP + /* + * Workaround to allow the execution of VFP instructions within + * the kernel. Allow the first in-kernel VFP instruction to be + * properly handled by this handler without panicing. + */ + else if(uh != NULL) + return; +#else else panic("Undefined instruction in kernel (0x%08x).\n", fault_instruction); +#endif } userret(td, frame); diff --git a/sys/arm/arm/vfp.c b/sys/arm/arm/vfp.c --- a/sys/arm/arm/vfp.c +++ b/sys/arm/arm/vfp.c @@ -33,9 +33,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -45,6 +47,9 @@ #include #include +static MALLOC_DEFINE(M_FPUKERN_CTX, "fpukern_ctx", + "Kernel contexts for VFP state"); + /* function prototypes */ static int vfp_bounce(u_int, u_int, struct trapframe *, int); static void vfp_restore(struct vfp_state *); @@ -205,8 +210,11 @@ struct pcb *curpcb; ksiginfo_t ksi; +#ifndef VFP + /* Allow in-kernel vfp instruction handling */ if ((code & FAULT_USER) == 0) panic("undefined floating point instruction in supervisor mode"); +#endif critical_enter(); @@ -257,12 +265,39 @@ critical_exit(); +#ifndef VFP + /* + * Allow kernel state in use when entering userspace as we now allow + * in-kernel VFP + */ KASSERT(curpcb->pcb_vfpsaved == &curpcb->pcb_vfpstate, ("Kernel VFP state in use when entering userspace")); +#endif return (0); } +struct fpu_kern_ctx * +fpu_kern_alloc_ctx(u_int flags) +{ + struct fpu_kern_ctx *res; + size_t sz; + + sz = sizeof(struct fpu_kern_ctx); + res = malloc(sz, M_FPUKERN_CTX, ((flags & FPU_KERN_NOWAIT) ? + M_NOWAIT : M_WAITOK) | M_ZERO); + return (res); +} + +void +fpu_kern_free_ctx(struct fpu_kern_ctx *ctx) +{ + + KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) == 0, ("free'ing inuse ctx")); + + free(ctx, M_FPUKERN_CTX); +} + /* * Update the VFP state for a forked process or new thread. The PCB will * have been copied from the old thread.