linux-cvs-patches
[Top] [All Lists]

CVS Update@linux-mips.org: linux

To: linux-cvs-patches@linux-mips.org
Subject: CVS Update@linux-mips.org: linux
From: ralf@linux-mips.org
Date: Wed, 13 Apr 2005 18:44:05 +0100
Reply-to: linux-mips@linux-mips.org
Sender: linux-cvs-patches-bounce@linux-mips.org
CVSROOT:        /home/cvs
Module name:    linux
Changes by:     ralf@ftp.linux-mips.org 05/04/13 18:44:00

Modified files:
        arch/mips/kernel: linux32.c offset.c process.c ptrace.c 
                          ptrace32.c scall32-o32.S scall64-64.S 
                          scall64-n32.S scall64-o32.S syscall.c traps.c 
        include/asm-mips: inst.h thread_info.h unistd.h 

Log message:
        NPTL, round one.

diff -urN linux/arch/mips/kernel/linux32.c linux/arch/mips/kernel/linux32.c
--- linux/arch/mips/kernel/linux32.c    2005/02/16 21:25:03     1.27
+++ linux/arch/mips/kernel/linux32.c    2005/04/13 17:43:59     1.28
@@ -1471,3 +1471,30 @@
        }
        return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);
 }
+
+save_static_function(sys32_clone);
+__attribute_used__ noinline static int
+_sys32_clone(nabi_no_regargs struct pt_regs regs)
+{
+       unsigned long clone_flags;
+       unsigned long newsp;
+       int __user *parent_tidptr, *child_tidptr;
+
+       clone_flags = regs.regs[4];
+       newsp = regs.regs[5];
+       if (!newsp)
+               newsp = regs.regs[29];
+       parent_tidptr = (int *) regs.regs[6];
+
+       /* Use __dummy4 instead of getting it off the stack, so that
+          syscall() works.  */
+       child_tidptr = (int __user *) __dummy4;
+       return do_fork(clone_flags, newsp, &regs, 0,
+                      parent_tidptr, child_tidptr);
+}
+
+extern asmlinkage void sys_set_thread_area(u32 addr);
+asmlinkage void sys32_set_thread_area(u32 addr)
+{
+       sys_set_thread_area(AA(addr));
+}
diff -urN linux/arch/mips/kernel/offset.c linux/arch/mips/kernel/offset.c
--- linux/arch/mips/kernel/offset.c     2004/11/25 13:40:10     1.16
+++ linux/arch/mips/kernel/offset.c     2005/04/13 17:43:59     1.17
@@ -95,6 +95,7 @@
        offset("#define TI_PRE_COUNT       ", struct thread_info, 
preempt_count);
        offset("#define TI_ADDR_LIMIT      ", struct thread_info, addr_limit);
        offset("#define TI_RESTART_BLOCK   ", struct thread_info, 
restart_block);
+       offset("#define TI_TP_VALUE        ", struct thread_info, tp_value);
        constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
        constant("#define _THREAD_SIZE       ", THREAD_SIZE);
        constant("#define _THREAD_MASK       ", THREAD_MASK);
diff -urN linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- linux/arch/mips/kernel/process.c    2005/03/14 10:16:59     1.77
+++ linux/arch/mips/kernel/process.c    2005/04/13 17:43:59     1.78
@@ -89,6 +89,7 @@
        struct thread_info *ti = p->thread_info;
        struct pt_regs *childregs;
        long childksp;
+       p->set_child_tid = p->clear_child_tid = NULL;
 
        childksp = (unsigned long)ti + THREAD_SIZE - 32;
 
@@ -134,6 +135,9 @@
        childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
        clear_tsk_thread_flag(p, TIF_USEDFPU);
 
+       if (clone_flags & CLONE_SETTLS)
+               ti->tp_value = regs->regs[7];
+       
        return 0;
 }
 
diff -urN linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- linux/arch/mips/kernel/ptrace.c     2005/03/18 17:36:53     1.60
+++ linux/arch/mips/kernel/ptrace.c     2005/04/13 17:43:59     1.61
@@ -289,6 +289,11 @@
                ret = ptrace_detach(child, data);
                break;
 
+       case PTRACE_GET_THREAD_AREA:
+               ret = put_user(child->thread_info->tp_value,
+                               (unsigned long __user *) data);
+               break;
+
        default:
                ret = ptrace_request(child, request, addr, data);
                break;
diff -urN linux/arch/mips/kernel/ptrace32.c linux/arch/mips/kernel/ptrace32.c
--- linux/arch/mips/kernel/ptrace32.c   2005/02/16 21:22:40     1.5
+++ linux/arch/mips/kernel/ptrace32.c   2005/04/13 17:43:59     1.6
@@ -268,6 +268,11 @@
                wake_up_process(child);
                break;
 
