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