-/* $OpenBSD: cpuswitch.S,v 1.4 2018/09/07 01:32:01 mortimer Exp $ */
+/* $OpenBSD: cpuswitch.S,v 1.5 2022/01/01 18:52:36 kettenis Exp $ */
/*
* Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com>
*
* x4 - may contain user thread pointer (TCB)
* x5 - may contain PCB pointer (new or old)
*/
-ENTRY(cpu_switchto)
+ENTRY(cpu_switchto_asm)
// check if old context needs to be saved
cmp x0, #0
beq 1f
ldr x5, [x2, #(CI_CURPCB)]
str x3, [x5, #(PCB_SP) ] // save to old pcb
-
- mov x19, x1 //save new ctx across vfp
- // old process has been saved
- // save old fpu?
- ldr w7, [x5, #(PCB_FLAGS)]
- mov w3, #(PCB_FPU)
- and w7, w7, w3
- cbz w7, 1f
-
- bl vfp_save
-
- mov x1, x19
1:
RETGUARD_SYMBOL(cpu_switchto)
RETGUARD_LOAD_RANDOM(cpu_switchto, x20)
-/* $OpenBSD: cryptox.c,v 1.5 2021/10/24 10:26:22 patrick Exp $ */
+/* $OpenBSD: cryptox.c,v 1.6 2022/01/01 18:52:36 kettenis Exp $ */
/*
* Copyright (c) 2003 Jason Wright
* Copyright (c) 2003, 2004 Theo de Raadt
#include <crypto/xform.h>
#include <crypto/cryptosoft.h>
-#include <machine/vfp.h>
+#include <machine/fpu.h>
struct cryptox_aes_key {
uint32_t rd_key[4 *(AES_MAXROUNDS + 1)];
switch (c->cri_alg) {
case CRYPTO_AES_CBC:
ses->ses_klen = c->cri_klen / 8;
- vfp_kernel_enter();
+ fpu_kernel_enter();
aes_v8_set_encrypt_key(c->cri_key, c->cri_klen, &ses->ses_ekey);
aes_v8_set_decrypt_key(c->cri_key, c->cri_klen, &ses->ses_dkey);
- vfp_kernel_exit();
+ fpu_kernel_exit();
break;
case CRYPTO_MD5_HMAC:
crd->crd_len, buf);
/* Apply cipher */
- vfp_kernel_enter();
+ fpu_kernel_enter();
switch (crd->crd_alg) {
case CRYPTO_AES_CBC:
if (crd->crd_flags & CRD_F_ENCRYPT)
aes_v8_cbc_encrypt(buf, buf, crd->crd_len, &ses->ses_dkey, iv, 0);
break;
}
- vfp_kernel_exit();
+ fpu_kernel_exit();
cryptox_ops++;
-/* $OpenBSD: exception.S,v 1.12 2021/02/17 12:11:44 kettenis Exp $ */
+/* $OpenBSD: exception.S,v 1.13 2022/01/01 18:52:36 kettenis Exp $ */
/*-
* Copyright (c) 2014 Andrew Turner
* All rights reserved.
mov x0, sp
bl do_el0_sync
do_ast
- bl _C_LABEL(vfp_enable)
allow_ss
restore_registers 0
return
handle_el0_irq:
save_registers 0
disable_ss
- bl _C_LABEL(vfp_save)
mov x0, sp
bl arm_cpu_irq
do_ast
- bl _C_LABEL(vfp_enable)
allow_ss
restore_registers 0
return
handle_el0_fiq:
save_registers 0
disable_ss
- bl _C_LABEL(vfp_save)
mov x0, sp
bl arm_cpu_fiq
do_ast
- bl _C_LABEL(vfp_enable)
allow_ss
restore_registers 0
return
--- /dev/null
+/* $OpenBSD: fpu.c,v 1.1 2022/01/01 18:52:36 kettenis Exp $ */
+/*
+ * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <machine/armreg.h>
+
+void
+fpu_save(struct proc *p)
+{
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ struct fpreg *fp = &pcb->pcb_fpstate;
+ uint64_t cpacr;
+
+ cpacr = READ_SPECIALREG(cpacr_el1);
+ if ((cpacr & CPACR_FPEN_MASK) == CPACR_FPEN_TRAP_ALL1)
+ return;
+ KASSERT((cpacr & CPACR_FPEN_MASK) == CPACR_FPEN_TRAP_NONE);
+
+#define STRQx(x) \
+ __asm volatile ("str q" #x ", [%0, %1]" :: "r"(fp->fp_reg), "i"(x * 16))
+
+ STRQx(0);
+ STRQx(1);
+ STRQx(2);
+ STRQx(3);
+ STRQx(4);
+ STRQx(5);
+ STRQx(6);
+ STRQx(7);
+ STRQx(8);
+ STRQx(9);
+ STRQx(10);
+ STRQx(11);
+ STRQx(12);
+ STRQx(13);
+ STRQx(14);
+ STRQx(15);
+ STRQx(16);
+ STRQx(17);
+ STRQx(18);
+ STRQx(19);
+ STRQx(20);
+ STRQx(21);
+ STRQx(22);
+ STRQx(23);
+ STRQx(24);
+ STRQx(25);
+ STRQx(26);
+ STRQx(27);
+ STRQx(28);
+ STRQx(29);
+ STRQx(30);
+ STRQx(31);
+
+ fp->fp_sr = READ_SPECIALREG(fpsr);
+ fp->fp_cr = READ_SPECIALREG(fpcr);
+}
+
+void
+fpu_load(struct proc *p)
+{
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ struct fpreg *fp = &pcb->pcb_fpstate;
+ uint64_t cpacr;
+
+ cpacr = READ_SPECIALREG(cpacr_el1);
+ KASSERT((cpacr & CPACR_FPEN_MASK) == CPACR_FPEN_TRAP_ALL1);
+
+ if ((pcb->pcb_flags & PCB_FPU) == 0) {
+ memset(fp, 0, sizeof(*fp));
+ pcb->pcb_flags |= PCB_FPU;
+ }
+
+ /* Enable FPU. */
+ cpacr &= ~CPACR_FPEN_MASK;
+ cpacr |= CPACR_FPEN_TRAP_NONE;
+ WRITE_SPECIALREG(cpacr_el1, cpacr);
+ __asm volatile ("isb");
+
+#define LDRQx(x) \
+ __asm volatile ("ldr q" #x ", [%0, %1]" :: "r"(fp->fp_reg), "i"(x * 16))
+
+ LDRQx(0);
+ LDRQx(1);
+ LDRQx(2);
+ LDRQx(3);
+ LDRQx(4);
+ LDRQx(5);
+ LDRQx(6);
+ LDRQx(7);
+ LDRQx(8);
+ LDRQx(9);
+ LDRQx(10);
+ LDRQx(11);
+ LDRQx(12);
+ LDRQx(13);
+ LDRQx(14);
+ LDRQx(15);
+ LDRQx(16);
+ LDRQx(17);
+ LDRQx(18);
+ LDRQx(19);
+ LDRQx(20);
+ LDRQx(21);
+ LDRQx(22);
+ LDRQx(23);
+ LDRQx(24);
+ LDRQx(25);
+ LDRQx(26);
+ LDRQx(27);
+ LDRQx(28);
+ LDRQx(29);
+ LDRQx(30);
+ LDRQx(31);
+
+ WRITE_SPECIALREG(fpsr, fp->fp_sr);
+ WRITE_SPECIALREG(fpcr, fp->fp_cr);
+}
+
+void
+fpu_drop(void)
+{
+ uint64_t cpacr;
+
+ /* Disable FPU. */
+ cpacr = READ_SPECIALREG(cpacr_el1);
+ cpacr &= ~CPACR_FPEN_MASK;
+ cpacr |= CPACR_FPEN_TRAP_ALL1;
+ WRITE_SPECIALREG(cpacr_el1, cpacr);
+
+ /*
+ * No ISB instruction needed here, as returning to EL0 is a
+ * context synchronization event.
+ */
+}
+
+void
+fpu_kernel_enter(void)
+{
+ struct pcb *pcb = &curproc->p_addr->u_pcb;
+ uint64_t cpacr;
+
+ if (pcb->pcb_flags & PCB_FPU)
+ fpu_save(curproc);
+
+ /* Enable FPU (kernel only). */
+ cpacr = READ_SPECIALREG(cpacr_el1);
+ cpacr &= ~CPACR_FPEN_MASK;
+ cpacr |= CPACR_FPEN_TRAP_EL0;
+ WRITE_SPECIALREG(cpacr_el1, cpacr);
+ __asm volatile ("isb");
+}
+
+void
+fpu_kernel_exit(void)
+{
+ uint64_t cpacr;
+
+ /* Disable FPU. */
+ cpacr = READ_SPECIALREG(cpacr_el1);
+ cpacr &= ~CPACR_FPEN_MASK;
+ cpacr |= CPACR_FPEN_TRAP_ALL1;
+ WRITE_SPECIALREG(cpacr_el1, cpacr);
+
+ /*
+ * No ISB instruction needed here, as returning to EL0 is a
+ * context synchronization event.
+ */
+}
-/* $OpenBSD: machdep.c,v 1.66 2021/12/06 09:49:46 jsg Exp $ */
+/* $OpenBSD: machdep.c,v 1.67 2022/01/01 18:52:36 kettenis Exp $ */
/*
* Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
* Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
#include <machine/kcore.h>
#include <machine/bootconfig.h>
#include <machine/bus.h>
-#include <machine/vfp.h>
+#include <machine/fpu.h>
#include <arm64/arm64/arm64var.h>
#include <machine/db_machdep.h>
}
}
+void cpu_switchto_asm(struct proc *, struct proc *);
+
+void
+cpu_switchto(struct proc *old, struct proc *new)
+{
+ if (old) {
+ struct pcb *pcb = &old->p_addr->u_pcb;
+
+ if (pcb->pcb_flags & PCB_FPU)
+ fpu_save(old);
+
+ fpu_drop();
+ }
+
+ cpu_switchto_asm(old, new);
+}
+
/*
* machine dependent system variables.
*/
setregs(struct proc *p, struct exec_package *pack, u_long stack,
register_t *retval)
{
- struct trapframe *tf;
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ struct trapframe *tf = pcb->pcb_tf;
/* If we were using the FPU, forget about it. */
- if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
- vfp_discard(p);
- p->p_addr->u_pcb.pcb_flags &= ~PCB_FPU;
-
- tf = p->p_addr->u_pcb.pcb_tf;
+ memset(&pcb->pcb_fpstate, 0, sizeof(pcb->pcb_fpstate));
+ pcb->pcb_flags &= ~PCB_FPU;
+ fpu_drop();
memset (tf,0, sizeof(*tf));
tf->tf_sp = stack;
-/* $OpenBSD: process_machdep.c,v 1.5 2018/08/03 18:36:01 kettenis Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.6 2022/01/01 18:52:36 kettenis Exp $ */
/*
* Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
*
#include <sys/systm.h>
#include <sys/user.h>
+#include <machine/fpu.h>
#include <machine/pcb.h>
#include <machine/reg.h>
int
process_read_fpregs(struct proc *p, struct fpreg *regs)
{
+ if (p->p_addr->u_pcb.pcb_flags & PCB_FPU)
+ fpu_save(p);
+
if (p->p_addr->u_pcb.pcb_flags & PCB_FPU)
memcpy(regs, &p->p_addr->u_pcb.pcb_fpstate, sizeof(*regs));
else
int
process_write_fpregs(struct proc *p, struct fpreg *regs)
{
- p->p_addr->u_pcb.pcb_flags |= PCB_FPU;
memcpy(&p->p_addr->u_pcb.pcb_fpstate, regs,
sizeof(p->p_addr->u_pcb.pcb_fpstate));
+ p->p_addr->u_pcb.pcb_flags |= PCB_FPU;
+
+ /* drop FPU state */
+ fpu_drop();
+
return(0);
}
-/* $OpenBSD: syscall.c,v 1.9 2021/12/09 00:26:11 guenther Exp $ */
+/* $OpenBSD: syscall.c,v 1.10 2022/01/01 18:52:36 kettenis Exp $ */
/*
* Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com>
*
#include <uvm/uvm_extern.h>
-#include <machine/vfp.h>
-
#define MAXARGS 8
void
uvmexp.syscalls++;
- /* Before enabling interrupts, save FPU state */
- vfp_save();
-
/* Re-enable interrupts if they were enabled previously */
if (__predict_true((frame->tf_spsr & I_bit) == 0))
intr_enable();
-/* $OpenBSD: trap.c,v 1.38 2021/05/16 15:10:19 deraadt Exp $ */
+/* $OpenBSD: trap.c,v 1.39 2022/01/01 18:52:36 kettenis Exp $ */
/*-
* Copyright (c) 2014 Andrew Turner
* All rights reserved.
#include <uvm/uvm.h>
#include <uvm/uvm_extern.h>
+#include <machine/cpu.h>
+#include <machine/fpu.h>
#include <machine/frame.h>
#include <machine/pcb.h>
-#include <machine/cpu.h>
#include <machine/vmparam.h>
-#include <machine/vfp.h>
#ifdef KDB
#include <machine/db_machdep.h>
switch(exception) {
case EXCP_FP_SIMD:
case EXCP_TRAP_FP:
- panic("VFP exception in the kernel");
+ panic("FP exception in the kernel");
case EXCP_DATA_ABORT:
kdata_abort(frame, esr, far, 0);
break;
switch (exception) {
case EXCP_UNKNOWN:
- vfp_save();
curcpu()->ci_flush_bp();
sv.sival_ptr = (void *)frame->tf_elr;
trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
break;
case EXCP_FP_SIMD:
case EXCP_TRAP_FP:
- vfp_fault(frame->tf_elr, 0, frame, exception);
+ fpu_load(p);
break;
case EXCP_SVC:
- vfp_save();
svc_handler(frame);
break;
case EXCP_INSN_ABORT_L:
- vfp_save();
udata_abort(frame, esr, far, 1);
break;
case EXCP_PC_ALIGN:
- vfp_save();
curcpu()->ci_flush_bp();
sv.sival_ptr = (void *)frame->tf_elr;
trapsignal(p, SIGBUS, 0, BUS_ADRALN, sv);
break;
case EXCP_SP_ALIGN:
- vfp_save();
curcpu()->ci_flush_bp();
sv.sival_ptr = (void *)frame->tf_sp;
trapsignal(p, SIGBUS, 0, BUS_ADRALN, sv);
break;
case EXCP_DATA_ABORT_L:
- vfp_save();
udata_abort(frame, esr, far, 0);
break;
case EXCP_BRK:
- vfp_save();
sv.sival_ptr = (void *)frame->tf_elr;
trapsignal(p, SIGTRAP, 0, TRAP_BRKPT, sv);
break;
case EXCP_SOFTSTP_EL0:
- vfp_save();
sv.sival_ptr = (void *)frame->tf_elr;
trapsignal(p, SIGTRAP, 0, TRAP_TRACE, sv);
break;
+++ /dev/null
-/* $OpenBSD: vfp.c,v 1.6 2021/06/29 19:58:21 kettenis Exp $ */
-/*
- * Copyright (c) 2011 Dale Rahn <drahn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/user.h>
-
-#include <arm64/include/vfp.h>
-
-static inline void
-set_vfp_enable(int val)
-{
- uint64_t v;
- __asm __volatile("mrs %x0, cpacr_el1" : "=r" (v));
- if (val != 0) {
- v |= VFP_UFPEN;
- } else {
- v &= ~(VFP_UFPEN);
- }
- __asm __volatile("msr cpacr_el1, %x0" :: "r" (v));
- __asm __volatile("isb");
-}
-
-static inline int
-get_vfp_enable(void)
-{
- uint64_t v;
- int enabled = 0;
- __asm __volatile("mrs %x0, cpacr_el1" : "=r" (v));
- if ((v & VFP_UFPEN) == VFP_UFPEN )
- enabled = 1;
- return enabled;
-}
-
-int vfp_fault(vaddr_t pc, uint32_t insn, trapframe_t *tf, int fault_code);
-void vfp_load(struct proc *p);
-void vfp_store(struct fpreg *vfpsave);
-
-void
-vfp_store(struct fpreg *vfpsave)
-{
- uint32_t scratch;
-
- if (get_vfp_enable()) {
- __asm __volatile(
- "str q0, [%x1]\n"
- "str q1, [%x1, #0x10]\n"
- "str q2, [%x1, #0x20]\n"
- "str q3, [%x1, #0x30]\n"
- "str q4, [%x1, #0x40]\n"
- "str q5, [%x1, #0x50]\n"
- "str q6, [%x1, 0x60]\n"
- "str q7, [%x1, #0x70]\n"
- "str q8, [%x1, #0x80]\n"
- "str q9, [%x1, #0x90]\n"
- "str q10, [%x1, #0xa0]\n"
- "str q11, [%x1, #0xb0]\n"
- "str q12, [%x1, #0xc0]\n"
- "str q13, [%x1, 0xd0]\n"
- "str q14, [%x1, #0xe0]\n"
- "str q15, [%x1, #0xf0]\n"
- "str q16, [%x1, #0x100]\n"
- "str q17, [%x1, #0x110]\n"
- "str q18, [%x1, #0x120]\n"
- "str q19, [%x1, #0x130]\n"
- "str q20, [%x1, #0x140]\n"
- "str q21, [%x1, #0x150]\n"
- "str q22, [%x1, #0x160]\n"
- "str q23, [%x1, #0x170]\n"
- "str q24, [%x1, #0x180]\n"
- "str q25, [%x1, #0x190]\n"
- "str q26, [%x1, #0x1a0]\n"
- "str q27, [%x1, #0x1b0]\n"
- "str q28, [%x1, #0x1c0]\n"
- "str q29, [%x1, #0x1d0]\n"
- "str q30, [%x1, #0x1e0]\n"
- "str q31, [%x1, #0x1f0]\n"
- "mrs %x0, fpsr\n"
- "str %w0, [%x1, 0x200]\n" /* save vfpscr */
- "mrs %x0, fpcr\n"
- "str %w0, [%x1, 0x204]\n" /* save vfpscr */
- : "=&r" (scratch) : "r" (vfpsave));
- }
-
- /* disable FPU */
- set_vfp_enable(0);
-}
-
-void
-vfp_save(void)
-{
- struct cpu_info *ci = curcpu();
- struct pcb *pcb = curpcb;
- struct proc *p = curproc;
- uint32_t vfp_enabled;
-
- if (ci->ci_fpuproc == 0)
- return;
-
- vfp_enabled = get_vfp_enable();
-
- if (!vfp_enabled)
- return; /* not enabled, nothing to do */
-
- if (pcb->pcb_fpcpu == NULL || ci->ci_fpuproc == NULL ||
- !(pcb->pcb_fpcpu == ci && ci->ci_fpuproc == p)) {
- /* disable fpu before panic, otherwise recurse */
- set_vfp_enable(0);
-
- panic("FPU unit enabled when curproc and curcpu dont agree %p %p %p %p", pcb->pcb_fpcpu, ci, ci->ci_fpuproc, p);
- }
-
- vfp_store(&p->p_addr->u_pcb.pcb_fpstate);
-
- /*
- * NOTE: fpu state is saved but remains 'valid', as long as
- * curpcb()->pcb_fpucpu == ci && ci->ci_fpuproc == curproc()
- * is true FPU state is valid and can just be enabled without reload.
- */
- set_vfp_enable(0);
-}
-
-void
-vfp_enable(void)
-{
- struct cpu_info *ci = curcpu();
-
- if (curproc->p_addr->u_pcb.pcb_fpcpu == ci &&
- ci->ci_fpuproc == curproc) {
- intr_disable();
-
- /* FPU state is still valid, just enable and go */
- set_vfp_enable(1);
- }
-}
-
-void
-vfp_load(struct proc *p)
-{
- struct cpu_info *ci = curcpu();
- struct pcb *pcb = &p->p_addr->u_pcb;
- uint32_t scratch = 0;
- u_long psw;
-
- /* do not allow a partially synced state here */
- psw = intr_disable();
-
- /*
- * p->p_pcb->pcb_fpucpu _may_ not be NULL here, but the FPU state
- * was synced on kernel entry, so we can steal the FPU state
- * instead of signalling and waiting for it to save
- */
-
- /* enable to be able to load ctx */
- set_vfp_enable(1);
-
- __asm __volatile(
- "ldr q0, [%x1]\n"
- "ldr q1, [%x1, #0x10]\n"
- "ldr q2, [%x1, #0x20]\n"
- "ldr q3, [%x1, #0x30]\n"
- "ldr q4, [%x1, #0x40]\n"
- "ldr q5, [%x1, #0x50]\n"
- "ldr q6, [%x1, 0x60]\n"
- "ldr q7, [%x1, #0x70]\n"
- "ldr q8, [%x1, #0x80]\n"
- "ldr q9, [%x1, #0x90]\n"
- "ldr q10, [%x1, #0xa0]\n"
- "ldr q11, [%x1, #0xb0]\n"
- "ldr q12, [%x1, #0xc0]\n"
- "ldr q13, [%x1, 0xd0]\n"
- "ldr q14, [%x1, #0xe0]\n"
- "ldr q15, [%x1, #0xf0]\n"
- "ldr q16, [%x1, #0x100]\n"
- "ldr q17, [%x1, #0x110]\n"
- "ldr q18, [%x1, #0x120]\n"
- "ldr q19, [%x1, #0x130]\n"
- "ldr q20, [%x1, #0x140]\n"
- "ldr q21, [%x1, #0x150]\n"
- "ldr q22, [%x1, #0x160]\n"
- "ldr q23, [%x1, #0x170]\n"
- "ldr q24, [%x1, #0x180]\n"
- "ldr q25, [%x1, #0x190]\n"
- "ldr q26, [%x1, #0x1a0]\n"
- "ldr q27, [%x1, #0x1b0]\n"
- "ldr q28, [%x1, #0x1c0]\n"
- "ldr q29, [%x1, #0x1d0]\n"
- "ldr q30, [%x1, #0x1e0]\n"
- "ldr q31, [%x1, #0x1f0]\n"
-
- "ldr %w0, [%x1, #0x200]\n" /* set old fpsr */
- "msr fpsr, %x0\n"
- "ldr %w0, [%x1, #0x204]\n" /* set old fpsr */
- "msr fpcr, %x0\n"
- : "=&r" (scratch) : "r" (&pcb->pcb_fpstate));
-
- ci->ci_fpuproc = p;
- pcb->pcb_fpcpu = ci;
-
- /* disable until return to userland */
- set_vfp_enable(0);
-
- intr_restore(psw);
-}
-
-
-int
-vfp_fault(vaddr_t pc, uint32_t insn, trapframe_t *tf, int fault_code)
-{
- struct proc *p = curproc;
- struct pcb *pcb = &p->p_addr->u_pcb;
-
- if (get_vfp_enable()) {
- /*
- * We probably ran into an unsupported instruction,
- * like NEON on a non-NEON system. Let the process know.
- */
- return 1;
- }
-
- /* we should be able to ignore old state of pcb_fpcpu ci_fpuproc */
- if ((pcb->pcb_flags & PCB_FPU) == 0) {
- pcb->pcb_flags |= PCB_FPU;
- memset(&pcb->pcb_fpstate, 0, sizeof (pcb->pcb_fpstate));
- }
- vfp_load(p);
-
- return 0;
-}
-
-void
-vfp_discard(struct proc *p)
-{
- struct cpu_info *ci = curcpu();
-
- if (curpcb->pcb_fpcpu == ci && ci->ci_fpuproc == p) {
- ci->ci_fpuproc = NULL;
- curpcb->pcb_fpcpu = NULL;
- }
-}
-
-void
-vfp_kernel_enter(void)
-{
- struct cpu_info *ci = curcpu();
-
- ci->ci_fpuproc = NULL;
- set_vfp_enable(1);
-}
-
-void
-vfp_kernel_exit(void)
-{
- set_vfp_enable(0);
-}
-/* $OpenBSD: vm_machdep.c,v 1.8 2021/05/16 06:20:29 jsg Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.9 2022/01/01 18:52:36 kettenis Exp $ */
/* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */
/*-
#include <uvm/uvm_extern.h>
#include <machine/cpu.h>
+#include <machine/fpu.h>
#include <machine/reg.h>
-#include <machine/vfp.h>
/*
* Finish a fork operation, with process p2 nearly set up.
void (*func)(void *), void *arg)
{
struct pcb *pcb = &p2->p_addr->u_pcb;
+ struct pcb *pcb1 = &p1->p_addr->u_pcb;
struct trapframe *tf;
struct switchframe *sf;
- // Does any flushing need to be done if process was running?
+ /* Save FPU state to PCB if necessary. */
+ if (pcb1->pcb_flags & PCB_FPU)
+ fpu_save(p1);
/* Copy the pcb. */
*pcb = p1->p_addr->u_pcb;
- pcb->pcb_fpcpu = NULL;
tf = (struct trapframe *)((u_long)p2->p_addr
+ USPACE
void
cpu_exit(struct proc *p)
{
- /* If we were using the FPU, forget about it. */
- if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
- vfp_discard(p);
-
pmap_deactivate(p);
sched_exit(p);
}
-# $OpenBSD: files.arm64,v 1.50 2021/12/24 00:01:39 patrick Exp $
+# $OpenBSD: files.arm64,v 1.51 2022/01/01 18:52:37 kettenis Exp $
maxpartitions 16
maxusers 2 8 128
file arch/arm64/arm64/sys_machdep.c
file arch/arm64/arm64/cpu.c
+file arch/arm64/arm64/fpu.c
file arch/arm64/arm64/intr.c
file arch/arm64/arm64/softintr.c
-file arch/arm64/arm64/vfp.c
file arch/arm64/arm64/exception.S
file arch/arm64/arm64/trampoline.S
file arch/arm64/arm64/trap.c
-/* $OpenBSD: efi.c,v 1.11 2021/10/24 17:52:28 mpi Exp $ */
+/* $OpenBSD: efi.c,v 1.12 2022/01/01 18:52:37 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
#include <machine/cpufunc.h>
#include <machine/bus.h>
#include <machine/fdt.h>
-#include <machine/vfp.h>
+#include <machine/fpu.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/fdt.h>
__asm volatile("isb");
cpu_setttb(pm->pm_asid, pm->pm_pt0pa);
- vfp_kernel_enter();
+ fpu_kernel_enter();
}
void
{
struct pmap *pm = curcpu()->ci_curpm;
- vfp_kernel_exit();
+ fpu_kernel_exit();
WRITE_SPECIALREG(ttbr0_el1, pmap_kernel()->pm_pt0pa);
__asm volatile("isb");
-/* $OpenBSD: armreg.h,v 1.17 2021/09/02 10:48:52 kettenis Exp $ */
+/* $OpenBSD: armreg.h,v 1.18 2022/01/01 18:52:37 kettenis Exp $ */
/*-
* Copyright (c) 2013, 2014 Andrew Turner
* Copyright (c) 2015 The FreeBSD Foundation
#define ESR_ELx_EC_MASK (0x3f << 26)
#define ESR_ELx_EXCEPTION(esr) (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT)
#define EXCP_UNKNOWN 0x00 /* Unkwn exception */
-#define EXCP_FP_SIMD 0x07 /* VFP/SIMD trap */
+#define EXCP_FP_SIMD 0x07 /* FP/SIMD trap */
#define EXCP_ILL_STATE 0x0e /* Illegal execution state */
#define EXCP_SVC 0x15 /* SVC trap */
#define EXCP_MSR 0x18 /* MSR/MRS trap */
-/* $OpenBSD: cpu.h,v 1.23 2021/11/22 19:22:59 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.24 2022/01/01 18:52:37 kettenis Exp $ */
/*
* Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
*
struct proc *ci_curproc;
struct pmap *ci_curpm;
- struct proc *ci_fpuproc;
u_int32_t ci_randseed;
struct pcb *ci_curpcb;
--- /dev/null
+/* $OpenBSD: fpu.h,v 1.1 2022/01/01 18:52:37 kettenis Exp $ */
+/*
+ * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_FPU_H
+#define _MACHINE_FPU_H
+
+void fpu_save(struct proc *);
+void fpu_load(struct proc *);
+void fpu_drop(void);
+
+void fpu_kernel_enter(void);
+void fpu_kernel_exit(void);
+
+#endif /* !_MACHINE_FPU_H */
-/* $OpenBSD: pcb.h,v 1.4 2018/07/04 17:52:29 drahn Exp $ */
+/* $OpenBSD: pcb.h,v 1.5 2022/01/01 18:52:37 kettenis Exp $ */
/*
* Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
*
caddr_t pcb_onfault; // On fault handler
struct fpreg pcb_fpstate; // Floating Point state */
- struct cpu_info *pcb_fpcpu;
void *pcb_tcb;
};
+++ /dev/null
-/* $OpenBSD: vfp.h,v 1.4 2018/07/02 07:23:37 kettenis Exp $ */
-/*-
- * Copyright (c) 2015 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Andrew Turner under
- * sponsorship from the FreeBSD Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD: head/sys/arm64/include/vfp.h 281494 2015-04-13 14:43:10Z andrew $
- */
-
-#ifndef _MACHINE_VFP_H_
-#define _MACHINE_VFP_H_
-
-#ifdef _KERNEL
-
-#define VFP_KFPEN (1 << 20)
-#define VFP_UFPEN (3 << 20)
-
-#ifndef LOCORE
-void vfp_discard(struct proc *);
-void vfp_save(void);
-void vfp_enable(void);
-int vfp_fault(vaddr_t, uint32_t, trapframe_t *, int);
-void vfp_kernel_enter(void);
-void vfp_kernel_exit(void);
-#endif
-
-#endif
-
-#endif /* !_MACHINE_VFP_H_ */