Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

alpha: switch to generic kernel_thread()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro cba1ec7e 756144f8

+30 -71
+1
arch/alpha/Kconfig
··· 20 20 select GENERIC_CMOS_UPDATE 21 21 select GENERIC_STRNCPY_FROM_USER 22 22 select GENERIC_STRNLEN_USER 23 + select GENERIC_KERNEL_THREAD 23 24 help 24 25 The Alpha is a 64-bit general-purpose processor designed and 25 26 marketed by the Digital Equipment Corporation of blessed memory,
-3
arch/alpha/include/asm/processor.h
··· 49 49 /* Free all resources held by a thread. */ 50 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 52 unsigned long get_wchan(struct task_struct *p); 56 53 57 54 #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
-3
arch/alpha/kernel/alpha_ksyms.c
··· 50 50 EXPORT_SYMBOL(alpha_write_fp_reg); 51 51 EXPORT_SYMBOL(alpha_write_fp_reg_s); 52 52 53 - /* entry.S */ 54 - EXPORT_SYMBOL(kernel_thread); 55 - 56 53 /* Networking helper routines. */ 57 54 EXPORT_SYMBOL(csum_tcpudp_magic); 58 55 EXPORT_SYMBOL(ip_compute_csum);
+10 -47
arch/alpha/kernel/entry.S
··· 609 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 614 .align 4 615 - .globl kernel_thread 616 - .ent kernel_thread 617 - kernel_thread: 618 - /* We can be called from a module. */ 619 - ldgp $gp, 0($27) 620 - .prologue 1 621 - subq $sp, SP_OFF+6*8, $sp 622 - br $1, 2f /* load start address */ 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) 615 + .globl ret_from_kernel_thread 616 + .ent ret_from_kernel_thread 617 + ret_from_kernel_thread: 618 + mov $17, $16 619 + jsr $26, schedule_tail 620 + mov $9, $27 621 + mov $10, $16 622 + jsr $26, ($9) 632 623 ldgp $gp, 0($26) 633 624 mov $0, $16 634 625 mov $31, $26 635 626 jmp $31, sys_exit 636 - 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 627 + .end ret_from_kernel_thread 665 628 666 629 667 630 /*
+19 -18
arch/alpha/kernel/process.c
··· 259 259 260 260 /* 261 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 264 int 272 265 copy_thread(unsigned long clone_flags, unsigned long usp, 273 - unsigned long unused, 266 + unsigned long arg, 274 267 struct task_struct * p, struct pt_regs * regs) 275 268 { 276 269 extern void ret_from_fork(void); 270 + extern void ret_from_kernel_thread(void); 277 271 278 272 struct thread_info *childti = task_thread_info(p); 279 - struct pt_regs * childregs; 280 - struct switch_stack * childstack, *stack; 281 - unsigned long stack_offset, settls; 273 + struct pt_regs *childregs = task_pt_regs(p); 274 + struct switch_stack *childstack, *stack; 275 + unsigned long settls; 282 276 283 - stack_offset = PAGE_SIZE - sizeof(struct pt_regs); 284 - if (!(regs->ps & 8)) 285 - stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; 286 - childregs = (struct pt_regs *) 287 - (stack_offset + PAGE_SIZE + task_stack_page(p)); 288 - 277 + childstack = ((struct switch_stack *) childregs) - 1; 278 + if (unlikely(!regs)) { 279 + /* kernel thread */ 280 + memset(childstack, 0, 281 + sizeof(struct switch_stack) + sizeof(struct pt_regs)); 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 291 *childregs = *regs; 290 292 settls = regs->r20; 291 293 childregs->r0 = 0; ··· 295 293 childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ 296 294 regs->r20 = 0; 297 295 stack = ((struct switch_stack *) regs) - 1; 298 - childstack = ((struct switch_stack *) childregs) - 1; 299 296 *childstack = *stack; 300 297 childstack->r26 = (unsigned long) ret_from_fork; 301 298 childti->pcb.usp = usp;