NPTL, round one.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
38551576a3
commit
3c37026d43
|
@ -95,6 +95,7 @@ void output_thread_info_defines(void)
|
||||||
offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
|
offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count);
|
||||||
offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
|
offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit);
|
||||||
offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block);
|
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_ORDER ", THREAD_SIZE_ORDER);
|
||||||
constant("#define _THREAD_SIZE ", THREAD_SIZE);
|
constant("#define _THREAD_SIZE ", THREAD_SIZE);
|
||||||
constant("#define _THREAD_MASK ", THREAD_MASK);
|
constant("#define _THREAD_MASK ", THREAD_MASK);
|
||||||
|
|
|
@ -1468,3 +1468,30 @@ sysn32_rt_sigtimedwait(const sigset_t __user *uthese,
|
||||||
}
|
}
|
||||||
return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);
|
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, ®s, 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));
|
||||||
|
}
|
||||||
|
|
|
@ -89,6 +89,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
||||||
struct thread_info *ti = p->thread_info;
|
struct thread_info *ti = p->thread_info;
|
||||||
struct pt_regs *childregs;
|
struct pt_regs *childregs;
|
||||||
long childksp;
|
long childksp;
|
||||||
|
p->set_child_tid = p->clear_child_tid = NULL;
|
||||||
|
|
||||||
childksp = (unsigned long)ti + THREAD_SIZE - 32;
|
childksp = (unsigned long)ti + THREAD_SIZE - 32;
|
||||||
|
|
||||||
|
@ -134,6 +135,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
||||||
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
|
childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
|
||||||
clear_tsk_thread_flag(p, TIF_USEDFPU);
|
clear_tsk_thread_flag(p, TIF_USEDFPU);
|
||||||
|
|
||||||
|
if (clone_flags & CLONE_SETTLS)
|
||||||
|
ti->tp_value = regs->regs[7];
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -289,6 +289,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
|
||||||
ret = ptrace_detach(child, data);
|
ret = ptrace_detach(child, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PTRACE_GET_THREAD_AREA:
|
||||||
|
ret = put_user(child->thread_info->tp_value,
|
||||||
|
(unsigned long __user *) data);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = ptrace_request(child, request, addr, data);
|
ret = ptrace_request(child, request, addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -268,6 +268,11 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
|
||||||
wake_up_process(child);
|
wake_up_process(child);
|
||||||
break;
|
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. */
|
case PTRACE_DETACH: /* detach a process that was attached. */
|
||||||
ret = ptrace_detach(child, data);
|
ret = ptrace_detach(child, data);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -623,6 +623,7 @@ einval: li v0, -EINVAL
|
||||||
sys sys_add_key 5
|
sys sys_add_key 5
|
||||||
sys sys_request_key 4
|
sys sys_request_key 4
|
||||||
sys sys_keyctl 5
|
sys sys_keyctl 5
|
||||||
|
sys sys_set_thread_area 1
|
||||||
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
|
|
@ -449,3 +449,4 @@ sys_call_table:
|
||||||
PTR sys_add_key
|
PTR sys_add_key
|
||||||
PTR sys_request_key /* 5240 */
|
PTR sys_request_key /* 5240 */
|
||||||
PTR sys_keyctl
|
PTR sys_keyctl
|
||||||
|
PTR sys_set_thread_area
|
||||||
|
|
|
@ -363,3 +363,4 @@ EXPORT(sysn32_call_table)
|
||||||
PTR sys_add_key
|
PTR sys_add_key
|
||||||
PTR sys_request_key
|
PTR sys_request_key
|
||||||
PTR sys_keyctl /* 6245 */
|
PTR sys_keyctl /* 6245 */
|
||||||
|
PTR sys_set_thread_area
|
||||||
|
|
|
@ -322,7 +322,7 @@ sys_call_table:
|
||||||
PTR sys32_ipc
|
PTR sys32_ipc
|
||||||
PTR sys_fsync
|
PTR sys_fsync
|
||||||
PTR sys32_sigreturn
|
PTR sys32_sigreturn
|
||||||
PTR sys_clone /* 4120 */
|
PTR sys32_clone /* 4120 */
|
||||||
PTR sys_setdomainname
|
PTR sys_setdomainname
|
||||||
PTR sys32_newuname
|
PTR sys32_newuname
|
||||||
PTR sys_ni_syscall /* sys_modify_ldt */
|
PTR sys_ni_syscall /* sys_modify_ldt */
|
||||||
|
@ -485,4 +485,5 @@ sys_call_table:
|
||||||
PTR sys_add_key /* 4280 */
|
PTR sys_add_key /* 4280 */
|
||||||
PTR sys_request_key
|
PTR sys_request_key
|
||||||
PTR sys_keyctl
|
PTR sys_keyctl
|
||||||
|
PTR sys_set_thread_area
|
||||||
.size sys_call_table,.-sys_call_table
|
.size sys_call_table,.-sys_call_table
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
||||||
* Copyright (C) 2001 MIPS Technologies, Inc.
|
* Copyright (C) 2001 MIPS Technologies, Inc.
|
||||||
*/
|
*/
|
||||||
|
#include <linux/config.h>
|
||||||
#include <linux/a.out.h>
|
#include <linux/a.out.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
|
@ -176,14 +177,28 @@ _sys_clone(nabi_no_regargs struct pt_regs regs)
|
||||||
{
|
{
|
||||||
unsigned long clone_flags;
|
unsigned long clone_flags;
|
||||||
unsigned long newsp;
|
unsigned long newsp;
|
||||||
int *parent_tidptr, *child_tidptr;
|
int __user *parent_tidptr, *child_tidptr;
|
||||||
|
|
||||||
clone_flags = regs.regs[4];
|
clone_flags = regs.regs[4];
|
||||||
newsp = regs.regs[5];
|
newsp = regs.regs[5];
|
||||||
if (!newsp)
|
if (!newsp)
|
||||||
newsp = regs.regs[29];
|
newsp = regs.regs[29];
|
||||||
parent_tidptr = (int *) regs.regs[6];
|
parent_tidptr = (int __user *) regs.regs[6];
|
||||||
child_tidptr = (int *) regs.regs[7];
|
#ifdef CONFIG_32BIT
|
||||||
|
/* 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, ®s, 0,
|
return do_fork(clone_flags, newsp, ®s, 0,
|
||||||
parent_tidptr, child_tidptr);
|
parent_tidptr, child_tidptr);
|
||||||
}
|
}
|
||||||
|
@ -245,6 +260,16 @@ asmlinkage int sys_olduname(struct oldold_utsname * name)
|
||||||
return error;
|
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)
|
asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
|
||||||
{
|
{
|
||||||
int tmp, len;
|
int tmp, len;
|
||||||
|
|
|
@ -360,6 +360,10 @@ static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
|
||||||
#define OFFSET 0x0000ffff
|
#define OFFSET 0x0000ffff
|
||||||
#define LL 0xc0000000
|
#define LL 0xc0000000
|
||||||
#define SC 0xe0000000
|
#define SC 0xe0000000
|
||||||
|
#define SPEC3 0x7c000000
|
||||||
|
#define RD 0x0000f800
|
||||||
|
#define FUNC 0x0000003f
|
||||||
|
#define RDHWR 0x0000003b
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The ll_bit is cleared by r*_switch.S
|
* The ll_bit is cleared by r*_switch.S
|
||||||
|
@ -495,6 +499,37 @@ static inline int simulate_llsc(struct pt_regs *regs)
|
||||||
return -EFAULT; /* Strange things going on ... */
|
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)
|
asmlinkage void do_ov(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
|
@ -641,6 +676,9 @@ asmlinkage void do_ri(struct pt_regs *regs)
|
||||||
if (!simulate_llsc(regs))
|
if (!simulate_llsc(regs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!simulate_rdhwr(regs))
|
||||||
|
return;
|
||||||
|
|
||||||
force_sig(SIGILL, current);
|
force_sig(SIGILL, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,11 +692,13 @@ asmlinkage void do_cpu(struct pt_regs *regs)
|
||||||
|
|
||||||
switch (cpid) {
|
switch (cpid) {
|
||||||
case 0:
|
case 0:
|
||||||
if (cpu_has_llsc)
|
if (!cpu_has_llsc)
|
||||||
break;
|
if (!simulate_llsc(regs))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!simulate_llsc(regs))
|
if (!simulate_rdhwr(regs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -28,7 +28,7 @@ enum major_op {
|
||||||
sdl_op, sdr_op, swr_op, cache_op,
|
sdl_op, sdr_op, swr_op, cache_op,
|
||||||
ll_op, lwc1_op, lwc2_op, pref_op,
|
ll_op, lwc1_op, lwc2_op, pref_op,
|
||||||
lld_op, ldc1_op, ldc2_op, ld_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
|
scd_op, sdc1_op, sdc2_op, sd_op
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct thread_info {
|
||||||
struct task_struct *task; /* main task structure */
|
struct task_struct *task; /* main task structure */
|
||||||
struct exec_domain *exec_domain; /* execution domain */
|
struct exec_domain *exec_domain; /* execution domain */
|
||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
|
unsigned long tp_value; /* thread pointer */
|
||||||
__u32 cpu; /* current CPU */
|
__u32 cpu; /* current CPU */
|
||||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||||
|
|
||||||
|
|
|
@ -303,16 +303,17 @@
|
||||||
#define __NR_add_key (__NR_Linux + 280)
|
#define __NR_add_key (__NR_Linux + 280)
|
||||||
#define __NR_request_key (__NR_Linux + 281)
|
#define __NR_request_key (__NR_Linux + 281)
|
||||||
#define __NR_keyctl (__NR_Linux + 282)
|
#define __NR_keyctl (__NR_Linux + 282)
|
||||||
|
#define __NR_set_thread_area (__NR_Linux + 283)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offset of the last Linux o32 flavoured syscall
|
* Offset of the last Linux o32 flavoured syscall
|
||||||
*/
|
*/
|
||||||
#define __NR_Linux_syscalls 282
|
#define __NR_Linux_syscalls 283
|
||||||
|
|
||||||
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
|
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
|
||||||
|
|
||||||
#define __NR_O32_Linux 4000
|
#define __NR_O32_Linux 4000
|
||||||
#define __NR_O32_Linux_syscalls 282
|
#define __NR_O32_Linux_syscalls 283
|
||||||
|
|
||||||
#if _MIPS_SIM == _MIPS_SIM_ABI64
|
#if _MIPS_SIM == _MIPS_SIM_ABI64
|
||||||
|
|
||||||
|
@ -562,16 +563,17 @@
|
||||||
#define __NR_add_key (__NR_Linux + 239)
|
#define __NR_add_key (__NR_Linux + 239)
|
||||||
#define __NR_request_key (__NR_Linux + 240)
|
#define __NR_request_key (__NR_Linux + 240)
|
||||||
#define __NR_keyctl (__NR_Linux + 241)
|
#define __NR_keyctl (__NR_Linux + 241)
|
||||||
|
#define __NR_set_thread_area (__NR_Linux + 242)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offset of the last Linux 64-bit flavoured syscall
|
* 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 */
|
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
|
||||||
|
|
||||||
#define __NR_64_Linux 5000
|
#define __NR_64_Linux 5000
|
||||||
#define __NR_64_Linux_syscalls 241
|
#define __NR_64_Linux_syscalls 242
|
||||||
|
|
||||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||||
|
|
||||||
|
@ -825,16 +827,17 @@
|
||||||
#define __NR_add_key (__NR_Linux + 243)
|
#define __NR_add_key (__NR_Linux + 243)
|
||||||
#define __NR_request_key (__NR_Linux + 244)
|
#define __NR_request_key (__NR_Linux + 244)
|
||||||
#define __NR_keyctl (__NR_Linux + 245)
|
#define __NR_keyctl (__NR_Linux + 245)
|
||||||
|
#define __NR_set_thread_area (__NR_Linux + 246)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offset of the last N32 flavoured syscall
|
* Offset of the last N32 flavoured syscall
|
||||||
*/
|
*/
|
||||||
#define __NR_Linux_syscalls 245
|
#define __NR_Linux_syscalls 246
|
||||||
|
|
||||||
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
|
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
|
||||||
|
|
||||||
#define __NR_N32_Linux 6000
|
#define __NR_N32_Linux 6000
|
||||||
#define __NR_N32_Linux_syscalls 245
|
#define __NR_N32_Linux_syscalls 246
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue