Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NPTL, round one.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+129 -14
+1
arch/mips/kernel/asm-offsets.c
··· 95 95 offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count); 96 96 offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit); 97 97 offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block); 98 + offset("#define TI_TP_VALUE ", struct thread_info, tp_value); 98 99 constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER); 99 100 constant("#define _THREAD_SIZE ", THREAD_SIZE); 100 101 constant("#define _THREAD_MASK ", THREAD_MASK);
+27
arch/mips/kernel/linux32.c
··· 1468 1468 } 1469 1469 return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize); 1470 1470 } 1471 + 1472 + save_static_function(sys32_clone); 1473 + __attribute_used__ noinline static int 1474 + _sys32_clone(nabi_no_regargs struct pt_regs regs) 1475 + { 1476 + unsigned long clone_flags; 1477 + unsigned long newsp; 1478 + int __user *parent_tidptr, *child_tidptr; 1479 + 1480 + clone_flags = regs.regs[4]; 1481 + newsp = regs.regs[5]; 1482 + if (!newsp) 1483 + newsp = regs.regs[29]; 1484 + parent_tidptr = (int *) regs.regs[6]; 1485 + 1486 + /* Use __dummy4 instead of getting it off the stack, so that 1487 + syscall() works. */ 1488 + child_tidptr = (int __user *) __dummy4; 1489 + return do_fork(clone_flags, newsp, &regs, 0, 1490 + parent_tidptr, child_tidptr); 1491 + } 1492 + 1493 + extern asmlinkage void sys_set_thread_area(u32 addr); 1494 + asmlinkage void sys32_set_thread_area(u32 addr) 1495 + { 1496 + sys_set_thread_area(AA(addr)); 1497 + }
+4
arch/mips/kernel/process.c
··· 89 89 struct thread_info *ti = p->thread_info; 90 90 struct pt_regs *childregs; 91 91 long childksp; 92 + p->set_child_tid = p->clear_child_tid = NULL; 92 93 93 94 childksp = (unsigned long)ti + THREAD_SIZE - 32; 94 95 ··· 134 133 p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); 135 134 childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); 136 135 clear_tsk_thread_flag(p, TIF_USEDFPU); 136 + 137 + if (clone_flags & CLONE_SETTLS) 138 + ti->tp_value = regs->regs[7]; 137 139 138 140 return 0; 139 141 }
+5
arch/mips/kernel/ptrace.c
··· 289 289 ret = ptrace_detach(child, data); 290 290 break; 291 291 292 + case PTRACE_GET_THREAD_AREA: 293 + ret = put_user(child->thread_info->tp_value, 294 + (unsigned long __user *) data); 295 + break; 296 + 292 297 default: 293 298 ret = ptrace_request(child, request, addr, data); 294 299 break;
+5
arch/mips/kernel/ptrace32.c
··· 268 268 wake_up_process(child); 269 269 break; 270 270 271 + case PTRACE_GET_THREAD_AREA: 272 + ret = put_user(child->thread_info->tp_value, 273 + (unsigned int __user *) (unsigned long) data); 274 + break; 275 + 271 276 case PTRACE_DETACH: /* detach a process that was attached. */ 272 277 ret = ptrace_detach(child, data); 273 278 break;
+1
arch/mips/kernel/scall32-o32.S
··· 623 623 sys sys_add_key 5 624 624 sys sys_request_key 4 625 625 sys sys_keyctl 5 626 + sys sys_set_thread_area 1 626 627 627 628 .endm 628 629
+1
arch/mips/kernel/scall64-64.S
··· 449 449 PTR sys_add_key 450 450 PTR sys_request_key /* 5240 */ 451 451 PTR sys_keyctl 452 + PTR sys_set_thread_area
+1
arch/mips/kernel/scall64-n32.S
··· 363 363 PTR sys_add_key 364 364 PTR sys_request_key 365 365 PTR sys_keyctl /* 6245 */ 366 + PTR sys_set_thread_area
+2 -1
arch/mips/kernel/scall64-o32.S
··· 322 322 PTR sys32_ipc 323 323 PTR sys_fsync 324 324 PTR sys32_sigreturn 325 - PTR sys_clone /* 4120 */ 325 + PTR sys32_clone /* 4120 */ 326 326 PTR sys_setdomainname 327 327 PTR sys32_newuname 328 328 PTR sys_ni_syscall /* sys_modify_ldt */ ··· 485 485 PTR sys_add_key /* 4280 */ 486 486 PTR sys_request_key 487 487 PTR sys_keyctl 488 + PTR sys_set_thread_area 488 489 .size sys_call_table,.-sys_call_table
+28 -3
arch/mips/kernel/syscall.c
··· 7 7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8 8 * Copyright (C) 2001 MIPS Technologies, Inc. 9 9 */ 10 + #include <linux/config.h> 10 11 #include <linux/a.out.h> 11 12 #include <linux/errno.h> 12 13 #include <linux/linkage.h> ··· 177 176 { 178 177 unsigned long clone_flags; 179 178 unsigned long newsp; 180 - int *parent_tidptr, *child_tidptr; 179 + int __user *parent_tidptr, *child_tidptr; 181 180 182 181 clone_flags = regs.regs[4]; 183 182 newsp = regs.regs[5]; 184 183 if (!newsp) 185 184 newsp = regs.regs[29]; 186 - parent_tidptr = (int *) regs.regs[6]; 187 - child_tidptr = (int *) regs.regs[7]; 185 + parent_tidptr = (int __user *) regs.regs[6]; 186 + #ifdef CONFIG_32BIT 187 + /* We need to fetch the fifth argument off the stack. */ 188 + child_tidptr = NULL; 189 + if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) { 190 + int __user *__user *usp = (int __user *__user *) regs.regs[29]; 191 + if (regs.regs[2] == __NR_syscall) { 192 + if (get_user (child_tidptr, &usp[5])) 193 + return -EFAULT; 194 + } 195 + else if (get_user (child_tidptr, &usp[4])) 196 + return -EFAULT; 197 + } 198 + #else 199 + child_tidptr = (int __user *) regs.regs[8]; 200 + #endif 188 201 return do_fork(clone_flags, newsp, &regs, 0, 189 202 parent_tidptr, child_tidptr); 190 203 } ··· 258 243 error = error ? -EFAULT : 0; 259 244 260 245 return error; 246 + } 247 + 248 + void sys_set_thread_area(unsigned long addr) 249 + { 250 + struct thread_info *ti = current->thread_info; 251 + 252 + ti->tp_value = addr; 253 + 254 + /* If some future MIPS implementation has this register in hardware, 255 + * we will need to update it here (and in context switches). */ 261 256 } 262 257 263 258 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
+43 -3
arch/mips/kernel/traps.c
··· 360 360 #define OFFSET 0x0000ffff 361 361 #define LL 0xc0000000 362 362 #define SC 0xe0000000 363 + #define SPEC3 0x7c000000 364 + #define RD 0x0000f800 365 + #define FUNC 0x0000003f 366 + #define RDHWR 0x0000003b 363 367 364 368 /* 365 369 * The ll_bit is cleared by r*_switch.S ··· 497 493 } 498 494 499 495 return -EFAULT; /* Strange things going on ... */ 496 + } 497 + 498 + /* 499 + * Simulate trapping 'rdhwr' instructions to provide user accessible 500 + * registers not implemented in hardware. The only current use of this 501 + * is the thread area pointer. 502 + */ 503 + static inline int simulate_rdhwr(struct pt_regs *regs) 504 + { 505 + struct thread_info *ti = current->thread_info; 506 + unsigned int opcode; 507 + 508 + if (unlikely(get_insn_opcode(regs, &opcode))) 509 + return -EFAULT; 510 + 511 + if (unlikely(compute_return_epc(regs))) 512 + return -EFAULT; 513 + 514 + if ((opcode & OPCODE) == SPEC3 && (opcode & FUNC) == RDHWR) { 515 + int rd = (opcode & RD) >> 11; 516 + int rt = (opcode & RT) >> 16; 517 + switch (rd) { 518 + case 29: 519 + regs->regs[rt] = ti->tp_value; 520 + break; 521 + default: 522 + return -EFAULT; 523 + } 524 + } 525 + 526 + return 0; 500 527 } 501 528 502 529 asmlinkage void do_ov(struct pt_regs *regs) ··· 676 641 if (!simulate_llsc(regs)) 677 642 return; 678 643 644 + if (!simulate_rdhwr(regs)) 645 + return; 646 + 679 647 force_sig(SIGILL, current); 680 648 } 681 649 ··· 692 654 693 655 switch (cpid) { 694 656 case 0: 695 - if (cpu_has_llsc) 696 - break; 657 + if (!cpu_has_llsc) 658 + if (!simulate_llsc(regs)) 659 + return; 697 660 698 - if (!simulate_llsc(regs)) 661 + if (!simulate_rdhwr(regs)) 699 662 return; 663 + 700 664 break; 701 665 702 666 case 1:
+1 -1
include/asm-mips/inst.h
··· 28 28 sdl_op, sdr_op, swr_op, cache_op, 29 29 ll_op, lwc1_op, lwc2_op, pref_op, 30 30 lld_op, ldc1_op, ldc2_op, ld_op, 31 - sc_op, swc1_op, swc2_op, major_3b_op, /* Opcode 0x3b is unused */ 31 + sc_op, swc1_op, swc2_op, rdhwr_op, 32 32 scd_op, sdc1_op, sdc2_op, sd_op 33 33 }; 34 34
+1
include/asm-mips/thread_info.h
··· 26 26 struct task_struct *task; /* main task structure */ 27 27 struct exec_domain *exec_domain; /* execution domain */ 28 28 unsigned long flags; /* low level flags */ 29 + unsigned long tp_value; /* thread pointer */ 29 30 __u32 cpu; /* current CPU */ 30 31 int preempt_count; /* 0 => preemptable, <0 => BUG */ 31 32
+9 -6
include/asm-mips/unistd.h
··· 303 303 #define __NR_add_key (__NR_Linux + 280) 304 304 #define __NR_request_key (__NR_Linux + 281) 305 305 #define __NR_keyctl (__NR_Linux + 282) 306 + #define __NR_set_thread_area (__NR_Linux + 283) 306 307 307 308 /* 308 309 * Offset of the last Linux o32 flavoured syscall 309 310 */ 310 - #define __NR_Linux_syscalls 282 311 + #define __NR_Linux_syscalls 283 311 312 312 313 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ 313 314 314 315 #define __NR_O32_Linux 4000 315 - #define __NR_O32_Linux_syscalls 282 316 + #define __NR_O32_Linux_syscalls 283 316 317 317 318 #if _MIPS_SIM == _MIPS_SIM_ABI64 318 319 ··· 563 562 #define __NR_add_key (__NR_Linux + 239) 564 563 #define __NR_request_key (__NR_Linux + 240) 565 564 #define __NR_keyctl (__NR_Linux + 241) 565 + #define __NR_set_thread_area (__NR_Linux + 242) 566 566 567 567 /* 568 568 * Offset of the last Linux 64-bit flavoured syscall 569 569 */ 570 - #define __NR_Linux_syscalls 241 570 + #define __NR_Linux_syscalls 242 571 571 572 572 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ 573 573 574 574 #define __NR_64_Linux 5000 575 - #define __NR_64_Linux_syscalls 241 575 + #define __NR_64_Linux_syscalls 242 576 576 577 577 #if _MIPS_SIM == _MIPS_SIM_NABI32 578 578 ··· 827 825 #define __NR_add_key (__NR_Linux + 243) 828 826 #define __NR_request_key (__NR_Linux + 244) 829 827 #define __NR_keyctl (__NR_Linux + 245) 828 + #define __NR_set_thread_area (__NR_Linux + 246) 830 829 831 830 /* 832 831 * Offset of the last N32 flavoured syscall 833 832 */ 834 - #define __NR_Linux_syscalls 245 833 + #define __NR_Linux_syscalls 246 835 834 836 835 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ 837 836 838 837 #define __NR_N32_Linux 6000 839 - #define __NR_N32_Linux_syscalls 245 838 + #define __NR_N32_Linux_syscalls 246 840 839 841 840 #ifndef __ASSEMBLY__ 842 841