Index: sys/arch/hppa/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/conf/GENERIC,v retrieving revision 1.49 diff -u -p -r1.49 GENERIC --- sys/arch/hppa/conf/GENERIC 27 Mar 2025 12:22:43 -0000 1.49 +++ sys/arch/hppa/conf/GENERIC 19 Aug 2026 15:04:47 -0000 @@ -191,6 +191,8 @@ options PCDISPLAY_SOFTCURSOR # enable VGA raster mode capable of displaying multilingual text on console #options VGA_RASTERCONSOLE +#options HPPA_FPU_EAGER + # Kernel root file system and dump configuration. config netbsd root on ? type ? #config netbsd root on sd0a type ffs Index: sys/arch/hppa/conf/RAMDISK =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/conf/RAMDISK,v retrieving revision 1.4 diff -u -p -r1.4 RAMDISK --- sys/arch/hppa/conf/RAMDISK 13 Jan 2022 08:25:24 -0000 1.4 +++ sys/arch/hppa/conf/RAMDISK 19 Aug 2026 15:04:47 -0000 @@ -9,6 +9,6 @@ include "arch/hppa/conf/GENERIC" options MEMORY_DISK_HOOKS options MEMORY_DISK_IS_ROOT # force root on memory disk options MEMORY_DISK_SERVER=0 # no userspace memory disk support -options MEMORY_DISK_ROOT_SIZE=6600 # size of memory disk, in blocks +options MEMORY_DISK_ROOT_SIZE=7000 # size of memory disk, in blocks options MEMORY_DISK_RBFLAGS=RB_SINGLE # boot in single-user mode Index: sys/arch/hppa/conf/files.hppa =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/conf/files.hppa,v retrieving revision 1.29 diff -u -p -r1.29 files.hppa --- sys/arch/hppa/conf/files.hppa 20 Oct 2025 09:42:46 -0000 1.29 +++ sys/arch/hppa/conf/files.hppa 19 Aug 2026 15:04:47 -0000 @@ -111,6 +111,7 @@ file arch/hppa/dev/cpu.c cpu device fpu attach fpu at gedoens file arch/hppa/dev/fpu.c fpu +defflag opt_hppa_fpu.h HPPA_FPU_EAGER # Phantom PseudoBC GSC+ Port device phantomas: gedoens Index: sys/arch/hppa/hppa/fpu.c =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/hppa/fpu.c,v retrieving revision 1.27 diff -u -p -r1.27 fpu.c --- sys/arch/hppa/hppa/fpu.c 16 Apr 2020 05:44:43 -0000 1.27 +++ sys/arch/hppa/hppa/fpu.c 19 Aug 2026 15:04:47 -0000 @@ -36,6 +36,10 @@ #include __KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.27 2020/04/16 05:44:43 skrll Exp $"); +#ifdef _KERNEL_OPT +#include "opt_hppa_fpu.h" +#endif + #include #include #include @@ -78,10 +82,19 @@ u_int fpu_version; /* The number of times we have had to switch the FPU context. */ u_int fpu_csw; +#ifdef HPPA_FPU_EAGER +#define fpu_eager 1 +#else +/* Don't use the default lazy FPU switching */ +int fpu_eager; +#endif + /* In locore.S, this swaps states in and out of the FPU. */ void hppa_fpu_swapout(struct pcb *); void hppa_fpu_swap(struct fpreg *, struct fpreg *); +void hppa_fpu_switch(struct lwp *); + static int hppa_fpu_ls(struct trapframe *, struct lwp *); /* @@ -139,14 +152,15 @@ const int _frame_reg_positions[32] = { void hppa_fpu_bootstrap(u_int ccr_enable) { - uint32_t junk[2]; - uint32_t vers[2]; + uint32_t junk[2] __aligned(8); + uint32_t vers[2] __aligned(8); /* See if we have a present and functioning hardware FPU. */ fpu_present = (ccr_enable & HPPA_FPUS) == HPPA_FPUS; if (!fpu_present) { fpu_csw = 0; curcpu()->ci_fpu_state = 0; + curcpu()->ci_fpu_lwp = NULL; return; } @@ -182,9 +196,40 @@ hppa_fpu_bootstrap(u_int ccr_enable) */ fpu_csw = 0; curcpu()->ci_fpu_state = 0; + curcpu()->ci_fpu_lwp = NULL; mtctl(ccr_enable & (CCR_MASK ^ HPPA_FPUS), CR_CCR); fpu_version = vers[0]; + +#ifdef HPPA_FPU_EAGER + aprint_normal("fpu: eager switching\n"); +#else + /* + * Handle QEMU, which does not check whether the FPU + * is disabled before trying to run instructions on it, + * thus never traps, thus never triggers our lazy FPU + * switching scheme. + */ + mtctl(0, CR_CCR); + __asm volatile("fstds %%fr0, 0(%0)" :: "r" (junk) : "memory"); + u_int ccr; + mfctl(CR_CCR, ccr); + if (!(ccr & HPPA_FPUS)) { + fpu_eager = 1; + /* No trap, so no trap handler, so re-enable FPU ourselves. */ + mtctl(HPPA_FPUS, CR_CCR); + aprint_normal("fpu: emulation trap failure; " + "using eager switching\n"); + } else { + /* + * This probe is the only thing that ever traps from lwp0, + * and we're not really set up for that to work right. + * Fortunately, we know what state we should put back. + */ + curcpu()->ci_fpu_state = 0; + mtctl(ccr_enable & (CCR_MASK ^ HPPA_FPUS), CR_CCR); + } +#endif } /* @@ -212,6 +257,14 @@ hppa_fpu_flush(struct lwp *l) hppa_fpu_swapout(pcb); ci->ci_fpu_state = 0; + /* + * If we are doing eager FPU switching, hang onto the + * LWP - if it uses the FPU again, the regs will need to be + * saved again. + */ + if (!fpu_eager) { + ci->ci_fpu_lwp = NULL; + } } /* @@ -424,3 +477,51 @@ hppa_fpu_emulate(struct trapframe *frame trapsignal(l, &ksi); } } + +/* + * Immediately switch current LWP's FP regs for those of the new LWP's; + * called from cpu_switchto if hppa_fpu_switch is set (if we are avoiding + * lazy FPU switching). + */ +void +hppa_fpu_switch(struct lwp *newl) +{ + struct cpu_info *ci = curcpu(); + struct pcb *oldpcb, *newpcb; + struct fpreg *oldregs = NULL, *newregs; + + if (!fpu_present) + return; + if (ci->ci_fpu_lwp == newl) + return; + + if (ci->ci_fpu_lwp != NULL) { + oldpcb = lwp_getpcb(ci->ci_fpu_lwp); + oldregs = oldpcb->pcb_fpregs; + } + + newpcb = lwp_getpcb(newl); + newregs = newpcb->pcb_fpregs; + + ci->ci_fpu_lwp = newl; + hppa_fpu_swap(oldregs, newregs); +} + +/* + * With eager FPU switching, we can't rely on trap side effects to catch + * use of the FPU and sync regs like the status register. Push a change + * out to the hardware, to avoid use of some other process's FPU status etc. + */ +void +hppa_fpu_commit(struct lwp *l) +{ + struct cpu_info *ci = curcpu(); + + KASSERT(kpreempt_disabled()); + + if (fpu_eager && ci->ci_fpu_lwp == l) { + struct pcb *pcb = lwp_getpcb(l); + + hppa_fpu_swap(NULL, pcb->pcb_fpregs); + } +} Index: sys/arch/hppa/hppa/hppa_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/hppa/hppa_machdep.c,v retrieving revision 1.33 diff -u -p -r1.33 hppa_machdep.c --- sys/arch/hppa/hppa/hppa_machdep.c 13 May 2022 18:40:02 -0000 1.33 +++ sys/arch/hppa/hppa/hppa_machdep.c 19 Aug 2026 15:04:48 -0000 @@ -252,8 +252,11 @@ cpu_setmcontext(struct lwp *l, const mco if ((flags & _UC_FPU) != 0) { struct pcb *pcb = lwp_getpcb(l); + kpreempt_disable(); hppa_fpu_flush(l); memcpy(pcb->pcb_fpregs, &mcp->__fpregs, sizeof(mcp->__fpregs)); + hppa_fpu_commit(l); + kpreempt_enable(); } mutex_enter(p->p_lock); Index: sys/arch/hppa/hppa/locore.S =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/hppa/locore.S,v retrieving revision 1.7 diff -u -p -r1.7 locore.S --- sys/arch/hppa/hppa/locore.S 3 Apr 2025 17:49:49 -0000 1.7 +++ sys/arch/hppa/hppa/locore.S 19 Aug 2026 15:04:48 -0000 @@ -57,10 +57,11 @@ * suitability of this software for any purpose. */ -#include "opt_multiprocessor.h" #include "opt_cputype.h" #include "opt_ddb.h" +#include "opt_hppa_fpu.h" #include "opt_kgdb.h" +#include "opt_multiprocessor.h" #include #include @@ -945,13 +946,38 @@ kstack_ok: noras: /* - * We do have a hardware FPU. If the LWP - * that we just switched to has its state in the - * FPU, enable the FPU, else disable it, so if - * the LWP does try to use the coprocessor - * we'll get an assist emulation trap to swap - * states. + * We do have a hardware FPU. Two paths: eager + * (if selected by kernel config, or if emulation trap broken), + * or lazy. + */ +#ifndef HPPA_FPU_EAGER + .import fpu_eager, data + ldil L%fpu_eager, %t1 + ldw R%fpu_eager(%t1), %t1 + comib,=,n 0, %t1, L$fpu_lazy +#endif + /* + * Eager path - via C helper */ + stw %arg0, HPPA_FRAME_ARG(0)(%r3) + stw %arg1, HPPA_FRAME_ARG(1)(%r3) + copy %arg1, %arg0 + CALL(hppa_fpu_switch, %r1) + ldw HPPA_FRAME_ARG(1)(%r3), %arg1 + ldw HPPA_FRAME_ARG(0)(%r3), %arg0 + +#ifndef HPPA_FPU_EAGER + b,n switch_return + + /* + * Lazy path. If the LWP + * that we just switched to has its state in the + * FPU, enable the FPU, else disable it, so if + * the LWP does try to use the coprocessor + * we'll get an assist emulation trap to swap + * states. + */ +L$fpu_lazy: GET_CURCPU(%t1) mfctl CR_CCR, %r1 mfctl CR_FPPADDR, %t2 @@ -960,6 +986,7 @@ noras: comb,<>,n %t1, %t2, 0 ; nullify if LWPs different depi 3, 25, 2, %r1 ; enables the FPU mtctl %r1, CR_CCR +#endif switch_return: copy %arg0, %ret0 Index: sys/arch/hppa/hppa/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/hppa/machdep.c,v retrieving revision 1.27 diff -u -p -r1.27 machdep.c --- sys/arch/hppa/hppa/machdep.c 15 Aug 2026 11:14:59 -0000 1.27 +++ sys/arch/hppa/hppa/machdep.c 19 Aug 2026 15:04:48 -0000 @@ -1923,12 +1923,15 @@ setregs(struct lwp *l, struct exec_packa hppa_setvmspace(l); /* reset any of the pending FPU exceptions */ + kpreempt_disable(); hppa_fpu_flush(l); memset(pcb->pcb_fpregs, 0, sizeof(*pcb->pcb_fpregs)); pcb->pcb_fpregs->fpr_regs[0] = ((uint64_t)HPPA_FPU_INIT) << 32; pcb->pcb_fpregs->fpr_regs[1] = 0; pcb->pcb_fpregs->fpr_regs[2] = 0; pcb->pcb_fpregs->fpr_regs[3] = 0; + hppa_fpu_commit(l); + kpreempt_enable(); l->l_md.md_bpva = 0; Index: sys/arch/hppa/hppa/machdep.h =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/hppa/machdep.h,v retrieving revision 1.19 diff -u -p -r1.19 machdep.h --- sys/arch/hppa/hppa/machdep.h 14 Sep 2020 16:11:00 -0000 1.19 +++ sys/arch/hppa/hppa/machdep.h 19 Aug 2026 15:04:48 -0000 @@ -80,6 +80,7 @@ extern u_int fpu_csw; void hppa_fpu_bootstrap(u_int); void hppa_fpu_flush(struct lwp *); void hppa_fpu_emulate(struct trapframe *, struct lwp *, u_int); +void hppa_fpu_commit(struct lwp *); /* Set up of space registers and protection IDs */ void hppa_setvmspace(struct lwp *); Index: sys/arch/hppa/hppa/process_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/hppa/process_machdep.c,v retrieving revision 1.18 diff -u -p -r1.18 process_machdep.c --- sys/arch/hppa/hppa/process_machdep.c 4 Jan 2014 00:10:02 -0000 1.18 +++ sys/arch/hppa/hppa/process_machdep.c 19 Aug 2026 15:04:48 -0000 @@ -181,8 +181,11 @@ process_write_fpregs(struct lwp *l, cons { struct pcb *pcb = lwp_getpcb(l); + kpreempt_disable(); hppa_fpu_flush(l); memcpy(pcb->pcb_fpregs, fpregs, sizeof(*fpregs)); + hppa_fpu_commit(l); + kpreempt_enable(); return 0; } Index: sys/arch/hppa/include/cpu.h =================================================================== RCS file: /cvsroot/src/sys/arch/hppa/include/cpu.h,v retrieving revision 1.13 diff -u -p -r1.13 cpu.h --- sys/arch/hppa/include/cpu.h 23 Feb 2023 14:55:36 -0000 1.13 +++ sys/arch/hppa/include/cpu.h 19 Aug 2026 15:04:48 -0000 @@ -290,6 +290,8 @@ struct cpu_info { hppa_hpa_t ci_hpa; register_t ci_psw; /* Processor Status Word. */ paddr_t ci_fpu_state; /* LWP FPU state address, or zero. */ + struct lwp *ci_fpu_lwp; /* If eager mode, LWP vaddr or NULL */ + u_long ci_itmr; int ci_cpuid; /* CPU index (see cpus[] array) */