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

Reply via email to