diff options
author | Mark Salter <msalter@redhat.com> | 2012-09-21 12:26:37 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-01 00:59:08 -0400 |
commit | 46f15067c020a0ce712cb2d3ef38c0589a521c15 (patch) | |
tree | f980e4faf9dccc1be052fdbbb1dbd785c6238cc6 /arch/c6x | |
parent | 61b7fbc3f4ebdcfd34f9438adfab8df936a19e33 (diff) |
c6x: add ret_from_kernel_thread(), simplify kernel_thread()
Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/c6x')
-rw-r--r-- | arch/c6x/kernel/entry.S | 20 | ||||
-rw-r--r-- | arch/c6x/kernel/process.c | 38 |
2 files changed, 32 insertions, 26 deletions
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S index 30b37e5f4a61..6e6bd9d3d9cc 100644 --- a/arch/c6x/kernel/entry.S +++ b/arch/c6x/kernel/entry.S | |||
@@ -400,6 +400,26 @@ ret_from_fork_2: | |||
400 | STW .D2T2 B0,*+SP(REGS_A4+8) | 400 | STW .D2T2 B0,*+SP(REGS_A4+8) |
401 | ENDPROC(ret_from_fork) | 401 | ENDPROC(ret_from_fork) |
402 | 402 | ||
403 | ENTRY(ret_from_kernel_thread) | ||
404 | #ifdef CONFIG_C6X_BIG_KERNEL | ||
405 | MVKL .S1 schedule_tail,A0 | ||
406 | MVKH .S1 schedule_tail,A0 | ||
407 | B .S2X A0 | ||
408 | #else | ||
409 | B .S2 schedule_tail | ||
410 | #endif | ||
411 | LDW .D2T2 *+SP(REGS_A0+8),B10 /* get fn */ | ||
412 | ADDKPC .S2 0f,B3,3 | ||
413 | 0: | ||
414 | B .S2 B10 /* call fn */ | ||
415 | LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ | ||
416 | MVKL .S2 sys_exit,B11 | ||
417 | MVKH .S2 sys_exit,B11 | ||
418 | ADDKPC .S2 0f,B3,1 | ||
419 | 0: | ||
420 | BNOP .S2 B11,5 /* jump to sys_exit */ | ||
421 | ENDPROC(ret_from_kernel_thread) | ||
422 | |||
403 | ;; | 423 | ;; |
404 | ;; These are the interrupt handlers, responsible for calling __do_IRQ() | 424 | ;; These are the interrupt handlers, responsible for calling __do_IRQ() |
405 | ;; int6 is used for syscalls (see _system_call entry) | 425 | ;; int6 is used for syscalls (see _system_call entry) |
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c index 45e924a636a0..d2ffc9bdaba1 100644 --- a/arch/c6x/kernel/process.c +++ b/arch/c6x/kernel/process.c | |||
@@ -25,6 +25,7 @@ void (*c6x_restart)(void); | |||
25 | void (*c6x_halt)(void); | 25 | void (*c6x_halt)(void); |
26 | 26 | ||
27 | extern asmlinkage void ret_from_fork(void); | 27 | extern asmlinkage void ret_from_fork(void); |
28 | extern asmlinkage void ret_from_kernel_thread(void); | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * power off function, if any | 31 | * power off function, if any |
@@ -103,36 +104,21 @@ void machine_power_off(void) | |||
103 | halt_loop(); | 104 | halt_loop(); |
104 | } | 105 | } |
105 | 106 | ||
106 | static void kernel_thread_helper(int dummy, void *arg, int (*fn)(void *)) | ||
107 | { | ||
108 | do_exit(fn(arg)); | ||
109 | } | ||
110 | |||
111 | /* | 107 | /* |
112 | * Create a kernel thread | 108 | * Create a kernel thread |
113 | */ | 109 | */ |
114 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | 110 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) |
115 | { | 111 | { |
116 | struct pt_regs regs; | 112 | struct pt_regs regs = { |
117 | 113 | .a0 = (unsigned long)fn, | |
118 | /* | 114 | .a1 = (unsigned long)arg, |
119 | * copy_thread sets a4 to zero (child return from fork) | 115 | .tsr = 0, /* kernel mode */ |
120 | * so we can't just set things up to directly return to | 116 | }; |
121 | * fn. | ||
122 | */ | ||
123 | memset(®s, 0, sizeof(regs)); | ||
124 | regs.b4 = (unsigned long) arg; | ||
125 | regs.a6 = (unsigned long) fn; | ||
126 | regs.pc = (unsigned long) kernel_thread_helper; | ||
127 | local_save_flags(regs.csr); | ||
128 | regs.csr |= 1; | ||
129 | regs.tsr = 5; /* Set GEE and GIE in TSR */ | ||
130 | 117 | ||
131 | /* Ok, create the new process.. */ | 118 | /* Ok, create the new process.. */ |
132 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, -1, ®s, | 119 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, -1, ®s, |
133 | 0, NULL, NULL); | 120 | 0, NULL, NULL); |
134 | } | 121 | } |
135 | EXPORT_SYMBOL(kernel_thread); | ||
136 | 122 | ||
137 | void flush_thread(void) | 123 | void flush_thread(void) |
138 | { | 124 | { |
@@ -192,21 +178,21 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
192 | childregs = task_pt_regs(p); | 178 | childregs = task_pt_regs(p); |
193 | 179 | ||
194 | *childregs = *regs; | 180 | *childregs = *regs; |
195 | childregs->a4 = 0; | ||
196 | 181 | ||
197 | if (usp == -1) | 182 | if (usp == -1) { |
198 | /* case of __kernel_thread: we return to supervisor space */ | 183 | /* case of __kernel_thread: we return to supervisor space */ |
199 | childregs->sp = (unsigned long)(childregs + 1); | 184 | childregs->sp = (unsigned long)(childregs + 1); |
200 | else | 185 | p->thread.pc = (unsigned long) ret_from_kernel_thread; |
186 | } else { | ||
201 | /* Otherwise use the given stack */ | 187 | /* Otherwise use the given stack */ |
202 | childregs->sp = usp; | 188 | childregs->sp = usp; |
189 | p->thread.pc = (unsigned long) ret_from_fork; | ||
190 | } | ||
203 | 191 | ||
204 | /* Set usp/ksp */ | 192 | /* Set usp/ksp */ |
205 | p->thread.usp = childregs->sp; | 193 | p->thread.usp = childregs->sp; |
206 | /* switch_to uses stack to save/restore 14 callee-saved regs */ | ||
207 | thread_saved_ksp(p) = (unsigned long)childregs - 8; | 194 | thread_saved_ksp(p) = (unsigned long)childregs - 8; |
208 | p->thread.pc = (unsigned int) ret_from_fork; | 195 | p->thread.wchan = p->thread.pc; |
209 | p->thread.wchan = (unsigned long) ret_from_fork; | ||
210 | #ifdef __DSBT__ | 196 | #ifdef __DSBT__ |
211 | { | 197 | { |
212 | unsigned long dp; | 198 | unsigned long dp; |