+       case PTRACE_GET_THREAD_AREA:
+               ret = put_user(child->thread_info->tp_value,
+                               (unsigned int __user *) (unsigned long) data);
+               break;
+
        case PTRACE_DETACH: /* detach a process that was attached. */
                ret = ptrace_detach(child, data);
                break;
diff -urN linux/arch/mips/kernel/scall32-o32.S 
linux/arch/mips/kernel/scall32-o32.S
--- linux/arch/mips/kernel/scall32-o32.S        2005/03/13 00:07:00     1.25
+++ linux/arch/mips/kernel/scall32-o32.S        2005/04/13 17:43:59     1.26
@@ -623,6 +623,7 @@
        sys     sys_add_key             5
        sys     sys_request_key         4
        sys     sys_keyctl              5
+       sys     sys_set_thread_area     1
 
        .endm
 
diff -urN linux/arch/mips/kernel/scall64-64.S 
linux/arch/mips/kernel/scall64-64.S
--- linux/arch/mips/kernel/scall64-64.S 2005/01/07 16:54:47     1.28
+++ linux/arch/mips/kernel/scall64-64.S 2005/04/13 17:44:00     1.29
@@ -449,3 +449,4 @@
        PTR     sys_add_key
        PTR     sys_request_key                 /* 5240 */
        PTR     sys_keyctl
+       PTR     sys_set_thread_area
diff -urN linux/arch/mips/kernel/scall64-n32.S 
linux/arch/mips/kernel/scall64-n32.S
--- linux/arch/mips/kernel/scall64-n32.S        2005/04/13 09:11:22     1.29
+++ linux/arch/mips/kernel/scall64-n32.S        2005/04/13 17:44:00     1.30
@@ -363,3 +363,4 @@
        PTR     sys_add_key
        PTR     sys_request_key
        PTR     sys_keyctl                      /* 6245 */
+       PTR     sys_set_thread_area
diff -urN linux/arch/mips/kernel/scall64-o32.S 
linux/arch/mips/kernel/scall64-o32.S
--- linux/arch/mips/kernel/scall64-o32.S        2005/02/16 21:25:03     1.35
+++ linux/arch/mips/kernel/scall64-o32.S        2005/04/13 17:44:00     1.36
@@ -322,7 +322,7 @@
        PTR     sys32_ipc
        PTR     sys_fsync
        PTR     sys32_sigreturn
-       PTR     sys_clone                       /* 4120 */
+       PTR     sys32_clone                     /* 4120 */
        PTR     sys_setdomainname
        PTR     sys32_newuname
        PTR     sys_ni_syscall                  /* sys_modify_ldt */
@@ -485,4 +485,5 @@
        PTR     sys_add_key                     /* 4280 */
        PTR     sys_request_key
        PTR     sys_keyctl
+       PTR     sys_set_thread_area
        .size   sys_call_table,.-sys_call_table
diff -urN linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- linux/arch/mips/kernel/syscall.c    2005/04/12 16:43:52     1.51
+++ linux/arch/mips/kernel/syscall.c    2005/04/13 17:44:00     1.52
@@ -176,14 +176,28 @@
 {
        unsigned long clone_flags;
        unsigned long newsp;
-       int *parent_tidptr, *child_tidptr;
+       int __user *parent_tidptr, *child_tidptr;
 
        clone_flags = regs.regs[4];
        newsp = regs.regs[5];
        if (!newsp)
                newsp = regs.regs[29];
-       parent_tidptr = (int *) regs.regs[6];
-       child_tidptr = (int *) regs.regs[7];
+       parent_tidptr = (int __user *) regs.regs[6];
+#ifdef CONFIG_MIPS32
+       /* We need to fetch the fifth argument off the stack.  */
+       child_tidptr = NULL;
+       if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
+               int __user *__user *usp = (int __user *__user *) regs.regs[29];
+               if (regs.regs[2] == __NR_syscall) {
+                       if (get_user (child_tidptr, &usp[5]))
+                               return -EFAULT;
+               }
+               else if (get_user (child_tidptr, &usp[4]))
+                       return -EFAULT;
+       }
+#else
+       child_tidptr = (int __user *) regs.regs[8];
+#endif
        return do_fork(clone_flags, newsp, &regs, 0,
                       parent_tidptr, child_tidptr);
 }
@@ -245,6 +259,16 @@
        return error;
 }
 
+void sys_set_thread_area(unsigned long addr)
+{
+       struct thread_info *ti = current->thread_info;
+
+       ti->tp_value = addr;
+
+       /* If some future MIPS implementation has this register in hardware,
+        * we will need to update it here (and in context switches).  */
+}
+
 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
 {
        int     tmp, len;
diff -urN linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- linux/arch/mips/kernel/traps.c      2005/04/12 20:26:05     1.212
+++ linux/arch/mips/kernel/traps.c      2005/04/13 17:44:00     1.213
@@ -360,6 +360,10 @@
 #define OFFSET 0x0000ffff
 #define LL     0xc0000000
 #define SC     0xe0000000
+#define SPEC3  0x7c000000
+#define RD     0x0000f800
+#define FUNC   0x0000003f
+#define RDHWR  0x0000003b
 
 /*
  * The ll_bit is cleared by r*_switch.S
@@ -495,6 +499,37 @@
        return -EFAULT;                 /* Strange things going on ... */
 }
 
