diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-11 21:49:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-11 21:49:08 -0400 |
commit | 8213a2f3eeafdecf06dd718cb4130372263f6067 (patch) | |
tree | 0d02e3201dac64d1429f8552ee1163d4a1ef1646 /arch/m68k | |
parent | 40924754f2cabd5d9af4bcd4dcecc362b5e0baa1 (diff) | |
parent | 12f79be93d94698778ff2b3f921073fc5f6780d6 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull pile 2 of execve and kernel_thread unification work from Al Viro:
"Stuff in there: kernel_thread/kernel_execve/sys_execve conversions for
several more architectures plus assorted signal fixes and cleanups.
There'll be more (in particular, real fixes for the alpha
do_notify_resume() irq mess)..."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (43 commits)
alpha: don't open-code trace_report_syscall_{enter,exit}
Uninclude linux/freezer.h
m32r: trim masks
avr32: trim masks
tile: don't bother with SIGTRAP in setup_frame
microblaze: don't bother with SIGTRAP in setup_rt_frame()
mn10300: don't bother with SIGTRAP in setup_frame()
frv: no need to raise SIGTRAP in setup_frame()
x86: get rid of duplicate code in case of CONFIG_VM86
unicore32: remove pointless test
h8300: trim _TIF_WORK_MASK
parisc: decide whether to go to slow path (tracesys) based on thread flags
parisc: don't bother looping in do_signal()
parisc: fix double restarts
bury the rest of TIF_IRET
sanitize tsk_is_polling()
bury _TIF_RESTORE_SIGMASK
unicore32: unobfuscate _TIF_WORK_MASK
mips: NOTIFY_RESUME is not needed in TIF masks
mips: merge the identical "return from syscall" per-ABI code
...
Conflicts:
arch/arm/include/asm/thread_info.h
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/Kconfig | 1 | ||||
-rw-r--r-- | arch/m68k/include/asm/processor.h | 25 | ||||
-rw-r--r-- | arch/m68k/include/asm/ptrace.h | 2 | ||||
-rw-r--r-- | arch/m68k/include/asm/unistd.h | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/entry.S | 16 | ||||
-rw-r--r-- | arch/m68k/kernel/process.c | 104 | ||||
-rw-r--r-- | arch/m68k/kernel/sys_m68k.c | 17 |
7 files changed, 57 insertions, 110 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index dae1e7e16a37..76fd6e2f71da 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -15,6 +15,7 @@ config M68K | |||
15 | select FPU if MMU | 15 | select FPU if MMU |
16 | select ARCH_WANT_IPC_PARSE_VERSION | 16 | select ARCH_WANT_IPC_PARSE_VERSION |
17 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE | 17 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE |
18 | select GENERIC_KERNEL_THREAD | ||
18 | 19 | ||
19 | config RWSEM_GENERIC_SPINLOCK | 20 | config RWSEM_GENERIC_SPINLOCK |
20 | bool | 21 | bool |
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h index f17c42aff7ff..ae700f49e51d 100644 --- a/arch/m68k/include/asm/processor.h +++ b/arch/m68k/include/asm/processor.h | |||
@@ -100,6 +100,16 @@ struct thread_struct { | |||
100 | .fs = __KERNEL_DS, \ | 100 | .fs = __KERNEL_DS, \ |
101 | } | 101 | } |
102 | 102 | ||
103 | /* | ||
104 | * ColdFire stack format sbould be 0x4 for an aligned usp (will always be | ||
105 | * true on thread creation). We need to set this explicitly. | ||
106 | */ | ||
107 | #ifdef CONFIG_COLDFIRE | ||
108 | #define setframeformat(_regs) do { (_regs)->format = 0x4; } while(0) | ||
109 | #else | ||
110 | #define setframeformat(_regs) do { } while (0) | ||
111 | #endif | ||
112 | |||
103 | #ifdef CONFIG_MMU | 113 | #ifdef CONFIG_MMU |
104 | /* | 114 | /* |
105 | * Do necessary setup to start up a newly executed thread. | 115 | * Do necessary setup to start up a newly executed thread. |
@@ -109,6 +119,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc, | |||
109 | { | 119 | { |
110 | regs->pc = pc; | 120 | regs->pc = pc; |
111 | regs->sr &= ~0x2000; | 121 | regs->sr &= ~0x2000; |
122 | setframeformat(regs); | ||
112 | wrusp(usp); | 123 | wrusp(usp); |
113 | } | 124 | } |
114 | 125 | ||
@@ -116,21 +127,11 @@ extern int handle_kernel_fault(struct pt_regs *regs); | |||
116 | 127 | ||
117 | #else | 128 | #else |
118 | 129 | ||
119 | /* | ||
120 | * Coldfire stacks need to be re-aligned on trap exit, conventional | ||
121 | * 68k can handle this case cleanly. | ||
122 | */ | ||
123 | #ifdef CONFIG_COLDFIRE | ||
124 | #define reformat(_regs) do { (_regs)->format = 0x4; } while(0) | ||
125 | #else | ||
126 | #define reformat(_regs) do { } while (0) | ||
127 | #endif | ||
128 | |||
129 | #define start_thread(_regs, _pc, _usp) \ | 130 | #define start_thread(_regs, _pc, _usp) \ |
130 | do { \ | 131 | do { \ |
131 | (_regs)->pc = (_pc); \ | 132 | (_regs)->pc = (_pc); \ |
132 | ((struct switch_stack *)(_regs))[-1].a6 = 0; \ | 133 | ((struct switch_stack *)(_regs))[-1].a6 = 0; \ |
133 | reformat(_regs); \ | 134 | setframeformat(_regs); \ |
134 | if (current->mm) \ | 135 | if (current->mm) \ |
135 | (_regs)->d5 = current->mm->start_data; \ | 136 | (_regs)->d5 = current->mm->start_data; \ |
136 | (_regs)->sr &= ~0x2000; \ | 137 | (_regs)->sr &= ~0x2000; \ |
@@ -153,8 +154,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
153 | { | 154 | { |
154 | } | 155 | } |
155 | 156 | ||
156 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
157 | |||
158 | /* | 157 | /* |
159 | * Free current thread data structures etc.. | 158 | * Free current thread data structures etc.. |
160 | */ | 159 | */ |
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h index 65322b17b6cf..5e08b597f012 100644 --- a/arch/m68k/include/asm/ptrace.h +++ b/arch/m68k/include/asm/ptrace.h | |||
@@ -85,6 +85,8 @@ struct switch_stack { | |||
85 | #define user_mode(regs) (!((regs)->sr & PS_S)) | 85 | #define user_mode(regs) (!((regs)->sr & PS_S)) |
86 | #define instruction_pointer(regs) ((regs)->pc) | 86 | #define instruction_pointer(regs) ((regs)->pc) |
87 | #define profile_pc(regs) instruction_pointer(regs) | 87 | #define profile_pc(regs) instruction_pointer(regs) |
88 | #define current_pt_regs() \ | ||
89 | (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1 | ||
88 | 90 | ||
89 | #define arch_has_single_step() (1) | 91 | #define arch_has_single_step() (1) |
90 | 92 | ||
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 045cfd6a9e31..c702ad716791 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h | |||
@@ -382,6 +382,8 @@ | |||
382 | #define __ARCH_WANT_SYS_SIGPROCMASK | 382 | #define __ARCH_WANT_SYS_SIGPROCMASK |
383 | #define __ARCH_WANT_SYS_RT_SIGACTION | 383 | #define __ARCH_WANT_SYS_RT_SIGACTION |
384 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 384 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
385 | #define __ARCH_WANT_SYS_EXECVE | ||
386 | #define __ARCH_WANT_KERNEL_EXECVE | ||
385 | 387 | ||
386 | /* | 388 | /* |
387 | * "Conditional" syscalls | 389 | * "Conditional" syscalls |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 165ee9f9d5c9..946cb0187751 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -111,6 +111,22 @@ ENTRY(ret_from_fork) | |||
111 | addql #4,%sp | 111 | addql #4,%sp |
112 | jra ret_from_exception | 112 | jra ret_from_exception |
113 | 113 | ||
114 | ENTRY(ret_from_kernel_thread) | ||
115 | | a3 contains the kernel thread payload, d7 - its argument | ||
116 | movel %d1,%sp@- | ||
117 | jsr schedule_tail | ||
118 | GET_CURRENT(%d0) | ||
119 | movel %d7,(%sp) | ||
120 | jsr %a3@ | ||
121 | addql #4,%sp | ||
122 | movel %d0,(%sp) | ||
123 | jra sys_exit | ||
124 | |||
125 | ENTRY(ret_from_kernel_execve) | ||
126 | movel 4(%sp), %sp | ||
127 | GET_CURRENT(%d0) | ||
128 | jra ret_from_exception | ||
129 | |||
114 | #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) | 130 | #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) |
115 | 131 | ||
116 | #ifdef TRAP_DBG_INTERRUPT | 132 | #ifdef TRAP_DBG_INTERRUPT |
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index ac2892e49c7c..c51bb172e14d 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | 36 | ||
37 | asmlinkage void ret_from_fork(void); | 37 | asmlinkage void ret_from_fork(void); |
38 | asmlinkage void ret_from_kernel_thread(void); | ||
38 | 39 | ||
39 | 40 | ||
40 | /* | 41 | /* |
@@ -123,51 +124,6 @@ void show_regs(struct pt_regs * regs) | |||
123 | printk("USP: %08lx\n", rdusp()); | 124 | printk("USP: %08lx\n", rdusp()); |
124 | } | 125 | } |
125 | 126 | ||
126 | /* | ||
127 | * Create a kernel thread | ||
128 | */ | ||
129 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
130 | { | ||
131 | int pid; | ||
132 | mm_segment_t fs; | ||
133 | |||
134 | fs = get_fs(); | ||
135 | set_fs (KERNEL_DS); | ||
136 | |||
137 | { | ||
138 | register long retval __asm__ ("d0"); | ||
139 | register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; | ||
140 | |||
141 | retval = __NR_clone; | ||
142 | __asm__ __volatile__ | ||
143 | ("clrl %%d2\n\t" | ||
144 | "trap #0\n\t" /* Linux/m68k system call */ | ||
145 | "tstl %0\n\t" /* child or parent */ | ||
146 | "jne 1f\n\t" /* parent - jump */ | ||
147 | #ifdef CONFIG_MMU | ||
148 | "lea %%sp@(%c7),%6\n\t" /* reload current */ | ||
149 | "movel %6@,%6\n\t" | ||
150 | #endif | ||
151 | "movel %3,%%sp@-\n\t" /* push argument */ | ||
152 | "jsr %4@\n\t" /* call fn */ | ||
153 | "movel %0,%%d1\n\t" /* pass exit value */ | ||
154 | "movel %2,%%d0\n\t" /* exit */ | ||
155 | "trap #0\n" | ||
156 | "1:" | ||
157 | : "+d" (retval) | ||
158 | : "i" (__NR_clone), "i" (__NR_exit), | ||
159 | "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), | ||
160 | "i" (-THREAD_SIZE) | ||
161 | : "d2"); | ||
162 | |||
163 | pid = retval; | ||
164 | } | ||
165 | |||
166 | set_fs (fs); | ||
167 | return pid; | ||
168 | } | ||
169 | EXPORT_SYMBOL(kernel_thread); | ||
170 | |||
171 | void flush_thread(void) | 127 | void flush_thread(void) |
172 | { | 128 | { |
173 | current->thread.fs = __USER_DS; | 129 | current->thread.fs = __USER_DS; |
@@ -219,30 +175,18 @@ asmlinkage int m68k_clone(struct pt_regs *regs) | |||
219 | } | 175 | } |
220 | 176 | ||
221 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 177 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
222 | unsigned long unused, | 178 | unsigned long arg, |
223 | struct task_struct * p, struct pt_regs * regs) | 179 | struct task_struct * p, struct pt_regs * regs) |
224 | { | 180 | { |
225 | struct pt_regs * childregs; | 181 | struct pt_regs * childregs; |
226 | struct switch_stack * childstack, *stack; | 182 | struct switch_stack *childstack; |
227 | unsigned long *retp; | ||
228 | 183 | ||
229 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | 184 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; |
230 | |||
231 | *childregs = *regs; | ||
232 | childregs->d0 = 0; | ||
233 | |||
234 | retp = ((unsigned long *) regs); | ||
235 | stack = ((struct switch_stack *) retp) - 1; | ||
236 | |||
237 | childstack = ((struct switch_stack *) childregs) - 1; | 185 | childstack = ((struct switch_stack *) childregs) - 1; |
238 | *childstack = *stack; | ||
239 | childstack->retpc = (unsigned long)ret_from_fork; | ||
240 | 186 | ||
241 | p->thread.usp = usp; | 187 | p->thread.usp = usp; |
242 | p->thread.ksp = (unsigned long)childstack; | 188 | p->thread.ksp = (unsigned long)childstack; |
243 | 189 | p->thread.esp0 = (unsigned long)childregs; | |
244 | if (clone_flags & CLONE_SETTLS) | ||
245 | task_thread_info(p)->tp_value = regs->d5; | ||
246 | 190 | ||
247 | /* | 191 | /* |
248 | * Must save the current SFC/DFC value, NOT the value when | 192 | * Must save the current SFC/DFC value, NOT the value when |
@@ -250,6 +194,26 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
250 | */ | 194 | */ |
251 | p->thread.fs = get_fs().seg; | 195 | p->thread.fs = get_fs().seg; |
252 | 196 | ||
197 | if (unlikely(!regs)) { | ||
198 | /* kernel thread */ | ||
199 | memset(childstack, 0, | ||
200 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); | ||
201 | childregs->sr = PS_S; | ||
202 | childstack->a3 = usp; /* function */ | ||
203 | childstack->d7 = arg; | ||
204 | childstack->retpc = (unsigned long)ret_from_kernel_thread; | ||
205 | p->thread.usp = 0; | ||
206 | return 0; | ||
207 | } | ||
208 | *childregs = *regs; | ||
209 | childregs->d0 = 0; | ||
210 | |||
211 | *childstack = ((struct switch_stack *) regs)[-1]; | ||
212 | childstack->retpc = (unsigned long)ret_from_fork; | ||
213 | |||
214 | if (clone_flags & CLONE_SETTLS) | ||
215 | task_thread_info(p)->tp_value = regs->d5; | ||
216 | |||
253 | #ifdef CONFIG_FPU | 217 | #ifdef CONFIG_FPU |
254 | if (!FPU_IS_EMU) { | 218 | if (!FPU_IS_EMU) { |
255 | /* Copy the current fpu state */ | 219 | /* Copy the current fpu state */ |
@@ -337,26 +301,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) | |||
337 | EXPORT_SYMBOL(dump_fpu); | 301 | EXPORT_SYMBOL(dump_fpu); |
338 | #endif /* CONFIG_FPU */ | 302 | #endif /* CONFIG_FPU */ |
339 | 303 | ||
340 | /* | ||
341 | * sys_execve() executes a new program. | ||
342 | */ | ||
343 | asmlinkage int sys_execve(const char __user *name, | ||
344 | const char __user *const __user *argv, | ||
345 | const char __user *const __user *envp) | ||
346 | { | ||
347 | int error; | ||
348 | char * filename; | ||
349 | struct pt_regs *regs = (struct pt_regs *) &name; | ||
350 | |||
351 | filename = getname(name); | ||
352 | error = PTR_ERR(filename); | ||
353 | if (IS_ERR(filename)) | ||
354 | return error; | ||
355 | error = do_execve(filename, argv, envp, regs); | ||
356 | putname(filename); | ||
357 | return error; | ||
358 | } | ||
359 | |||
360 | unsigned long get_wchan(struct task_struct *p) | 304 | unsigned long get_wchan(struct task_struct *p) |
361 | { | 305 | { |
362 | unsigned long fp, pc; | 306 | unsigned long fp, pc; |
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 9a5932ec3689..3a480b3df0d6 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c | |||
@@ -549,23 +549,6 @@ asmlinkage int sys_getpagesize(void) | |||
549 | return PAGE_SIZE; | 549 | return PAGE_SIZE; |
550 | } | 550 | } |
551 | 551 | ||
552 | /* | ||
553 | * Do a system call from kernel instead of calling sys_execve so we | ||
554 | * end up with proper pt_regs. | ||
555 | */ | ||
556 | int kernel_execve(const char *filename, | ||
557 | const char *const argv[], | ||
558 | const char *const envp[]) | ||
559 | { | ||
560 | register long __res asm ("%d0") = __NR_execve; | ||
561 | register long __a asm ("%d1") = (long)(filename); | ||
562 | register long __b asm ("%d2") = (long)(argv); | ||
563 | register long __c asm ("%d3") = (long)(envp); | ||
564 | asm volatile ("trap #0" : "+d" (__res) | ||
565 | : "d" (__a), "d" (__b), "d" (__c)); | ||
566 | return __res; | ||
567 | } | ||
568 | |||
569 | asmlinkage unsigned long sys_get_thread_area(void) | 552 | asmlinkage unsigned long sys_get_thread_area(void) |
570 | { | 553 | { |
571 | return current_thread_info()->tp_value; | 554 | return current_thread_info()->tp_value; |