diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-09 22:03:42 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-30 22:53:18 -0400 |
commit | cba1ec7e88a0257eb13e84d170a93cd52b702562 (patch) | |
tree | 8a79d3ac38463e3610c5f18481d07bda1e39d45b | |
parent | 756144f8ea2e4fccbbf1a5644f3e1e889a48f765 (diff) |
alpha: switch to generic kernel_thread()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | arch/alpha/Kconfig | 1 | ||||
-rw-r--r-- | arch/alpha/include/asm/processor.h | 3 | ||||
-rw-r--r-- | arch/alpha/kernel/alpha_ksyms.c | 3 | ||||
-rw-r--r-- | arch/alpha/kernel/entry.S | 57 | ||||
-rw-r--r-- | arch/alpha/kernel/process.c | 39 |
5 files changed, 31 insertions, 72 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9944dedee5b1..7da91246e279 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -20,6 +20,7 @@ config ALPHA | |||
20 | select GENERIC_CMOS_UPDATE | 20 | select GENERIC_CMOS_UPDATE |
21 | select GENERIC_STRNCPY_FROM_USER | 21 | select GENERIC_STRNCPY_FROM_USER |
22 | select GENERIC_STRNLEN_USER | 22 | select GENERIC_STRNLEN_USER |
23 | select GENERIC_KERNEL_THREAD | ||
23 | help | 24 | help |
24 | The Alpha is a 64-bit general-purpose processor designed and | 25 | The Alpha is a 64-bit general-purpose processor designed and |
25 | marketed by the Digital Equipment Corporation of blessed memory, | 26 | marketed by the Digital Equipment Corporation of blessed memory, |
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h index e37b887b3d9f..6cb7fe85c4b5 100644 --- a/arch/alpha/include/asm/processor.h +++ b/arch/alpha/include/asm/processor.h | |||
@@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long); | |||
49 | /* Free all resources held by a thread. */ | 49 | /* Free all resources held by a thread. */ |
50 | extern void release_thread(struct task_struct *); | 50 | extern void release_thread(struct task_struct *); |
51 | 51 | ||
52 | /* Create a kernel thread without removing it from tasklists. */ | ||
53 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
54 | |||
55 | unsigned long get_wchan(struct task_struct *p); | 52 | unsigned long get_wchan(struct task_struct *p); |
56 | 53 | ||
57 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) | 54 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) |
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 15fa821d09cd..89566b346c0f 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c | |||
@@ -50,9 +50,6 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s); | |||
50 | EXPORT_SYMBOL(alpha_write_fp_reg); | 50 | EXPORT_SYMBOL(alpha_write_fp_reg); |
51 | EXPORT_SYMBOL(alpha_write_fp_reg_s); | 51 | EXPORT_SYMBOL(alpha_write_fp_reg_s); |
52 | 52 | ||
53 | /* entry.S */ | ||
54 | EXPORT_SYMBOL(kernel_thread); | ||
55 | |||
56 | /* Networking helper routines. */ | 53 | /* Networking helper routines. */ |
57 | EXPORT_SYMBOL(csum_tcpudp_magic); | 54 | EXPORT_SYMBOL(csum_tcpudp_magic); |
58 | EXPORT_SYMBOL(ip_compute_csum); | 55 | EXPORT_SYMBOL(ip_compute_csum); |
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 61ff145cab6e..421dccf273eb 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S | |||
@@ -609,59 +609,22 @@ ret_from_fork: | |||
609 | .end ret_from_fork | 609 | .end ret_from_fork |
610 | 610 | ||
611 | /* | 611 | /* |
612 | * kernel_thread(fn, arg, clone_flags) | 612 | * ... and new kernel threads - here |
613 | */ | 613 | */ |
614 | .align 4 | 614 | .align 4 |
615 | .globl kernel_thread | 615 | .globl ret_from_kernel_thread |
616 | .ent kernel_thread | 616 | .ent ret_from_kernel_thread |
617 | kernel_thread: | 617 | ret_from_kernel_thread: |
618 | /* We can be called from a module. */ | 618 | mov $17, $16 |
619 | ldgp $gp, 0($27) | 619 | jsr $26, schedule_tail |
620 | .prologue 1 | 620 | mov $9, $27 |
621 | subq $sp, SP_OFF+6*8, $sp | 621 | mov $10, $16 |
622 | br $1, 2f /* load start address */ | 622 | jsr $26, ($9) |
623 | |||
624 | /* We've now "returned" from a fake system call. */ | ||
625 | unop | ||
626 | blt $0, 1f /* error? */ | ||
627 | ldi $1, 0x3fff | ||
628 | beq $20, 1f /* parent or child? */ | ||
629 | |||
630 | bic $sp, $1, $8 /* in child. */ | ||
631 | jsr $26, ($27) | ||
632 | ldgp $gp, 0($26) | 623 | ldgp $gp, 0($26) |
633 | mov $0, $16 | 624 | mov $0, $16 |
634 | mov $31, $26 | 625 | mov $31, $26 |
635 | jmp $31, sys_exit | 626 | jmp $31, sys_exit |
636 | 627 | .end ret_from_kernel_thread | |
637 | 1: ret /* in parent. */ | ||
638 | |||
639 | .align 4 | ||
640 | 2: /* Fake a system call stack frame, as we can't do system calls | ||
641 | from kernel space. Note that we store FN and ARG as they | ||
642 | need to be set up in the child for the call. Also store $8 | ||
643 | and $26 for use in the parent. */ | ||
644 | stq $31, SP_OFF($sp) /* ps */ | ||
645 | stq $1, SP_OFF+8($sp) /* pc */ | ||
646 | stq $gp, SP_OFF+16($sp) /* gp */ | ||
647 | stq $16, 136($sp) /* $27; FN for child */ | ||
648 | stq $17, SP_OFF+24($sp) /* $16; ARG for child */ | ||
649 | stq $8, 64($sp) /* $8 */ | ||
650 | stq $26, 128($sp) /* $26 */ | ||
651 | /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */ | ||
652 | ldq $2, alpha_mv+HAE_CACHE | ||
653 | stq $2, 152($sp) /* HAE */ | ||
654 | |||
655 | /* Shuffle FLAGS to the front; add CLONE_VM. */ | ||
656 | ldi $1, CLONE_VM|CLONE_UNTRACED | ||
657 | or $18, $1, $16 | ||
658 | bsr $26, sys_clone | ||
659 | |||
660 | /* We don't actually care for a3 success widgetry in the kernel. | ||
661 | Not for positive errno values. */ | ||
662 | stq $0, 0($sp) /* $0 */ | ||
663 | br ret_to_kernel | ||
664 | .end kernel_thread | ||
665 | 628 | ||
666 | 629 | ||
667 | /* | 630 | /* |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 145473909199..6b33ecdbc534 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
@@ -259,33 +259,35 @@ alpha_vfork(struct pt_regs *regs) | |||
259 | 259 | ||
260 | /* | 260 | /* |
261 | * Copy an alpha thread.. | 261 | * Copy an alpha thread.. |
262 | * | ||
263 | * Note the "stack_offset" stuff: when returning to kernel mode, we need | ||
264 | * to have some extra stack-space for the kernel stack that still exists | ||
265 | * after the "ret_from_fork". When returning to user mode, we only want | ||
266 | * the space needed by the syscall stack frame (ie "struct pt_regs"). | ||
267 | * Use the passed "regs" pointer to determine how much space we need | ||
268 | * for a kernel fork(). | ||
269 | */ | 262 | */ |
270 | 263 | ||
271 | int | 264 | int |
272 | copy_thread(unsigned long clone_flags, unsigned long usp, | 265 | copy_thread(unsigned long clone_flags, unsigned long usp, |
273 | unsigned long unused, | 266 | unsigned long arg, |
274 | struct task_struct * p, struct pt_regs * regs) | 267 | struct task_struct * p, struct pt_regs * regs) |
275 | { | 268 | { |
276 | extern void ret_from_fork(void); | 269 | extern void ret_from_fork(void); |
270 | extern void ret_from_kernel_thread(void); | ||
277 | 271 | ||
278 | struct thread_info *childti = task_thread_info(p); | 272 | struct thread_info *childti = task_thread_info(p); |
279 | struct pt_regs * childregs; | 273 | struct pt_regs *childregs = task_pt_regs(p); |
280 | struct switch_stack * childstack, *stack; | 274 | struct switch_stack *childstack, *stack; |
281 | unsigned long stack_offset, settls; | 275 | unsigned long settls; |
282 | 276 | ||
283 | stack_offset = PAGE_SIZE - sizeof(struct pt_regs); | 277 | childstack = ((struct switch_stack *) childregs) - 1; |
284 | if (!(regs->ps & 8)) | 278 | if (unlikely(!regs)) { |
285 | stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; | 279 | /* kernel thread */ |
286 | childregs = (struct pt_regs *) | 280 | memset(childstack, 0, |
287 | (stack_offset + PAGE_SIZE + task_stack_page(p)); | 281 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); |
288 | 282 | childstack->r26 = (unsigned long) ret_from_kernel_thread; | |
283 | childstack->r9 = usp; /* function */ | ||
284 | childstack->r10 = arg; | ||
285 | childregs->hae = alpha_mv.hae_cache, | ||
286 | childti->pcb.usp = 0; | ||
287 | childti->pcb.ksp = (unsigned long) childstack; | ||
288 | childti->pcb.flags = 1; /* set FEN, clear everything else */ | ||
289 | return 0; | ||
290 | } | ||
289 | *childregs = *regs; | 291 | *childregs = *regs; |
290 | settls = regs->r20; | 292 | settls = regs->r20; |
291 | childregs->r0 = 0; | 293 | childregs->r0 = 0; |
@@ -293,7 +295,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
293 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ | 295 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ |
294 | regs->r20 = 0; | 296 | regs->r20 = 0; |
295 | stack = ((struct switch_stack *) regs) - 1; | 297 | stack = ((struct switch_stack *) regs) - 1; |
296 | childstack = ((struct switch_stack *) childregs) - 1; | ||
297 | *childstack = *stack; | 298 | *childstack = *stack; |
298 | childstack->r26 = (unsigned long) ret_from_fork; | 299 | childstack->r26 = (unsigned long) ret_from_fork; |
299 | childti->pcb.usp = usp; | 300 | childti->pcb.usp = usp; |