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