Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src have fpsetmask() change the FE0/FE1 MSR bits to precise mode...



details:   https://anonhg.NetBSD.org/src/rev/0dee6e4ee952
branches:  trunk
changeset: 822040:0dee6e4ee952
user:      chs <chs%NetBSD.org@localhost>
date:      Mon Feb 27 06:54:00 2017 +0000

description:
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.

diffstat:

 lib/libc/arch/powerpc/gen/fpsetmask.c |  35 +++++++++++++++++++++++++++++++----
 sys/arch/powerpc/include/instr.h      |   4 ++--
 sys/arch/powerpc/powerpc/trap.c       |  16 +++++++++++++---
 3 files changed, 46 insertions(+), 9 deletions(-)

diffs (152 lines):

diff -r 30e7cb15a138 -r 0dee6e4ee952 lib/libc/arch/powerpc/gen/fpsetmask.c
--- a/lib/libc/arch/powerpc/gen/fpsetmask.c     Mon Feb 27 06:51:46 2017 +0000
+++ b/lib/libc/arch/powerpc/gen/fpsetmask.c     Mon Feb 27 06:54:00 2017 +0000
@@ -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 @@
 #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 @@
 #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 @@
                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);
 }
diff -r 30e7cb15a138 -r 0dee6e4ee952 sys/arch/powerpc/include/instr.h
--- a/sys/arch/powerpc/include/instr.h  Mon Feb 27 06:51:46 2017 +0000
+++ b/sys/arch/powerpc/include/instr.h  Mon Feb 27 06:54:00 2017 +0000
@@ -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 @@
 #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)
diff -r 30e7cb15a138 -r 0dee6e4ee952 sys/arch/powerpc/powerpc/trap.c
--- a/sys/arch/powerpc/powerpc/trap.c   Mon Feb 27 06:51:46 2017 +0000
+++ b/sys/arch/powerpc/powerpc/trap.c   Mon Feb 27 06:54:00 2017 +0000
@@ -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 @@
 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 @@
                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 @@
                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.



Home | Main Index | Thread Index | Old Index