aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-09-09 22:03:42 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-09-30 22:53:18 -0400
commitcba1ec7e88a0257eb13e84d170a93cd52b702562 (patch)
tree8a79d3ac38463e3610c5f18481d07bda1e39d45b
parent756144f8ea2e4fccbbf1a5644f3e1e889a48f765 (diff)
alpha: switch to generic kernel_thread()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/alpha/Kconfig1
-rw-r--r--arch/alpha/include/asm/processor.h3
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c3
-rw-r--r--arch/alpha/kernel/entry.S57
-rw-r--r--arch/alpha/kernel/process.c39
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. */
50extern void release_thread(struct task_struct *); 50extern void release_thread(struct task_struct *);
51 51
52/* Create a kernel thread without removing it from tasklists. */
53extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
54
55unsigned long get_wchan(struct task_struct *p); 52unsigned 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);
50EXPORT_SYMBOL(alpha_write_fp_reg); 50EXPORT_SYMBOL(alpha_write_fp_reg);
51EXPORT_SYMBOL(alpha_write_fp_reg_s); 51EXPORT_SYMBOL(alpha_write_fp_reg_s);
52 52
53/* entry.S */
54EXPORT_SYMBOL(kernel_thread);
55
56/* Networking helper routines. */ 53/* Networking helper routines. */
57EXPORT_SYMBOL(csum_tcpudp_magic); 54EXPORT_SYMBOL(csum_tcpudp_magic);
58EXPORT_SYMBOL(ip_compute_csum); 55EXPORT_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
617kernel_thread: 617ret_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
6371: ret /* in parent. */
638
639 .align 4
6402: /* 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
271int 264int
272copy_thread(unsigned long clone_flags, unsigned long usp, 265copy_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;