Module Name: src Committed By: rin Date: Wed Jul 15 08:58:52 UTC 2020
Modified Files: src/sys/arch/powerpc/include: cpu.h instr.h src/sys/arch/powerpc/powerpc: powerpc_machdep.c trap.c Log Message: Factor out emulation code for m[ft]msr in user mode from oea, and adjust it for systems without FPU. Now, it can be used from booke and ibm4xx in order to support fenv(3). To generate a diff of this commit: cvs rdiff -u -r1.114 -r1.115 src/sys/arch/powerpc/include/cpu.h cvs rdiff -u -r1.8 -r1.9 src/sys/arch/powerpc/include/instr.h cvs rdiff -u -r1.79 -r1.80 src/sys/arch/powerpc/powerpc/powerpc_machdep.c cvs rdiff -u -r1.162 -r1.163 src/sys/arch/powerpc/powerpc/trap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/powerpc/include/cpu.h diff -u src/sys/arch/powerpc/include/cpu.h:1.114 src/sys/arch/powerpc/include/cpu.h:1.115 --- src/sys/arch/powerpc/include/cpu.h:1.114 Tue Jul 7 01:39:23 2020 +++ src/sys/arch/powerpc/include/cpu.h Wed Jul 15 08:58:51 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.114 2020/07/07 01:39:23 rin Exp $ */ +/* $NetBSD: cpu.h,v 1.115 2020/07/15 08:58:51 rin Exp $ */ /* * Copyright (C) 1999 Wolfgang Solfrank. @@ -391,6 +391,8 @@ void icache_inv(vaddr_t, vsize_t); void * mapiodev(paddr_t, psize_t, bool); void unmapiodev(vaddr_t, vsize_t); +int emulate_mxmsr(struct lwp *, struct trapframe *, uint32_t); + #ifdef MULTIPROCESSOR int md_setup_trampoline(volatile struct cpu_hatch_data *, struct cpu_info *); Index: src/sys/arch/powerpc/include/instr.h diff -u src/sys/arch/powerpc/include/instr.h:1.8 src/sys/arch/powerpc/include/instr.h:1.9 --- src/sys/arch/powerpc/include/instr.h:1.8 Mon Feb 27 06:54:00 2017 +++ src/sys/arch/powerpc/include/instr.h Wed Jul 15 08:58:51 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: instr.h,v 1.8 2017/02/27 06:54:00 chs Exp $ */ +/* $NetBSD: instr.h,v 1.9 2020/07/15 08:58:51 rin Exp $ */ /* * Copyright (c) 1992, 1993 @@ -405,12 +405,6 @@ union instr { #define OPC_MFSPR_REG(o) (((o) >> 21) & 0x1f) #define OPC_MFSPR_P(o, spr) (((o) & OPC_MFSPR_MASK) == OPC_MFSPR(spr)) -#define OPC_MFMSR_CODE 0x7c0000a6 -#define OPC_MFMSR_MASK 0xfc1fffff -#define OPC_MFMSR OPC_MFMSR_CODE -#define OPC_MFMSR_REG(o) (((o) >> 21) & 0x1f) -#define OPC_MFMSR_P(o) (((o) & OPC_MFMSR_MASK) == OPC_MFMSR_CODE) - /* * booke doesn't have lwsync even though gcc emits it so we have to emulate it. */ Index: src/sys/arch/powerpc/powerpc/powerpc_machdep.c diff -u src/sys/arch/powerpc/powerpc/powerpc_machdep.c:1.79 src/sys/arch/powerpc/powerpc/powerpc_machdep.c:1.80 --- src/sys/arch/powerpc/powerpc/powerpc_machdep.c:1.79 Tue Jul 7 01:39:23 2020 +++ src/sys/arch/powerpc/powerpc/powerpc_machdep.c Wed Jul 15 08:58:52 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: powerpc_machdep.c,v 1.79 2020/07/07 01:39:23 rin Exp $ */ +/* $NetBSD: powerpc_machdep.c,v 1.80 2020/07/15 08:58:52 rin Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: powerpc_machdep.c,v 1.79 2020/07/07 01:39:23 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: powerpc_machdep.c,v 1.80 2020/07/15 08:58:52 rin Exp $"); #ifdef _KERNEL_OPT #include "opt_altivec.h" @@ -738,6 +738,82 @@ cpu_debug_dump(void) #endif /* DDB */ #endif /* MULTIPROCESSOR */ +int +emulate_mxmsr(struct lwp *l, struct trapframe *tf, uint32_t opcode) +{ + +#define OPC_MFMSR_CODE 0x7c0000a6 +#define OPC_MFMSR_MASK 0xfc1fffff +#define OPC_MFMSR_P(o) (((o) & OPC_MFMSR_MASK) == OPC_MFMSR_CODE) + +#define OPC_MTMSR_CODE 0x7c000124 +#define OPC_MTMSR_MASK 0xfc1fffff +#define OPC_MTMSR_P(o) (((o) & OPC_MTMSR_MASK) == OPC_MTMSR_CODE) + +#define OPC_MXMSR_REG(o) (((o) >> 21) & 0x1f) + + if (OPC_MFMSR_P(opcode)) { + struct pcb * const pcb = lwp_getpcb(l); + register_t msr = tf->tf_srr1 & PSL_USERSRR1; + + if (fpu_used_p(l)) + msr |= PSL_FP; +#ifdef ALTIVEC + if (vec_used_p(l)) + msr |= PSL_VEC; +#endif + + msr |= (pcb->pcb_flags & PSL_FE_PREC); + tf->tf_fixreg[OPC_MXMSR_REG(opcode)] = msr; + return 1; + } + + if (OPC_MTMSR_P(opcode)) { + struct pcb * const pcb = lwp_getpcb(l); + register_t msr = tf->tf_fixreg[OPC_MXMSR_REG(opcode)]; + + /* + * Ignore the FP enable bit in the requested MSR. + * It might be set in the thread's actual MSR but the + * user code isn't allowed to change it. + */ + msr &= ~PSL_FP; +#ifdef ALTIVEC + msr &= ~PSL_VEC; +#endif + + /* + * Don't let the user muck with bits he's not allowed to. + */ +#ifdef PPC_HAVE_FPU + if (!PSL_USEROK_P(msr)) +#else + if (!PSL_USEROK_P(msr & ~PSL_FE_PREC)) +#endif + return 0; + + /* + * For now, only update the FP exception mode. + */ + pcb->pcb_flags &= ~PSL_FE_PREC; + pcb->pcb_flags |= msr & PSL_FE_PREC; + +#ifdef PPC_HAVE_FPU + /* + * If we think we have the FPU, update SRR1 too. If we're + * wrong userret() will take care of it. + */ + if (tf->tf_srr1 & PSL_FP) { + tf->tf_srr1 &= ~(PSL_FE0|PSL_FE1); + tf->tf_srr1 |= msr & (PSL_FE0|PSL_FE1); + } +#endif + return 1; + } + + return 0; +} + #ifdef MODULAR /* * Push any modules loaded by the boot loader. Index: src/sys/arch/powerpc/powerpc/trap.c diff -u src/sys/arch/powerpc/powerpc/trap.c:1.162 src/sys/arch/powerpc/powerpc/trap.c:1.163 --- src/sys/arch/powerpc/powerpc/trap.c:1.162 Wed Jul 15 07:58:26 2020 +++ src/sys/arch/powerpc/powerpc/trap.c Wed Jul 15 08:58:52 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.162 2020/07/15 07:58:26 rin Exp $ */ +/* $NetBSD: trap.c,v 1.163 2020/07/15 08:58:52 rin Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -35,7 +35,7 @@ #define __UCAS_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.162 2020/07/15 07:58:26 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.163 2020/07/15 08:58:52 rin Exp $"); #ifdef _KERNEL_OPT #include "opt_altivec.h" @@ -1089,65 +1089,7 @@ emulate_privileged(struct lwp *l, struct return 1; } - if (OPC_MFMSR_P(opcode)) { - struct pcb * const pcb = lwp_getpcb(l); - register_t msr = tf->tf_srr1 & PSL_USERSRR1; - - if (fpu_used_p(l)) - msr |= PSL_FP; - msr |= (pcb->pcb_flags & (PCB_FE0|PCB_FE1)); -#ifdef ALTIVEC - if (vec_used_p(l)) - msr |= PSL_VEC; -#endif - tf->tf_fixreg[OPC_MFMSR_REG(opcode)] = msr; - return 1; - } - -#define OPC_MTMSR_CODE 0x7c000124 -#define OPC_MTMSR_MASK 0xfc1fffff -#define OPC_MTMSR OPC_MTMSR_CODE -#define OPC_MTMSR_REG(o) (((o) >> 21) & 0x1f) -#define OPC_MTMSR_P(o) (((o) & OPC_MTMSR_MASK) == OPC_MTMSR_CODE) - - if (OPC_MTMSR_P(opcode)) { - struct pcb * const pcb = lwp_getpcb(l); - register_t msr = tf->tf_fixreg[OPC_MTMSR_REG(opcode)]; - - /* - * Ignore the FP enable bit in the requested MSR. - * It might be set in the thread's actual MSR but the - * user code isn't allowed to change it. - */ - msr &= ~PSL_FP; -#ifdef ALTIVEC - msr &= ~PSL_VEC; -#endif - - /* - * Don't let the user muck with bits he's not allowed to. - */ - if (!PSL_USEROK_P(msr)) - return 0; - - /* - * For now, only update the FP exception mode. - */ - pcb->pcb_flags &= ~(PSL_FE0|PSL_FE1); - pcb->pcb_flags |= msr & (PSL_FE0|PSL_FE1); - - /* - * If we think we have the FPU, update SRR1 too. If we're - * wrong userret() will take care of it. - */ - if (tf->tf_srr1 & PSL_FP) { - tf->tf_srr1 &= ~(PSL_FE0|PSL_FE1); - tf->tf_srr1 |= msr & (PSL_FE0|PSL_FE1); - } - return 1; - } - - return 0; + return emulate_mxmsr(l, tf, opcode); } int