aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2012-11-14 05:12:54 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2012-11-14 05:12:54 -0500
commit908816dfe6043a9e28df17066d117a5c7df2a75d (patch)
tree89057a9a89ce8d6557e5db17a317d14e3ebd274e /arch/arm64
parent938edf5c04202b59b8ff01a4033e9413646b105b (diff)
parent6097a07411005c0184cf90256743c784079198fc (diff)
Merge branch 'execve' into upstream
* execve: arm64: Use generic sys_execve() implementation arm64: Use generic kernel_execve() implementation arm64: Use generic kernel_thread() implementation
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/Kconfig2
-rw-r--r--arch/arm64/include/asm/processor.h5
-rw-r--r--arch/arm64/include/asm/syscalls.h3
-rw-r--r--arch/arm64/include/asm/unistd.h1
-rw-r--r--arch/arm64/include/asm/unistd32.h2
-rw-r--r--arch/arm64/kernel/entry.S12
-rw-r--r--arch/arm64/kernel/process.c77
-rw-r--r--arch/arm64/kernel/sys.c65
-rw-r--r--arch/arm64/kernel/sys32.S5
-rw-r--r--arch/arm64/kernel/sys_compat.c18
10 files changed, 33 insertions, 157 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 15ac18a56c93..20b688c81956 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -7,6 +7,8 @@ config ARM64
7 select GENERIC_IOMAP 7 select GENERIC_IOMAP
8 select GENERIC_IRQ_PROBE 8 select GENERIC_IRQ_PROBE
9 select GENERIC_IRQ_SHOW 9 select GENERIC_IRQ_SHOW
10 select GENERIC_KERNEL_EXECVE
11 select GENERIC_KERNEL_THREAD
10 select GENERIC_SMP_IDLE_THREAD 12 select GENERIC_SMP_IDLE_THREAD
11 select GENERIC_TIME_VSYSCALL 13 select GENERIC_TIME_VSYSCALL
12 select HARDIRQS_SW_RESEND 14 select HARDIRQS_SW_RESEND
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 77f696c14339..ab239b2c456f 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -128,11 +128,6 @@ unsigned long get_wchan(struct task_struct *p);
128extern struct task_struct *cpu_switch_to(struct task_struct *prev, 128extern struct task_struct *cpu_switch_to(struct task_struct *prev,
129 struct task_struct *next); 129 struct task_struct *next);
130 130
131/*
132 * Create a new kernel thread
133 */
134extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
135
136#define task_pt_regs(p) \ 131#define task_pt_regs(p) \
137 ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) 132 ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
138 133
diff --git a/arch/arm64/include/asm/syscalls.h b/arch/arm64/include/asm/syscalls.h
index 09ff33572aab..81680a0ae913 100644
--- a/arch/arm64/include/asm/syscalls.h
+++ b/arch/arm64/include/asm/syscalls.h
@@ -23,9 +23,6 @@
23/* 23/*
24 * System call wrappers implemented in kernel/entry.S. 24 * System call wrappers implemented in kernel/entry.S.
25 */ 25 */
26asmlinkage long sys_execve_wrapper(const char __user *filename,
27 const char __user *const __user *argv,
28 const char __user *const __user *envp);
29asmlinkage long sys_clone_wrapper(unsigned long clone_flags, 26asmlinkage long sys_clone_wrapper(unsigned long clone_flags,
30 unsigned long newsp, 27 unsigned long newsp,
31 void __user *parent_tid, 28 void __user *parent_tid,
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 68aff2816e86..43064a8bd99e 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -25,4 +25,5 @@
25#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 25#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
26#define __ARCH_WANT_COMPAT_SYS_SENDFILE 26#define __ARCH_WANT_COMPAT_SYS_SENDFILE
27#endif 27#endif
28#define __ARCH_WANT_SYS_EXECVE
28#include <uapi/asm/unistd.h> 29#include <uapi/asm/unistd.h>
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 6d909faebf28..9035e6add3e4 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -32,7 +32,7 @@ __SYSCALL(7, sys_ni_syscall) /* 7 was sys_waitpid */
32__SYSCALL(8, sys_creat) 32__SYSCALL(8, sys_creat)
33__SYSCALL(9, sys_link) 33__SYSCALL(9, sys_link)
34__SYSCALL(10, sys_unlink) 34__SYSCALL(10, sys_unlink)
35__SYSCALL(11, compat_sys_execve_wrapper) 35__SYSCALL(11, compat_sys_execve)
36__SYSCALL(12, sys_chdir) 36__SYSCALL(12, sys_chdir)
37__SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */ 37__SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */
38__SYSCALL(14, sys_mknod) 38__SYSCALL(14, sys_mknod)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index a6f3f7da6880..616531862d52 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -594,7 +594,7 @@ work_resched:
594/* 594/*
595 * "slow" syscall return path. 595 * "slow" syscall return path.
596 */ 596 */
597ENTRY(ret_to_user) 597ret_to_user:
598 disable_irq // disable interrupts 598 disable_irq // disable interrupts
599 ldr x1, [tsk, #TI_FLAGS] 599 ldr x1, [tsk, #TI_FLAGS]
600 and x2, x1, #_TIF_WORK_MASK 600 and x2, x1, #_TIF_WORK_MASK
@@ -611,7 +611,10 @@ ENDPROC(ret_to_user)
611 */ 611 */
612ENTRY(ret_from_fork) 612ENTRY(ret_from_fork)
613 bl schedule_tail 613 bl schedule_tail
614 get_thread_info tsk 614 cbz x19, 1f // not a kernel thread
615 mov x0, x20
616 blr x19
6171: get_thread_info tsk
615 b ret_to_user 618 b ret_to_user
616ENDPROC(ret_from_fork) 619ENDPROC(ret_from_fork)
617 620
@@ -673,11 +676,6 @@ __sys_trace_return:
673/* 676/*
674 * Special system call wrappers. 677 * Special system call wrappers.
675 */ 678 */
676ENTRY(sys_execve_wrapper)
677 mov x3, sp
678 b sys_execve
679ENDPROC(sys_execve_wrapper)
680
681ENTRY(sys_clone_wrapper) 679ENTRY(sys_clone_wrapper)
682 mov x5, sp 680 mov x5, sp
683 b sys_clone 681 b sys_clone
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index e04cebdbb47f..a430b5cad308 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -240,27 +240,35 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
240 struct pt_regs *childregs = task_pt_regs(p); 240 struct pt_regs *childregs = task_pt_regs(p);
241 unsigned long tls = p->thread.tp_value; 241 unsigned long tls = p->thread.tp_value;
242 242
243 *childregs = *regs; 243 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
244 childregs->regs[0] = 0;
245 244
246 if (is_compat_thread(task_thread_info(p))) 245 if (likely(regs)) {
247 childregs->compat_sp = stack_start; 246 *childregs = *regs;
248 else { 247 childregs->regs[0] = 0;
248 if (is_compat_thread(task_thread_info(p))) {
249 childregs->compat_sp = stack_start;
250 } else {
251 /*
252 * Read the current TLS pointer from tpidr_el0 as it may be
253 * out-of-sync with the saved value.
254 */
255 asm("mrs %0, tpidr_el0" : "=r" (tls));
256 childregs->sp = stack_start;
257 }
249 /* 258 /*
250 * Read the current TLS pointer from tpidr_el0 as it may be 259 * If a TLS pointer was passed to clone (4th argument), use it
251 * out-of-sync with the saved value. 260 * for the new thread.
252 */ 261 */
253 asm("mrs %0, tpidr_el0" : "=r" (tls)); 262 if (clone_flags & CLONE_SETTLS)
254 childregs->sp = stack_start; 263 tls = regs->regs[3];
264 } else {
265 memset(childregs, 0, sizeof(struct pt_regs));
266 childregs->pstate = PSR_MODE_EL1h;
267 p->thread.cpu_context.x19 = stack_start;
268 p->thread.cpu_context.x20 = stk_sz;
255 } 269 }
256
257 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
258 p->thread.cpu_context.sp = (unsigned long)childregs;
259 p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 270 p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
260 271 p->thread.cpu_context.sp = (unsigned long)childregs;
261 /* If a TLS pointer was passed to clone, use that for the new thread. */
262 if (clone_flags & CLONE_SETTLS)
263 tls = regs->regs[3];
264 p->thread.tp_value = tls; 272 p->thread.tp_value = tls;
265 273
266 ptrace_hw_copy_thread(p); 274 ptrace_hw_copy_thread(p);
@@ -309,43 +317,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
309 return last; 317 return last;
310} 318}
311 319
312/*
313 * Shuffle the argument into the correct register before calling the
314 * thread function. x1 is the thread argument, x2 is the pointer to
315 * the thread function, and x3 points to the exit function.
316 */
317extern void kernel_thread_helper(void);
318asm( ".section .text\n"
319" .align\n"
320" .type kernel_thread_helper, #function\n"
321"kernel_thread_helper:\n"
322" mov x0, x1\n"
323" mov x30, x3\n"
324" br x2\n"
325" .size kernel_thread_helper, . - kernel_thread_helper\n"
326" .previous");
327
328#define kernel_thread_exit do_exit
329
330/*
331 * Create a kernel thread.
332 */
333pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
334{
335 struct pt_regs regs;
336
337 memset(&regs, 0, sizeof(regs));
338
339 regs.regs[1] = (unsigned long)arg;
340 regs.regs[2] = (unsigned long)fn;
341 regs.regs[3] = (unsigned long)kernel_thread_exit;
342 regs.pc = (unsigned long)kernel_thread_helper;
343 regs.pstate = PSR_MODE_EL1h;
344
345 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
346}
347EXPORT_SYMBOL(kernel_thread);
348
349unsigned long get_wchan(struct task_struct *p) 320unsigned long get_wchan(struct task_struct *p)
350{ 321{
351 struct stackframe frame; 322 struct stackframe frame;
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
index b120df37de35..9c77c0bacc1d 100644
--- a/arch/arm64/kernel/sys.c
+++ b/arch/arm64/kernel/sys.c
@@ -41,70 +41,6 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
41 return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); 41 return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
42} 42}
43 43
44/*
45 * sys_execve() executes a new program.
46 */
47asmlinkage long sys_execve(const char __user *filenamei,
48 const char __user *const __user *argv,
49 const char __user *const __user *envp,
50 struct pt_regs *regs)
51{
52 long error;
53 struct filename *filename;
54
55 filename = getname(filenamei);
56 error = PTR_ERR(filename);
57 if (IS_ERR(filename))
58 goto out;
59 error = do_execve(filename->name, argv, envp, regs);
60 putname(filename);
61out:
62 return error;
63}
64
65int kernel_execve(const char *filename,
66 const char *const argv[],
67 const char *const envp[])
68{
69 struct pt_regs regs;
70 int ret;
71
72 memset(&regs, 0, sizeof(struct pt_regs));
73 ret = do_execve(filename,
74 (const char __user *const __user *)argv,
75 (const char __user *const __user *)envp, &regs);
76 if (ret < 0)
77 goto out;
78
79 /*
80 * Save argc to the register structure for userspace.
81 */
82 regs.regs[0] = ret;
83
84 /*
85 * We were successful. We won't be returning to our caller, but
86 * instead to user space by manipulating the kernel stack.
87 */
88 asm( "add x0, %0, %1\n\t"
89 "mov x1, %2\n\t"
90 "mov x2, %3\n\t"
91 "bl memmove\n\t" /* copy regs to top of stack */
92 "mov x27, #0\n\t" /* not a syscall */
93 "mov x28, %0\n\t" /* thread structure */
94 "mov sp, x0\n\t" /* reposition stack pointer */
95 "b ret_to_user"
96 :
97 : "r" (current_thread_info()),
98 "Ir" (THREAD_START_SP - sizeof(regs)),
99 "r" (&regs),
100 "Ir" (sizeof(regs))
101 : "x0", "x1", "x2", "x27", "x28", "x30", "memory");
102
103 out:
104 return ret;
105}
106EXPORT_SYMBOL(kernel_execve);
107
108asmlinkage long sys_mmap(unsigned long addr, unsigned long len, 44asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
109 unsigned long prot, unsigned long flags, 45 unsigned long prot, unsigned long flags,
110 unsigned long fd, off_t off) 46 unsigned long fd, off_t off)
@@ -118,7 +54,6 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
118/* 54/*
119 * Wrappers to pass the pt_regs argument. 55 * Wrappers to pass the pt_regs argument.
120 */ 56 */
121#define sys_execve sys_execve_wrapper
122#define sys_clone sys_clone_wrapper 57#define sys_clone sys_clone_wrapper
123#define sys_rt_sigreturn sys_rt_sigreturn_wrapper 58#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
124#define sys_sigaltstack sys_sigaltstack_wrapper 59#define sys_sigaltstack sys_sigaltstack_wrapper
diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S
index 54c4aec47a08..92145d402cf1 100644
--- a/arch/arm64/kernel/sys32.S
+++ b/arch/arm64/kernel/sys32.S
@@ -36,11 +36,6 @@ compat_sys_vfork_wrapper:
36 b compat_sys_vfork 36 b compat_sys_vfork
37ENDPROC(compat_sys_vfork_wrapper) 37ENDPROC(compat_sys_vfork_wrapper)
38 38
39compat_sys_execve_wrapper:
40 mov x3, sp
41 b compat_sys_execve
42ENDPROC(compat_sys_execve_wrapper)
43
44compat_sys_clone_wrapper: 39compat_sys_clone_wrapper:
45 mov x5, sp 40 mov x5, sp
46 b compat_sys_clone 41 b compat_sys_clone
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 906e3bd270b0..d140b73a8bc4 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -49,24 +49,6 @@ asmlinkage int compat_sys_vfork(struct pt_regs *regs)
49 regs, 0, NULL, NULL); 49 regs, 0, NULL, NULL);
50} 50}
51 51
52asmlinkage int compat_sys_execve(const char __user *filenamei,
53 compat_uptr_t argv, compat_uptr_t envp,
54 struct pt_regs *regs)
55{
56 int error;
57 struct filename *filename;
58
59 filename = getname(filenamei);
60 error = PTR_ERR(filename);
61 if (IS_ERR(filename))
62 goto out;
63 error = compat_do_execve(filename->name, compat_ptr(argv),
64 compat_ptr(envp), regs);
65 putname(filename);
66out:
67 return error;
68}
69
70asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, 52asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
71 struct compat_timespec __user *interval) 53 struct compat_timespec __user *interval)
72{ 54{