aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7720.c6
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7757.c6
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7763.c6
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7786.c6
-rw-r--r--arch/sh/kernel/cpu/sh5/entry.S19
-rw-r--r--arch/sh/kernel/entry-common.S13
-rw-r--r--arch/sh/kernel/process_32.c134
-rw-r--r--arch/sh/kernel/process_64.c127
-rw-r--r--arch/sh/kernel/signal_64.c6
-rw-r--r--arch/sh/kernel/sys_sh32.c24
-rw-r--r--arch/sh/kernel/sys_sh64.c50
12 files changed, 95 insertions, 305 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 88571ff8eeec..f259b37874e9 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -16,7 +16,7 @@ obj-y := debugtraps.o dma-nommu.o dumpstack.o \
16 machvec.o nmi_debug.o process.o \ 16 machvec.o nmi_debug.o process.o \
17 process_$(BITS).o ptrace.o ptrace_$(BITS).o \ 17 process_$(BITS).o ptrace.o ptrace_$(BITS).o \
18 reboot.o return_address.o \ 18 reboot.o return_address.o \
19 setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ 19 setup.o signal_$(BITS).o sys_sh.o \
20 syscalls_$(BITS).o time.o topology.o traps.o \ 20 syscalls_$(BITS).o time.o topology.o traps.o \
21 traps_$(BITS).o unwinder.o 21 traps_$(BITS).o unwinder.o
22 22
@@ -25,6 +25,7 @@ obj-y += iomap.o
25obj-$(CONFIG_HAS_IOPORT) += ioport.o 25obj-$(CONFIG_HAS_IOPORT) += ioport.o
26endif 26endif
27 27
28obj-$(CONFIG_SUPERH32) += sys_sh32.o
28obj-y += cpu/ 29obj-y += cpu/
29obj-$(CONFIG_VSYSCALL) += vsyscall/ 30obj-$(CONFIG_VSYSCALL) += vsyscall/
30obj-$(CONFIG_SMP) += smp.o 31obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index 0c2f1b2c2e19..42d991f632b1 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -20,6 +20,7 @@
20#include <linux/serial_sci.h> 20#include <linux/serial_sci.h>
21#include <linux/sh_timer.h> 21#include <linux/sh_timer.h>
22#include <linux/sh_intc.h> 22#include <linux/sh_intc.h>
23#include <linux/usb/ohci_pdriver.h>
23#include <asm/rtc.h> 24#include <asm/rtc.h>
24#include <cpu/serial.h> 25#include <cpu/serial.h>
25 26
@@ -103,12 +104,15 @@ static struct resource usb_ohci_resources[] = {
103 104
104static u64 usb_ohci_dma_mask = 0xffffffffUL; 105static u64 usb_ohci_dma_mask = 0xffffffffUL;
105 106
107static struct usb_ohci_pdata usb_ohci_pdata;
108
106static struct platform_device usb_ohci_device = { 109static struct platform_device usb_ohci_device = {
107 .name = "sh_ohci", 110 .name = "ohci-platform",
108 .id = -1, 111 .id = -1,
109 .dev = { 112 .dev = {
110 .dma_mask = &usb_ohci_dma_mask, 113 .dma_mask = &usb_ohci_dma_mask,
111 .coherent_dma_mask = 0xffffffff, 114 .coherent_dma_mask = 0xffffffff,
115 .platform_data = &usb_ohci_pdata,
112 }, 116 },
113 .num_resources = ARRAY_SIZE(usb_ohci_resources), 117 .num_resources = ARRAY_SIZE(usb_ohci_resources),
114 .resource = usb_ohci_resources, 118 .resource = usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index 4a2f357f4df8..9079a0f9ea9b 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -19,6 +19,7 @@
19#include <linux/sh_timer.h> 19#include <linux/sh_timer.h>
20#include <linux/sh_dma.h> 20#include <linux/sh_dma.h>
21#include <linux/sh_intc.h> 21#include <linux/sh_intc.h>
22#include <linux/usb/ohci_pdriver.h>
22#include <cpu/dma-register.h> 23#include <cpu/dma-register.h>
23#include <cpu/sh7757.h> 24#include <cpu/sh7757.h>
24 25
@@ -750,12 +751,15 @@ static struct resource usb_ohci_resources[] = {
750 }, 751 },
751}; 752};
752 753
754static struct usb_ohci_pdata usb_ohci_pdata;
755
753static struct platform_device usb_ohci_device = { 756static struct platform_device usb_ohci_device = {
754 .name = "sh_ohci", 757 .name = "ohci-platform",
755 .id = -1, 758 .id = -1,
756 .dev = { 759 .dev = {
757 .dma_mask = &usb_ohci_device.dev.coherent_dma_mask, 760 .dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
758 .coherent_dma_mask = DMA_BIT_MASK(32), 761 .coherent_dma_mask = DMA_BIT_MASK(32),
762 .platform_data = &usb_ohci_pdata,
759 }, 763 },
760 .num_resources = ARRAY_SIZE(usb_ohci_resources), 764 .num_resources = ARRAY_SIZE(usb_ohci_resources),
761 .resource = usb_ohci_resources, 765 .resource = usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index bd0a8fbe610f..1686acaaf45a 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -16,6 +16,7 @@
16#include <linux/sh_intc.h> 16#include <linux/sh_intc.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/serial_sci.h> 18#include <linux/serial_sci.h>
19#include <linux/usb/ohci_pdriver.h>
19 20
20static struct plat_sci_port scif0_platform_data = { 21static struct plat_sci_port scif0_platform_data = {
21 .mapbase = 0xffe00000, 22 .mapbase = 0xffe00000,
@@ -106,12 +107,15 @@ static struct resource usb_ohci_resources[] = {
106 107
107static u64 usb_ohci_dma_mask = 0xffffffffUL; 108static u64 usb_ohci_dma_mask = 0xffffffffUL;
108 109
110static struct usb_ohci_pdata usb_ohci_pdata;
111
109static struct platform_device usb_ohci_device = { 112static struct platform_device usb_ohci_device = {
110 .name = "sh_ohci", 113 .name = "ohci-platform",
111 .id = -1, 114 .id = -1,
112 .dev = { 115 .dev = {
113 .dma_mask = &usb_ohci_dma_mask, 116 .dma_mask = &usb_ohci_dma_mask,
114 .coherent_dma_mask = 0xffffffff, 117 .coherent_dma_mask = 0xffffffff,
118 .platform_data = &usb_ohci_pdata,
115 }, 119 },
116 .num_resources = ARRAY_SIZE(usb_ohci_resources), 120 .num_resources = ARRAY_SIZE(usb_ohci_resources),
117 .resource = usb_ohci_resources, 121 .resource = usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index 2e6952f87848..ab52d4d4484d 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -23,6 +23,7 @@
23#include <linux/sh_timer.h> 23#include <linux/sh_timer.h>
24#include <linux/sh_dma.h> 24#include <linux/sh_dma.h>
25#include <linux/sh_intc.h> 25#include <linux/sh_intc.h>
26#include <linux/usb/ohci_pdriver.h>
26#include <cpu/dma-register.h> 27#include <cpu/dma-register.h>
27#include <asm/mmzone.h> 28#include <asm/mmzone.h>
28 29
@@ -583,12 +584,15 @@ static struct resource usb_ohci_resources[] = {
583 }, 584 },
584}; 585};
585 586
587static struct usb_ohci_pdata usb_ohci_pdata;
588
586static struct platform_device usb_ohci_device = { 589static struct platform_device usb_ohci_device = {
587 .name = "sh_ohci", 590 .name = "ohci-platform",
588 .id = -1, 591 .id = -1,
589 .dev = { 592 .dev = {
590 .dma_mask = &usb_ohci_device.dev.coherent_dma_mask, 593 .dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
591 .coherent_dma_mask = DMA_BIT_MASK(32), 594 .coherent_dma_mask = DMA_BIT_MASK(32),
595 .platform_data = &usb_ohci_pdata,
592 }, 596 },
593 .num_resources = ARRAY_SIZE(usb_ohci_resources), 597 .num_resources = ARRAY_SIZE(usb_ohci_resources),
594 .resource = usb_ohci_resources, 598 .resource = usb_ohci_resources,
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index 7e605b95592a..0c8d0377d40b 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -1228,6 +1228,25 @@ ret_from_fork:
1228 pta ret_from_syscall, tr0 1228 pta ret_from_syscall, tr0
1229 blink tr0, ZERO 1229 blink tr0, ZERO
1230 1230
1231.global ret_from_kernel_thread
1232ret_from_kernel_thread:
1233
1234 movi schedule_tail,r5
1235 ori r5, 1, r5
1236 ptabs r5, tr0
1237 blink tr0, LINK
1238
1239 ld.q SP, FRAME_R(2), r2
1240 ld.q SP, FRAME_R(3), r3
1241 ptabs r3, tr0
1242 blink tr0, LINK
1243
1244 ld.q SP, FRAME_S(FSPC), r2
1245 addi r2, 4, r2 /* Move PC, being pre-execution event */
1246 st.q SP, FRAME_S(FSPC), r2
1247 pta ret_from_syscall, tr0
1248 blink tr0, ZERO
1249
1231syscall_allowed: 1250syscall_allowed:
1232 /* Use LINK to deflect the exit point, default is syscall_ret */ 1251 /* Use LINK to deflect the exit point, default is syscall_ret */
1233 pta syscall_ret, tr0 1252 pta syscall_ret, tr0
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index b96489d8b27d..9b6e4beeb296 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -297,6 +297,19 @@ ret_from_fork:
297 mov r0, r4 297 mov r0, r4
298 bra syscall_exit 298 bra syscall_exit
299 nop 299 nop
300
301 .align 2
302 .globl ret_from_kernel_thread
303ret_from_kernel_thread:
304 mov.l 1f, r8
305 jsr @r8
306 mov r0, r4
307 mov.l @(OFF_R5,r15), r5 ! fn
308 jsr @r5
309 mov.l @(OFF_R4,r15), r4 ! arg
310 bra syscall_exit
311 nop
312
300 .align 2 313 .align 2
3011: .long schedule_tail 3141: .long schedule_tail
302 315
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index ba7345f37bc9..73eb66fc6253 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -68,38 +68,6 @@ void show_regs(struct pt_regs * regs)
68 show_code(regs); 68 show_code(regs);
69} 69}
70 70
71/*
72 * Create a kernel thread
73 */
74__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))
75{
76 do_exit(fn(arg));
77}
78
79/* Don't use this in BL=1(cli). Or else, CPU resets! */
80int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
81{
82 struct pt_regs regs;
83 int pid;
84
85 memset(&regs, 0, sizeof(regs));
86 regs.regs[4] = (unsigned long)arg;
87 regs.regs[5] = (unsigned long)fn;
88
89 regs.pc = (unsigned long)kernel_thread_helper;
90 regs.sr = SR_MD;
91#if defined(CONFIG_SH_FPU)
92 regs.sr |= SR_FD;
93#endif
94
95 /* Ok, create the new process.. */
96 pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
97 &regs, 0, NULL, NULL);
98
99 return pid;
100}
101EXPORT_SYMBOL(kernel_thread);
102
103void start_thread(struct pt_regs *regs, unsigned long new_pc, 71void start_thread(struct pt_regs *regs, unsigned long new_pc,
104 unsigned long new_sp) 72 unsigned long new_sp)
105{ 73{
@@ -157,10 +125,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
157EXPORT_SYMBOL(dump_fpu); 125EXPORT_SYMBOL(dump_fpu);
158 126
159asmlinkage void ret_from_fork(void); 127asmlinkage void ret_from_fork(void);
128asmlinkage void ret_from_kernel_thread(void);
160 129
161int copy_thread(unsigned long clone_flags, unsigned long usp, 130int copy_thread(unsigned long clone_flags, unsigned long usp,
162 unsigned long unused, 131 unsigned long arg, struct task_struct *p)
163 struct task_struct *p, struct pt_regs *regs)
164{ 132{
165 struct thread_info *ti = task_thread_info(p); 133 struct thread_info *ti = task_thread_info(p);
166 struct pt_regs *childregs; 134 struct pt_regs *childregs;
@@ -177,29 +145,35 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
177 } 145 }
178#endif 146#endif
179 147
180 childregs = task_pt_regs(p); 148 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
181 *childregs = *regs;
182 149
183 if (user_mode(regs)) { 150 childregs = task_pt_regs(p);
184 childregs->regs[15] = usp; 151 p->thread.sp = (unsigned long) childregs;
185 ti->addr_limit = USER_DS; 152 if (unlikely(p->flags & PF_KTHREAD)) {
186 } else { 153 memset(childregs, 0, sizeof(struct pt_regs));
187 childregs->regs[15] = (unsigned long)childregs; 154 p->thread.pc = (unsigned long) ret_from_kernel_thread;
155 childregs->regs[4] = arg;
156 childregs->regs[5] = usp;
157 childregs->sr = SR_MD;
158#if defined(CONFIG_SH_FPU)
159 childregs->sr |= SR_FD;
160#endif
188 ti->addr_limit = KERNEL_DS; 161 ti->addr_limit = KERNEL_DS;
189 ti->status &= ~TS_USEDFPU; 162 ti->status &= ~TS_USEDFPU;
190 p->fpu_counter = 0; 163 p->fpu_counter = 0;
164 return 0;
191 } 165 }
166 *childregs = *current_pt_regs();
167
168 if (usp)
169 childregs->regs[15] = usp;
170 ti->addr_limit = USER_DS;
192 171
193 if (clone_flags & CLONE_SETTLS) 172 if (clone_flags & CLONE_SETTLS)
194 childregs->gbr = childregs->regs[0]; 173 childregs->gbr = childregs->regs[0];
195 174
196 childregs->regs[0] = 0; /* Set return value for child */ 175 childregs->regs[0] = 0; /* Set return value for child */
197
198 p->thread.sp = (unsigned long) childregs;
199 p->thread.pc = (unsigned long) ret_from_fork; 176 p->thread.pc = (unsigned long) ret_from_fork;
200
201 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
202
203 return 0; 177 return 0;
204} 178}
205 179
@@ -243,74 +217,6 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
243 return prev; 217 return prev;
244} 218}
245 219
246asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
247 unsigned long r6, unsigned long r7,
248 struct pt_regs __regs)
249{
250#ifdef CONFIG_MMU
251 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
252 return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
253#else
254 /* fork almost works, enough to trick you into looking elsewhere :-( */
255 return -EINVAL;
256#endif
257}
258
259asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
260 unsigned long parent_tidptr,
261 unsigned long child_tidptr,
262 struct pt_regs __regs)
263{
264 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
265 if (!newsp)
266 newsp = regs->regs[15];
267 return do_fork(clone_flags, newsp, regs, 0,
268 (int __user *)parent_tidptr,
269 (int __user *)child_tidptr);
270}
271
272/*
273 * This is trivial, and on the face of it looks like it
274 * could equally well be done in user mode.
275 *
276 * Not so, for quite unobvious reasons - register pressure.
277 * In user mode vfork() cannot have a stack frame, and if
278 * done by calling the "clone()" system call directly, you
279 * do not have enough call-clobbered registers to hold all
280 * the information you need.
281 */
282asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
283 unsigned long r6, unsigned long r7,
284 struct pt_regs __regs)
285{
286 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
287 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
288 0, NULL, NULL);
289}
290
291/*
292 * sys_execve() executes a new program.
293 */
294asmlinkage int sys_execve(const char __user *ufilename,
295 const char __user *const __user *uargv,
296 const char __user *const __user *uenvp,
297 unsigned long r7, struct pt_regs __regs)
298{
299 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
300 int error;
301 struct filename *filename;
302
303 filename = getname(ufilename);
304 error = PTR_ERR(filename);
305 if (IS_ERR(filename))
306 goto out;
307
308 error = do_execve(filename->name, uargv, uenvp, regs);
309 putname(filename);
310out:
311 return error;
312}
313
314unsigned long get_wchan(struct task_struct *p) 220unsigned long get_wchan(struct task_struct *p)
315{ 221{
316 unsigned long pc; 222 unsigned long pc;
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index 98a709f0c3c4..e611c85144b1 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -285,39 +285,6 @@ void show_regs(struct pt_regs *regs)
285} 285}
286 286
287/* 287/*
288 * Create a kernel thread
289 */
290__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))
291{
292 do_exit(fn(arg));
293}
294
295/*
296 * This is the mechanism for creating a new kernel thread.
297 *
298 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
299 * who haven't done an "execve()") should use this: it will work within
300 * a system call from a "real" process, but the process memory space will
301 * not be freed until both the parent and the child have exited.
302 */
303int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
304{
305 struct pt_regs regs;
306
307 memset(&regs, 0, sizeof(regs));
308 regs.regs[2] = (unsigned long)arg;
309 regs.regs[3] = (unsigned long)fn;
310
311 regs.pc = (unsigned long)kernel_thread_helper;
312 regs.sr = (1 << 30);
313
314 /* Ok, create the new process.. */
315 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
316 &regs, 0, NULL, NULL);
317}
318EXPORT_SYMBOL(kernel_thread);
319
320/*
321 * Free current thread data structures etc.. 288 * Free current thread data structures etc..
322 */ 289 */
323void exit_thread(void) 290void exit_thread(void)
@@ -401,26 +368,37 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
401EXPORT_SYMBOL(dump_fpu); 368EXPORT_SYMBOL(dump_fpu);
402 369
403asmlinkage void ret_from_fork(void); 370asmlinkage void ret_from_fork(void);
371asmlinkage void ret_from_kernel_thread(void);
404 372
405int copy_thread(unsigned long clone_flags, unsigned long usp, 373int copy_thread(unsigned long clone_flags, unsigned long usp,
406 unsigned long unused, 374 unsigned long arg, struct task_struct *p)
407 struct task_struct *p, struct pt_regs *regs)
408{ 375{
409 struct pt_regs *childregs; 376 struct pt_regs *childregs, *regs = current_pt_regs();
410 377
411#ifdef CONFIG_SH_FPU 378#ifdef CONFIG_SH_FPU
412 if(last_task_used_math == current) { 379 /* can't happen for a kernel thread */
380 if (last_task_used_math == current) {
413 enable_fpu(); 381 enable_fpu();
414 save_fpu(current); 382 save_fpu(current);
415 disable_fpu(); 383 disable_fpu();
416 last_task_used_math = NULL; 384 last_task_used_math = NULL;
417 regs->sr |= SR_FD; 385 current_pt_regs()->sr |= SR_FD;
418 } 386 }
419#endif 387#endif
420 /* Copy from sh version */ 388 /* Copy from sh version */
421 childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; 389 childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1;
390 p->thread.sp = (unsigned long) childregs;
422 391
423 *childregs = *regs; 392 if (unlikely(p->flags & PF_KTHREAD)) {
393 memset(childregs, 0, sizeof(struct pt_regs));
394 childregs->regs[2] = (unsigned long)arg;
395 childregs->regs[3] = (unsigned long)fn;
396 childregs->sr = (1 << 30); /* not user_mode */
397 childregs->sr |= SR_FD; /* Invalidate FPU flag */
398 p->thread.pc = (unsigned long) ret_from_kernel_thread;
399 return 0;
400 }
401 *childregs = *current_pt_regs();
424 402
425 /* 403 /*
426 * Sign extend the edited stack. 404 * Sign extend the edited stack.
@@ -428,85 +406,18 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
428 * 32-bit wide and context switch must take care 406 * 32-bit wide and context switch must take care
429 * of NEFF sign extension. 407 * of NEFF sign extension.
430 */ 408 */
431 if (user_mode(regs)) { 409 if (usp)
432 childregs->regs[15] = neff_sign_extend(usp); 410 childregs->regs[15] = neff_sign_extend(usp);
433 p->thread.uregs = childregs; 411 p->thread.uregs = childregs;
434 } else {
435 childregs->regs[15] =
436 neff_sign_extend((unsigned long)task_stack_page(p) +
437 THREAD_SIZE);
438 }
439 412
440 childregs->regs[9] = 0; /* Set return value for child */ 413 childregs->regs[9] = 0; /* Set return value for child */
441 childregs->sr |= SR_FD; /* Invalidate FPU flag */ 414 childregs->sr |= SR_FD; /* Invalidate FPU flag */
442 415
443 p->thread.sp = (unsigned long) childregs;
444 p->thread.pc = (unsigned long) ret_from_fork; 416 p->thread.pc = (unsigned long) ret_from_fork;
445 417
446 return 0; 418 return 0;
447} 419}
448 420
449asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
450 unsigned long r4, unsigned long r5,
451 unsigned long r6, unsigned long r7,
452 struct pt_regs *pregs)
453{
454 return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
455}
456
457asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
458 unsigned long r4, unsigned long r5,
459 unsigned long r6, unsigned long r7,
460 struct pt_regs *pregs)
461{
462 if (!newsp)
463 newsp = pregs->regs[15];
464 return do_fork(clone_flags, newsp, pregs, 0, 0, 0);
465}
466
467/*
468 * This is trivial, and on the face of it looks like it
469 * could equally well be done in user mode.
470 *
471 * Not so, for quite unobvious reasons - register pressure.
472 * In user mode vfork() cannot have a stack frame, and if
473 * done by calling the "clone()" system call directly, you
474 * do not have enough call-clobbered registers to hold all
475 * the information you need.
476 */
477asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
478 unsigned long r4, unsigned long r5,
479 unsigned long r6, unsigned long r7,
480 struct pt_regs *pregs)
481{
482 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);
483}
484
485/*
486 * sys_execve() executes a new program.
487 */
488asmlinkage int sys_execve(const char *ufilename, char **uargv,
489 char **uenvp, unsigned long r5,
490 unsigned long r6, unsigned long r7,
491 struct pt_regs *pregs)
492{
493 int error;
494 struct filename *filename;
495
496 filename = getname((char __user *)ufilename);
497 error = PTR_ERR(filename);
498 if (IS_ERR(filename))
499 goto out;
500
501 error = do_execve(filename->name,
502 (const char __user *const __user *)uargv,
503 (const char __user *const __user *)uenvp,
504 pregs);
505 putname(filename);
506out:
507 return error;
508}
509
510#ifdef CONFIG_FRAME_POINTER 421#ifdef CONFIG_FRAME_POINTER
511static int in_sh64_switch_to(unsigned long pc) 422static int in_sh64_switch_to(unsigned long pc)
512{ 423{
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 23853814bd17..d867cd95a622 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -347,7 +347,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
347{ 347{
348 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP; 348 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
349 sigset_t set; 349 sigset_t set;
350 stack_t __user st;
351 long long ret; 350 long long ret;
352 351
353 /* Always make any pending restarted system calls return -EINTR */ 352 /* Always make any pending restarted system calls return -EINTR */
@@ -365,11 +364,10 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
365 goto badframe; 364 goto badframe;
366 regs->pc -= 4; 365 regs->pc -= 4;
367 366
368 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
369 goto badframe;
370 /* It is more difficult to avoid calling this function than to 367 /* It is more difficult to avoid calling this function than to
371 call it and ignore errors. */ 368 call it and ignore errors. */
372 do_sigaltstack(&st, NULL, REF_REG_SP); 369 if (do_sigaltstack(&frame->uc.uc_stack, NULL, REF_REG_SP) == -EFAULT)
370 goto badframe;
373 371
374 return (int) ret; 372 return (int) ret;
375 373
diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c
index f56b6fe5c5d0..497bab3a0401 100644
--- a/arch/sh/kernel/sys_sh32.c
+++ b/arch/sh/kernel/sys_sh32.c
@@ -60,27 +60,3 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
60 (u64)len0 << 32 | len1, advice); 60 (u64)len0 << 32 | len1, advice);
61#endif 61#endif
62} 62}
63
64#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
65#define SYSCALL_ARG3 "trapa #0x23"
66#else
67#define SYSCALL_ARG3 "trapa #0x13"
68#endif
69
70/*
71 * Do a system call from kernel instead of calling sys_execve so we
72 * end up with proper pt_regs.
73 */
74int kernel_execve(const char *filename,
75 const char *const argv[],
76 const char *const envp[])
77{
78 register long __sc0 __asm__ ("r3") = __NR_execve;
79 register long __sc4 __asm__ ("r4") = (long) filename;
80 register long __sc5 __asm__ ("r5") = (long) argv;
81 register long __sc6 __asm__ ("r6") = (long) envp;
82 __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0)
83 : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)
84 : "memory");
85 return __sc0;
86}
diff --git a/arch/sh/kernel/sys_sh64.c b/arch/sh/kernel/sys_sh64.c
deleted file mode 100644
index c5a38c4bf410..000000000000
--- a/arch/sh/kernel/sys_sh64.c
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * arch/sh/kernel/sys_sh64.c
3 *
4 * Copyright (C) 2000, 2001 Paolo Alberelli
5 *
6 * This file contains various random system calls that
7 * have a non-standard calling sequence on the Linux/SH5
8 * platform.
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details.
13 */
14#include <linux/errno.h>
15#include <linux/rwsem.h>
16#include <linux/sched.h>
17#include <linux/mm.h>
18#include <linux/fs.h>
19#include <linux/smp.h>
20#include <linux/sem.h>
21#include <linux/msg.h>
22#include <linux/shm.h>
23#include <linux/stat.h>
24#include <linux/mman.h>
25#include <linux/file.h>
26#include <linux/syscalls.h>
27#include <linux/ipc.h>
28#include <asm/uaccess.h>
29#include <asm/ptrace.h>
30#include <asm/unistd.h>
31
32/*
33 * Do a system call from kernel instead of calling sys_execve so we
34 * end up with proper pt_regs.
35 */
36int kernel_execve(const char *filename,
37 const char *const argv[],
38 const char *const envp[])
39{
40 register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve);
41 register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename;
42 register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv;
43 register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp;
44 __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)"
45 : "=r" (__sc0)
46 : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );
47 __asm__ __volatile__ ("!dummy %0 %1 %2 %3"
48 : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory");
49 return __sc0;
50}