Author: gonzo
Date: Thu Feb  9 22:17:13 2012
New Revision: 231312
URL: http://svn.freebsd.org/changeset/base/231312

Log:
  - Emulate RDHWR instruction for TLS support
  
  Reading register $29 with RDHWR is becoming the de-facto standard to
  implement TLS.  According to linux-mips wiki, MIPS Technologies has
  reserved hardware register $29 for ABI use.  Furthermore current GCC
  makes the following assumptions:
  - RDHWR is natively available or otherwise emulated by the kernel
  - Register $29 holds the TLS pointer
  
  Submitted by: Robert Millan <r...@debian.org>

Modified:
  head/sys/mips/include/mips_opcode.h
  head/sys/mips/mips/trap.c

Modified: head/sys/mips/include/mips_opcode.h
==============================================================================
--- head/sys/mips/include/mips_opcode.h Thu Feb  9 22:13:20 2012        
(r231311)
+++ head/sys/mips/include/mips_opcode.h Thu Feb  9 22:17:13 2012        
(r231312)
@@ -176,6 +176,11 @@ typedef union {
 #define        OP_LDL          032
 #define        OP_LDR          033
 
+#define OP_SPECIAL2    034
+#define OP_JALX                035
+
+#define OP_SPECIAL3    037
+
 #define        OP_LB           040
 #define        OP_LH           041
 #define        OP_LWL          042
@@ -389,6 +394,11 @@ typedef union {
 #define        OP_R_BGEZALL    OP_BGEZALL
 
 /*
+ * Values for the 'func' field when 'op' == OP_SPECIAL3.
+ */
+#define        OP_RDHWR        073
+
+/*
  * Values for the 'rs' field when 'op' == OP_COPz.
  */
 #define        OP_MF           000

Modified: head/sys/mips/mips/trap.c
==============================================================================
--- head/sys/mips/mips/trap.c   Thu Feb  9 22:13:20 2012        (r231311)
+++ head/sys/mips/mips/trap.c   Thu Feb  9 22:17:13 2012        (r231312)
@@ -414,6 +414,7 @@ trap(struct trapframe *trapframe)
        intptr_t addr = 0;
        register_t pc;
        int cop;
+       register_t *frame_regs;
 
        trapdebug_enter(trapframe, 0);
        
@@ -762,9 +763,29 @@ dofault:
                }
 
        case T_RES_INST + T_USER:
-               log_illegal_instruction("RES_INST", trapframe);
-               i = SIGILL;
-               addr = trapframe->pc;
+               {
+                       InstFmt inst;
+                       inst = *(InstFmt *)trapframe->pc;
+                       switch (inst.RType.op) {
+                       case OP_SPECIAL3:
+                               switch (inst.RType.func) {
+                               case OP_RDHWR:
+                                       /* Register 29 used for TLS */
+                                       if (inst.RType.rd == 29) {
+                                               frame_regs = &(trapframe->zero);
+                                               frame_regs[inst.RType.rt] = 
(register_t)td->td_md.md_tls;
+                                               trapframe->pc += sizeof(int);
+                                               goto out;
+                                       }
+                               break;
+                               }
+                       break;
+                       }
+
+                       log_illegal_instruction("RES_INST", trapframe);
+                       i = SIGILL;
+                       addr = trapframe->pc;
+               }
                break;
        case T_C2E:
        case T_C2E + T_USER:
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to