+/*
+ * Simulate trapping 'rdhwr' instructions to provide user accessible
+ * registers not implemented in hardware.  The only current use of this
+ * is the thread area pointer.
+ */
+static inline int simulate_rdhwr(struct pt_regs *regs)
+{
+       struct thread_info *ti = current->thread_info;
+       unsigned int opcode;
+
+       if (unlikely(get_insn_opcode(regs, &opcode)))
+               return -EFAULT;
+
+       if (unlikely(compute_return_epc(regs)))
+               return -EFAULT;
+
+       if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) {
+               int rd = (opcode & RD) >> 11;
+               int rt = (opcode & RT) >> 16;
+               switch (rd) {
+                       case 29:
+                               regs->regs[rt] = ti->tp_value;
+                               break;
+                       default:
+                               return -EFAULT;
+               }
+       }
+
+       return 0;
+}
+
 asmlinkage void do_ov(struct pt_regs *regs)
 {
        siginfo_t info;
@@ -641,6 +676,9 @@
                if (!simulate_llsc(regs))
                        return;
 
+       if (!simulate_rdhwr(regs))
+               return;
+
        force_sig(SIGILL, current);
 }
 
@@ -654,11 +692,13 @@
 
        switch (cpid) {
        case 0:
-               if (cpu_has_llsc)
-                       break;
+               if (!cpu_has_llsc)
+                       if (!simulate_llsc(regs))
+                               return;
 
-               if (!simulate_llsc(regs))
+               if (!simulate_rdhwr(regs))
                        return;
+
                break;
 
        case 1:
diff -urN linux/include/asm-mips/inst.h linux/include/asm-mips/inst.h
--- linux/include/asm-mips/inst.h       2000/11/25 04:49:47     1.3
+++ linux/include/asm-mips/inst.h       2005/04/13 17:44:00     1.4
@@ -28,7 +28,7 @@
        sdl_op, sdr_op, swr_op, cache_op,
        ll_op, lwc1_op, lwc2_op, pref_op,
        lld_op, ldc1_op, ldc2_op, ld_op,
-       sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */
+       sc_op, swc1_op, swc2_op, rdhwr_op,
        scd_op, sdc1_op, sdc2_op, sd_op
 };
 
diff -urN linux/include/asm-mips/thread_info.h 
linux/include/asm-mips/thread_info.h
--- linux/include/asm-mips/thread_info.h        2005/03/18 17:38:08     1.19
+++ linux/include/asm-mips/thread_info.h        2005/04/13 17:44:00     1.20
@@ -26,6 +26,7 @@
        struct task_struct      *task;          /* main task structure */
        struct exec_domain      *exec_domain;   /* execution domain */
        unsigned long           flags;          /* low level flags */
+       unsigned long           tp_value;       /* thread pointer */
        __u32                   cpu;            /* current CPU */
        __s32                   preempt_count; /* 0 => preemptable, <0 => BUG */
 
diff -urN linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h
--- linux/include/asm-mips/unistd.h     2005/03/18 17:38:08     1.73
+++ linux/include/asm-mips/unistd.h     2005/04/13 17:44:00     1.74
@@ -303,16 +303,17 @@
 #define __NR_add_key                   (__NR_Linux + 280)
 #define __NR_request_key               (__NR_Linux + 281)
 #define __NR_keyctl                    (__NR_Linux + 282)
+#define __NR_set_thread_area           (__NR_Linux + 283)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            282
+#define __NR_Linux_syscalls            283
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                282
+#define __NR_O32_Linux_syscalls                283
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -562,16 +563,17 @@
 #define __NR_add_key                   (__NR_Linux + 239)
 #define __NR_request_key               (__NR_Linux + 240)
 #define __NR_keyctl                    (__NR_Linux + 241)
+#define __NR_set_thread_area           (__NR_Linux + 242)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            241
+#define __NR_Linux_syscalls            242
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         241
+#define __NR_64_Linux_syscalls         242
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -825,16 +827,17 @@
 #define __NR_add_key                   (__NR_Linux + 243)
 #define __NR_request_key               (__NR_Linux + 244)
 #define __NR_keyctl                    (__NR_Linux + 245)
+#define __NR_set_thread_area           (__NR_Linux + 246)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            245
+#define __NR_Linux_syscalls            246
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                245
+#define __NR_N32_Linux_syscalls                246
 
 #ifndef __ASSEMBLY__
 

<Prev in Thread] Current Thread [Next in Thread>