···2020 select GENERIC_CMOS_UPDATE2121 select GENERIC_STRNCPY_FROM_USER2222 select GENERIC_STRNLEN_USER2323+ select GENERIC_KERNEL_THREAD2324 help2425 The Alpha is a 64-bit general-purpose processor designed and2526 marketed by the Digital Equipment Corporation of blessed memory,
-3
arch/alpha/include/asm/processor.h
···4949/* Free all resources held by a thread. */5050extern void release_thread(struct task_struct *);51515252-/* Create a kernel thread without removing it from tasklists. */5353-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);5454-5552unsigned long get_wchan(struct task_struct *p);56535754#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
···609609.end ret_from_fork610610611611/*612612- * kernel_thread(fn, arg, clone_flags)612612+ * ... and new kernel threads - here613613 */614614 .align 4615615- .globl kernel_thread616616- .ent kernel_thread617617-kernel_thread:618618- /* We can be called from a module. */619619- ldgp $gp, 0($27)620620- .prologue 1621621- subq $sp, SP_OFF+6*8, $sp622622- br $1, 2f /* load start address */623623-624624- /* We've now "returned" from a fake system call. */625625- unop626626- blt $0, 1f /* error? */627627- ldi $1, 0x3fff628628- beq $20, 1f /* parent or child? */629629-630630- bic $sp, $1, $8 /* in child. */631631- jsr $26, ($27)615615+ .globl ret_from_kernel_thread616616+ .ent ret_from_kernel_thread617617+ret_from_kernel_thread:618618+ mov $17, $16619619+ jsr $26, schedule_tail620620+ mov $9, $27621621+ mov $10, $16622622+ jsr $26, ($9)632623 ldgp $gp, 0($26)633624 mov $0, $16634625 mov $31, $26635626 jmp $31, sys_exit636636-637637-1: ret /* in parent. */638638-639639- .align 4640640-2: /* Fake a system call stack frame, as we can't do system calls641641- from kernel space. Note that we store FN and ARG as they642642- need to be set up in the child for the call. Also store $8643643- and $26 for use in the parent. */644644- stq $31, SP_OFF($sp) /* ps */645645- stq $1, SP_OFF+8($sp) /* pc */646646- stq $gp, SP_OFF+16($sp) /* gp */647647- stq $16, 136($sp) /* $27; FN for child */648648- stq $17, SP_OFF+24($sp) /* $16; ARG for child */649649- stq $8, 64($sp) /* $8 */650650- stq $26, 128($sp) /* $26 */651651- /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */652652- ldq $2, alpha_mv+HAE_CACHE653653- stq $2, 152($sp) /* HAE */654654-655655- /* Shuffle FLAGS to the front; add CLONE_VM. */656656- ldi $1, CLONE_VM|CLONE_UNTRACED657657- or $18, $1, $16658658- bsr $26, sys_clone659659-660660- /* We don't actually care for a3 success widgetry in the kernel.661661- Not for positive errno values. */662662- stq $0, 0($sp) /* $0 */663663- br ret_to_kernel664664-.end kernel_thread627627+.end ret_from_kernel_thread665628666629667630/*
+19-18
arch/alpha/kernel/process.c
···259259260260/*261261 * Copy an alpha thread..262262- *263263- * Note the "stack_offset" stuff: when returning to kernel mode, we need264264- * to have some extra stack-space for the kernel stack that still exists265265- * after the "ret_from_fork". When returning to user mode, we only want266266- * the space needed by the syscall stack frame (ie "struct pt_regs").267267- * Use the passed "regs" pointer to determine how much space we need268268- * for a kernel fork().269262 */270263271264int272265copy_thread(unsigned long clone_flags, unsigned long usp,273273- unsigned long unused,266266+ unsigned long arg,274267 struct task_struct * p, struct pt_regs * regs)275268{276269 extern void ret_from_fork(void);270270+ extern void ret_from_kernel_thread(void);277271278272 struct thread_info *childti = task_thread_info(p);279279- struct pt_regs * childregs;280280- struct switch_stack * childstack, *stack;281281- unsigned long stack_offset, settls;273273+ struct pt_regs *childregs = task_pt_regs(p);274274+ struct switch_stack *childstack, *stack;275275+ unsigned long settls;282276283283- stack_offset = PAGE_SIZE - sizeof(struct pt_regs);284284- if (!(regs->ps & 8))285285- stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;286286- childregs = (struct pt_regs *)287287- (stack_offset + PAGE_SIZE + task_stack_page(p));288288-277277+ childstack = ((struct switch_stack *) childregs) - 1;278278+ if (unlikely(!regs)) {279279+ /* kernel thread */280280+ memset(childstack, 0,281281+ sizeof(struct switch_stack) + sizeof(struct pt_regs));282282+ childstack->r26 = (unsigned long) ret_from_kernel_thread;283283+ childstack->r9 = usp; /* function */284284+ childstack->r10 = arg;285285+ childregs->hae = alpha_mv.hae_cache,286286+ childti->pcb.usp = 0;287287+ childti->pcb.ksp = (unsigned long) childstack;288288+ childti->pcb.flags = 1; /* set FEN, clear everything else */289289+ return 0;290290+ }289291 *childregs = *regs;290292 settls = regs->r20;291293 childregs->r0 = 0;···295293 childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */296294 regs->r20 = 0;297295 stack = ((struct switch_stack *) regs) - 1;298298- childstack = ((struct switch_stack *) childregs) - 1;299296 *childstack = *stack;300297 childstack->r26 = (unsigned long) ret_from_fork;301298 childti->pcb.usp = usp;