Implement fpu_kern_enter/leave for arm32.
This commit is contained in:
parent
9f4370e773
commit
c41eed1f74
@ -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 {
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user