Skip to content

Commit

Permalink
s390: switch to generic kernel_thread()
Browse files Browse the repository at this point in the history
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Oct 1, 2012
1 parent 37fe5d4 commit f9a7e02
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 40 deletions.
1 change: 1 addition & 0 deletions arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ config S390
select GENERIC_CLOCKEVENTS
select KTIME_SCALAR if 32BIT
select HAVE_ARCH_SECCOMP_FILTER
select GENERIC_KERNEL_THREAD

config SCHED_OMIT_FRAME_POINTER
def_bool y
Expand Down
1 change: 0 additions & 1 deletion arch/s390/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ struct seq_file;

/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);

/*
* Return saved PC of a blocked thread.
Expand Down
72 changes: 33 additions & 39 deletions arch/s390/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,6 @@ void cpu_idle(void)

extern void __kprobes kernel_thread_starter(void);

int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
struct pt_regs regs;

memset(&regs, 0, sizeof(regs));
regs.psw.mask = psw_kernel_bits |
PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
regs.gprs[9] = (unsigned long) fn;
regs.gprs[10] = (unsigned long) arg;
regs.gprs[11] = (unsigned long) do_exit;
regs.orig_gpr2 = -1;

/* Ok, create the new process.. */
return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
0, &regs, 0, NULL, NULL);
}
EXPORT_SYMBOL(kernel_thread);

/*
* Free current thread data structures etc..
*/
Expand All @@ -133,7 +114,7 @@ void release_thread(struct task_struct *dead_task)
}

int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
unsigned long unused,
unsigned long arg,
struct task_struct *p, struct pt_regs *regs)
{
struct thread_info *ti;
Expand All @@ -145,20 +126,44 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,

frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
p->thread.ksp = (unsigned long) frame;
/* Store access registers to kernel stack of new process. */
frame->childregs = *regs;
frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */
frame->childregs.gprs[15] = new_stackp;
frame->sf.back_chain = 0;
/* Save access registers to new thread structure. */
save_access_regs(&p->thread.acrs[0]);
/* start new process with ar4 pointing to the correct address space */
p->thread.mm_segment = get_fs();
/* Don't copy debug registers */
memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
clear_tsk_thread_flag(p, TIF_PER_TRAP);
/* Initialize per thread user and system timer values */
ti = task_thread_info(p);
ti->user_timer = 0;
ti->system_timer = 0;

frame->sf.back_chain = 0;
/* new return point is ret_from_fork */
frame->sf.gprs[8] = (unsigned long) ret_from_fork;

/* fake return stack for resume(), don't go back to schedule */
frame->sf.gprs[9] = (unsigned long) frame;

/* Save access registers to new thread structure. */
save_access_regs(&p->thread.acrs[0]);
/* Store access registers to kernel stack of new process. */
if (unlikely(!regs)) {
/* kernel thread */
memset(&frame->childregs, 0, sizeof(struct pt_regs));
frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT |
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
frame->childregs.psw.addr = PSW_ADDR_AMODE |
(unsigned long) kernel_thread_starter;
frame->childregs.gprs[9] = new_stackp; /* function */
frame->childregs.gprs[10] = arg;
frame->childregs.gprs[11] = (unsigned long) do_exit;
frame->childregs.orig_gpr2 = -1;

return 0;
}
frame->childregs = *regs;
frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */
frame->childregs.gprs[15] = new_stackp;

#ifndef CONFIG_64BIT
/*
Expand All @@ -184,17 +189,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
}
}
#endif /* CONFIG_64BIT */
/* start new process with ar4 pointing to the correct address space */
p->thread.mm_segment = get_fs();
/* Don't copy debug registers */
memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
clear_tsk_thread_flag(p, TIF_PER_TRAP);
/* Initialize per thread user and system timer values */
ti = task_thread_info(p);
ti->user_timer = 0;
ti->system_timer = 0;
return 0;
}

Expand Down

0 comments on commit f9a7e02

Please sign in to comment.