Implement fpu_kern_enter/leave for arm32.

This commit is contained in:
riastradh 2020-06-29 23:54:05 +00:00
parent 9f4370e773
commit c41eed1f74
3 changed files with 78 additions and 5 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.145 2020/06/20 07:10:36 skrll Exp $ */
/* $NetBSD: cpu.c,v 1.146 2020/06/29 23:54:05 riastradh Exp $ */
/*
* Copyright (c) 1995 Mark Brinicombe.
@ -46,7 +46,7 @@
#include "opt_multiprocessor.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.145 2020/06/20 07:10:36 skrll Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.146 2020/06/29 23:54:05 riastradh Exp $");
#include <sys/param.h>
@ -229,6 +229,8 @@ cpu_attach(device_t dv, cpuid_t id)
#endif
vfp_attach(ci); /* XXX SMP */
ci->ci_kfpu_spl = -1;
}
enum cpu_class {

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.110 2020/03/29 09:06:38 skrll Exp $ */
/* $NetBSD: cpu.h,v 1.111 2020/06/29 23:54:06 riastradh Exp $ */
/*
* Copyright (c) 1994-1996 Mark Brinicombe.
@ -168,6 +168,8 @@ struct cpu_info {
int ci_want_resched;/* resched() was called */
int ci_intr_depth; /* */
int ci_kfpu_spl;
struct cpu_softc *
ci_softc; /* platform softc */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfp_init.c,v 1.64 2019/10/29 16:18:23 joerg Exp $ */
/* $NetBSD: vfp_init.c,v 1.65 2020/06/29 23:54:06 riastradh Exp $ */
/*
* Copyright (c) 2008 ARM Ltd
@ -32,7 +32,7 @@
#include "opt_cputypes.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v 1.64 2019/10/29 16:18:23 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v 1.65 2020/06/29 23:54:06 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v 1.64 2019/10/29 16:18:23 joerg Exp $");
#include <arm/undefined.h>
#include <arm/vfpreg.h>
#include <arm/mcontext.h>
#include <arm/fpu.h>
#include <uvm/uvm_extern.h> /* for pmap.h */
@ -658,4 +659,72 @@ vfp_setcontext(struct lwp *l, const mcontext_t *mcp)
sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx));
}
void
fpu_kern_enter(void)
{
struct lwp *l = curlwp;
struct cpu_info *ci;
uint32_t fpexc;
int s;
/*
* Block all interrupts. We must block preemption since -- if
* this is a user thread -- there is nowhere to save the kernel
* fpu state, and if we want this to be usable in interrupts,
* we can't let interrupts interfere with the fpu state in use
* since there's nowhere for them to save it.
*/
s = splhigh();
ci = curcpu();
KASSERT(ci->ci_kfpu_spl == -1);
ci->ci_kfpu_spl = s;
/*
* If we are in a softint and have a pinned lwp, the fpu state
* is that of the pinned lwp, so save it there.
*/
if ((l->l_pflag & LP_INTR) && (l->l_switchto != NULL))
l = l->l_switchto;
if (vfp_used_p(l))
vfp_savecontext(l);
/* Enable the fpu. */
fpexc = armreg_fpexc_read();
fpexc |= VFP_FPEXC_EN;
fpexc &= ~VFP_FPEXC_EX;
armreg_fpexc_write(fpexc);
}
void
fpu_kern_leave(void)
{
static const struct vfpreg zero_vfpreg;
struct cpu_info *ci = curcpu();
int s;
uint32_t fpexc;
KASSERT(ci->ci_cpl == IPL_HIGH);
KASSERT(ci->ci_kfpu_spl != -1);
/*
* Zero the fpu registers; otherwise we might leak secrets
* through Spectre-class attacks to userland, even if there are
* no bugs in fpu state management.
*/
load_vfpregs(&zero_vfpreg);
/*
* Disable the fpu so that the kernel can't accidentally use
* it again.
*/
fpexc = armreg_fpexc_read();
fpexc &= ~VFP_FPEXC_EN;
armreg_fpexc_write(fpexc);
/* Restore interrupts. */
s = ci->ci_kfpu_spl;
ci->ci_kfpu_spl = -1;
splx(s);
}
#endif /* FPU_VFP */