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/274d36c5e233
branches: trunk
changeset: 351789:274d36c5e233
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 1ccc2dc93f4f -r 274d36c5e233 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 1ccc2dc93f4f -r 274d36c5e233 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 1ccc2dc93f4f -r 274d36c5e233 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