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.

Reply via email to