Module Name: src Committed By: chs Date: Mon Feb 27 06:54:00 UTC 2017
Modified Files: src/lib/libc/arch/powerpc/gen: fpsetmask.c src/sys/arch/powerpc/include: instr.h src/sys/arch/powerpc/powerpc: trap.c Log Message: have fpsetmask() change the FE0/FE1 MSR bits to precise mode if any FP exceptions are enabled. fix the kernel emulation of mfmsr and mtmsr to use the correct opcodes for these instructions. ignore PSL_FE (the FP enable bit) in the MSR that a user program tries to set, since it will naturally be set for FP-using processes but we can't let the user process manage that bit. To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/lib/libc/arch/powerpc/gen/fpsetmask.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/powerpc/include/instr.h cvs rdiff -u -r1.150 -r1.151 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/lib/libc/arch/powerpc/gen/fpsetmask.c diff -u src/lib/libc/arch/powerpc/gen/fpsetmask.c:1.10 src/lib/libc/arch/powerpc/gen/fpsetmask.c:1.11 --- src/lib/libc/arch/powerpc/gen/fpsetmask.c:1.10 Sun Jul 10 21:18:47 2011 +++ src/lib/libc/arch/powerpc/gen/fpsetmask.c Mon Feb 27 06:54:00 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: fpsetmask.c,v 1.10 2011/07/10 21:18:47 matt Exp $ */ +/* $NetBSD: fpsetmask.c,v 1.11 2017/02/27 06:54:00 chs Exp $ */ /* * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: fpsetmask.c,v 1.10 2011/07/10 21:18:47 matt Exp $"); +__RCSID("$NetBSD: fpsetmask.c,v 1.11 2017/02/27 06:54:00 chs Exp $"); #endif /* LIBC_SCCS and not lint */ #include "namespace.h" @@ -39,6 +39,7 @@ __RCSID("$NetBSD: fpsetmask.c,v 1.10 201 #include <sys/types.h> #include <ieeefp.h> #include <powerpc/fpu.h> +#include <powerpc/psl.h> #ifdef __weak_alias __weak_alias(fpsetmask,_fpsetmask) @@ -47,6 +48,24 @@ __weak_alias(fpsetmask,_fpsetmask) #define MASKBITS (FPSCR_XE|FPSCR_ZE|FPSCR_UE|FPSCR_OE|FPSCR_VE) #define MASKSHFT 3 +static __inline uint32_t +mfmsr(void) +{ + uint32_t msr; + + __asm volatile ("mfmsr %0" : "=r"(msr)); + return msr; +} + +static __inline void +mtmsr(uint32_t msr) +{ + + __asm volatile ("mtmsr %0" : : "r"(msr)); +} + +#include <stdio.h> + fp_except fpsetmask(fp_except mask) { @@ -54,12 +73,20 @@ fpsetmask(fp_except mask) double u_d; uint64_t u_fpscr; } ud; - fp_except old; + fp_except old, new; + uint32_t msr; __asm volatile("mffs %0" : "=f"(ud.u_d)); old = ((uint32_t)ud.u_fpscr & MASKBITS) >> MASKSHFT; ud.u_fpscr &= ~MASKBITS; - ud.u_fpscr |= ((uint32_t)mask << MASKSHFT) & MASKBITS; + new = ((uint32_t)mask << MASKSHFT) & MASKBITS; + ud.u_fpscr |= new; __asm volatile("mtfsf 0xff,%0" :: "f"(ud.u_d)); + + msr = mfmsr(); + msr = (msr & ~(PSL_FE0 | PSL_FE1)) | + (new ? PSL_FE_PREC : PSL_FE_DIS); + mtmsr(msr); + return (old); } Index: src/sys/arch/powerpc/include/instr.h diff -u src/sys/arch/powerpc/include/instr.h:1.7 src/sys/arch/powerpc/include/instr.h:1.8 --- src/sys/arch/powerpc/include/instr.h:1.7 Fri Aug 1 21:56:36 2014 +++ src/sys/arch/powerpc/include/instr.h Mon Feb 27 06:54:00 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: instr.h,v 1.7 2014/08/01 21:56:36 matt Exp $ */ +/* $NetBSD: instr.h,v 1.8 2017/02/27 06:54:00 chs Exp $ */ /* * Copyright (c) 1992, 1993 @@ -405,7 +405,7 @@ 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 0x7c0000a8 +#define OPC_MFMSR_CODE 0x7c0000a6 #define OPC_MFMSR_MASK 0xfc1fffff #define OPC_MFMSR OPC_MFMSR_CODE #define OPC_MFMSR_REG(o) (((o) >> 21) & 0x1f) Index: src/sys/arch/powerpc/powerpc/trap.c diff -u src/sys/arch/powerpc/powerpc/trap.c:1.150 src/sys/arch/powerpc/powerpc/trap.c:1.151 --- src/sys/arch/powerpc/powerpc/trap.c:1.150 Tue Aug 12 20:27:10 2014 +++ src/sys/arch/powerpc/powerpc/trap.c Mon Feb 27 06:54:00 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.150 2014/08/12 20:27:10 joerg Exp $ */ +/* $NetBSD: trap.c,v 1.151 2017/02/27 06:54:00 chs Exp $ */ /* * Copyright (C) 1995, 1996 Wolfgang Solfrank. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.150 2014/08/12 20:27:10 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.151 2017/02/27 06:54:00 chs Exp $"); #include "opt_altivec.h" #include "opt_ddb.h" @@ -1015,6 +1015,7 @@ int emulated_opcode(struct lwp *l, struct trapframe *tf) { uint32_t opcode; + if (copyin((void *)tf->tf_srr0, &opcode, sizeof(opcode)) != 0) return 0; @@ -1038,7 +1039,7 @@ emulated_opcode(struct lwp *l, struct tr return 1; } -#define OPC_MTMSR_CODE 0x7c0000a8 +#define OPC_MTMSR_CODE 0x7c000124 #define OPC_MTMSR_MASK 0xfc1fffff #define OPC_MTMSR OPC_MTMSR_CODE #define OPC_MTMSR_REG(o) (((o) >> 21) & 0x1f) @@ -1049,15 +1050,24 @@ emulated_opcode(struct lwp *l, struct tr 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; + + /* * 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.