Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-9]: src/sys/arch/hppa/hppa Pull up following revision(s) (request...
details: https://anonhg.NetBSD.org/src/rev/dc09027cda75
branches: netbsd-9
changeset: 366707:dc09027cda75
user: martin <martin%NetBSD.org@localhost>
date: Fri Jun 10 16:28:16 2022 +0000
description:
Pull up following revision(s) (requested by skrll in ticket #1466):
sys/arch/hppa/hppa/trap.c: revision 1.119
Handle 'NA' (non-access) traps for the lpa and probe instructions. The
change is inspired by OpenBSD with a bunch of my own, mainly stylistic,
changes.
Thanks to Tom Lane for the analysis.
PR/56118: sporadic app crashes in HPPA -current
diffstat:
sys/arch/hppa/hppa/trap.c | 161 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 157 insertions(+), 4 deletions(-)
diffs (199 lines):
diff -r 3b60bae5208d -r dc09027cda75 sys/arch/hppa/hppa/trap.c
--- a/sys/arch/hppa/hppa/trap.c Mon Jun 06 11:36:16 2022 +0000
+++ b/sys/arch/hppa/hppa/trap.c Fri Jun 10 16:28:16 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.111.4.1 2020/04/25 10:52:56 martin Exp $ */
+/* $NetBSD: trap.c,v 1.111.4.2 2022/06/10 16:28:16 martin Exp $ */
/*-
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.111.4.1 2020/04/25 10:52:56 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.111.4.2 2022/06/10 16:28:16 martin Exp $");
/* #define INTRDEBUG */
/* #define TRAPDEBUG */
@@ -480,6 +480,93 @@
}
#endif /* DEBUG */
+
+#define __PABITS(x, y) __BITS(31 - (x), 31 - (y))
+#define __PABIT(x) __BIT(31 - (x))
+
+#define LPA_MASK \
+ ( __PABITS(0, 5) | \
+ __PABITS(18, 25))
+#define LPA \
+ (__SHIFTIN(1, __PABITS(0, 5)) | \
+ __SHIFTIN(0x4d, __PABITS(18, 25)))
+
+
+#define PROBE_ENCS (0x46 | 0xc6 | 0x47 | 0xc7)
+#define PROBE_PL __PABITS(14, 15)
+#define PROBE_IMMED __PABIT(18)
+#define PROBE_RW __PABIT(25)
+
+#define PROBE_MASK \
+ (( __PABITS(0, 5) | \
+ __PABITS(18, 25) | \
+ __PABIT(26)) ^ \
+ (PROBE_IMMED | PROBE_RW))
+
+#define PROBE \
+ ((__SHIFTIN(1, __PABITS(0, 5)) | \
+ __SHIFTIN(PROBE_ENCS, __PABITS(18, 25)) | \
+ __SHIFTIN(0, __PABIT(26))) ^ \
+ (PROBE_IMMED | PROBE_RW))
+
+/* for hppa64 */
+CTASSERT(sizeof(register_t) == sizeof(u_int));
+size_t hppa_regmap[] = {
+ 0, /* r0 is special case */
+ offsetof(struct trapframe, tf_r1 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_rp ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r3 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r4 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r5 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r6 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r7 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r8 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r9 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r10 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r11 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r12 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r13 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r14 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r15 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r16 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r17 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r18 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_t4 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_t3 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_t2 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_t1 ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_arg3) / sizeof(register_t),
+ offsetof(struct trapframe, tf_arg2) / sizeof(register_t),
+ offsetof(struct trapframe, tf_arg1) / sizeof(register_t),
+ offsetof(struct trapframe, tf_arg0) / sizeof(register_t),
+ offsetof(struct trapframe, tf_dp ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_ret0) / sizeof(register_t),
+ offsetof(struct trapframe, tf_ret1) / sizeof(register_t),
+ offsetof(struct trapframe, tf_sp ) / sizeof(register_t),
+ offsetof(struct trapframe, tf_r31 ) / sizeof(register_t),
+};
+
+
+static inline register_t
+tf_getregno(struct trapframe *tf, u_int regno)
+{
+ register_t *tf_reg = (register_t *)tf;
+ if (regno == 0)
+ return 0;
+ else
+ return tf_reg[hppa_regmap[regno]];
+}
+
+static inline void
+tf_setregno(struct trapframe *tf, u_int regno, register_t val)
+{
+ register_t *tf_reg = (register_t *)tf;
+ if (regno == 0)
+ return;
+ else
+ tf_reg[hppa_regmap[regno]] = val;
+}
+
void
trap(int type, struct trapframe *frame)
{
@@ -593,6 +680,7 @@
mtctl(frame->tf_eiem, CR_EIEM);
}
+ const bool user = (type & T_USER) != 0;
switch (type) {
case T_NONEXIST:
case T_NONEXIST|T_USER:
@@ -817,11 +905,76 @@
trapsignal(l, &ksi);
break;
+ case T_ITLBMISSNA: case T_USER | T_ITLBMISSNA:
+ case T_DTLBMISSNA: case T_USER | T_DTLBMISSNA:
+ vm = p->p_vmspace;
+
+ if (!vm) {
+#ifdef TRAPDEBUG
+ printf("trap: no vm, p=%p\n", p);
+#endif
+ goto dead_end;
+ }
+
+ /*
+ * it could be a kernel map for exec_map faults
+ */
+ if (!user && space == HPPA_SID_KERNEL)
+ map = kernel_map;
+ else {
+ map = &vm->vm_map;
+ }
+
+ va = trunc_page(va);
+
+ if ((opcode & LPA_MASK) == LPA) {
+ /* lpa failure case */
+ const u_int regno =
+ __SHIFTOUT(opcode, __PABITS(27, 31));
+ tf_setregno(frame, regno, 0);
+ frame->tf_ipsw |= PSW_N;
+ } else if ((opcode & PROBE_MASK) == PROBE) {
+ u_int pl;
+ if ((opcode & PROBE_IMMED) == 0) {
+ pl = __SHIFTOUT(opcode, __PABITS(14, 15));
+ } else {
+ const u_int plreg =
+ __SHIFTOUT(opcode, __PABITS(11, 15));
+ pl = tf_getregno(frame, plreg);
+ }
+ bool ok = true;
+ if ((user && space == HPPA_SID_KERNEL) ||
+ (frame->tf_iioq_head & 3) != pl ||
+ (user && va >= VM_MAXUSER_ADDRESS)) {
+ ok = false;
+ } else {
+ /* Never call uvm_fault in interrupt context. */
+ KASSERT(curcpu()->ci_intr_depth == 0);
+
+ const bool read =
+ __SHIFTOUT(opcode, PROBE_RW) == 0;
+ onfault = pcb->pcb_onfault;
+ pcb->pcb_onfault = 0;
+ ret = uvm_fault(map, va, read ?
+ VM_PROT_READ : VM_PROT_WRITE);
+ pcb->pcb_onfault = onfault;
+
+ if (ret)
+ ok = false;
+ }
+ if (!ok) {
+ const u_int regno =
+ __SHIFTOUT(opcode, __PABITS(27, 31));
+ tf_setregno(frame, regno, 0);
+ frame->tf_ipsw |= PSW_N;
+ }
+ } else {
+ }
+ break;
+
case T_DATACC: case T_USER | T_DATACC:
case T_ITLBMISS: case T_USER | T_ITLBMISS:
case T_DTLBMISS: case T_USER | T_DTLBMISS:
- case T_ITLBMISSNA: case T_USER | T_ITLBMISSNA:
- case T_DTLBMISSNA: case T_USER | T_DTLBMISSNA:
case T_TLB_DIRTY: case T_USER | T_TLB_DIRTY:
vm = p->p_vmspace;
Home |
Main Index |
Thread Index |
Old Index