Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/arm Add a cp15 trapper to emulate the mrc/mcr i...
details: https://anonhg.NetBSD.org/src/rev/9882c93cce34
branches: trunk
changeset: 763930:9882c93cce34
user: matt <matt%NetBSD.org@localhost>
date: Thu Apr 07 11:02:24 2011 +0000
description:
Add a cp15 trapper to emulate the mrc/mcr instructions for the thread id
registers.
diffstat:
sys/arch/arm/arm/undefined.c | 58 ++++++++++++++++++++++++++++++++++++++++---
1 files changed, 54 insertions(+), 4 deletions(-)
diffs (97 lines):
diff -r 4c5a8df3e35a -r 9882c93cce34 sys/arch/arm/arm/undefined.c
--- a/sys/arch/arm/arm/undefined.c Thu Apr 07 11:01:49 2011 +0000
+++ b/sys/arch/arm/arm/undefined.c Thu Apr 07 11:02:24 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: undefined.c,v 1.40 2010/12/20 00:25:26 matt Exp $ */
+/* $NetBSD: undefined.c,v 1.41 2011/04/07 11:02:24 matt Exp $ */
/*
* Copyright (c) 2001 Ben Harris.
@@ -54,7 +54,7 @@
#include <sys/kgdb.h>
#endif
-__KERNEL_RCSID(0, "$NetBSD: undefined.c,v 1.40 2010/12/20 00:25:26 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: undefined.c,v 1.41 2011/04/07 11:02:24 matt Exp $");
#include <sys/malloc.h>
#include <sys/queue.h>
@@ -122,12 +122,57 @@
free(uh, M_TEMP);
}
+static int
+cp15_trapper(u_int addr, u_int insn, struct trapframe *frame, int code)
+{
+ struct lwp * const l = curlwp;
+
+#ifdef THUMB_CODE
+ if (frame->tf_spsr & PSR_T_bit)
+ return 1;
+#endif
+ if (code != FAULT_USER)
+ return 1;
+
+ /*
+ * Don't overwrite sp, pc, etc.
+ */
+ const u_int regno = (insn >> 12) & 15;
+ if (regno > 12)
+ return 1;
+
+ /*
+ * Get a pointer to the register used in the instruction to be emulated.
+ */
+ register_t * const regp = &frame->tf_r0 + regno;
+
+ /*
+ * Handle MRC p15, 0, <Rd>, c13, c0, 3 (Read User read-only thread id)
+ */
+ if ((insn & 0xffff0fff) == 0xee1d0f70) {
+ *regp = (uintptr_t)l->l_private;
+ return 0;
+ }
+
+ /*
+ * Handle {MRC,MCR} p15, 0, <Rd>, c13, c0, 2 (User read/write thread id)
+ */
+ if ((insn & 0xffef0fff) == 0xee0d0f50) {
+ struct pcb * const pcb = lwp_getpcb(l);
+ if (insn & 0x00100000)
+ *regp = pcb->pcb_user_pid_rw;
+ else
+ pcb->pcb_user_pid_rw = *regp;
+ return 0;
+ }
+
+ return 1;
+}
static int
gdb_trapper(u_int addr, u_int insn, struct trapframe *frame, int code)
{
- struct lwp *l;
- l = curlwp;
+ struct lwp * const l = curlwp;
#ifdef THUMB_CODE
if (frame->tf_spsr & PSR_T_bit) {
@@ -160,6 +205,7 @@
return 1;
}
+static struct undefined_handler cp15_uh;
static struct undefined_handler gdb_uh;
#ifdef THUMB_CODE
static struct undefined_handler gdb_uh_thumb;
@@ -174,6 +220,10 @@
for (loop = 0; loop < NUM_UNKNOWN_HANDLERS; ++loop)
LIST_INIT(&undefined_handlers[loop]);
+ /* Install handler for CP15 emulation */
+ cp15_uh.uh_handler = cp15_trapper;
+ install_coproc_handler_static(SYSTEM_COPROC, &cp15_uh);
+
/* Install handler for GDB breakpoints */
gdb_uh.uh_handler = gdb_trapper;
install_coproc_handler_static(CORE_UNKNOWN_HANDLER, &gdb_uh);
Home |
Main Index |
Thread Index |
Old Index