aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/process.c')
-rw-r--r--arch/s390/kernel/process.c107
1 files changed, 33 insertions, 74 deletions
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 5024be27df44..cd31ad457a9b 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -100,35 +100,6 @@ void cpu_idle(void)
100 100
101extern void __kprobes kernel_thread_starter(void); 101extern void __kprobes kernel_thread_starter(void);
102 102
103asm(
104 ".section .kprobes.text, \"ax\"\n"
105 ".global kernel_thread_starter\n"
106 "kernel_thread_starter:\n"
107 " la 2,0(10)\n"
108 " basr 14,9\n"
109 " la 2,0\n"
110 " br 11\n"
111 ".previous\n");
112
113int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
114{
115 struct pt_regs regs;
116
117 memset(&regs, 0, sizeof(regs));
118 regs.psw.mask = psw_kernel_bits |
119 PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
120 regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
121 regs.gprs[9] = (unsigned long) fn;
122 regs.gprs[10] = (unsigned long) arg;
123 regs.gprs[11] = (unsigned long) do_exit;
124 regs.orig_gpr2 = -1;
125
126 /* Ok, create the new process.. */
127 return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
128 0, &regs, 0, NULL, NULL);
129}
130EXPORT_SYMBOL(kernel_thread);
131
132/* 103/*
133 * Free current thread data structures etc.. 104 * Free current thread data structures etc..
134 */ 105 */
@@ -146,7 +117,7 @@ void release_thread(struct task_struct *dead_task)
146} 117}
147 118
148int copy_thread(unsigned long clone_flags, unsigned long new_stackp, 119int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
149 unsigned long unused, 120 unsigned long arg,
150 struct task_struct *p, struct pt_regs *regs) 121 struct task_struct *p, struct pt_regs *regs)
151{ 122{
152 struct thread_info *ti; 123 struct thread_info *ti;
@@ -158,20 +129,44 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
158 129
159 frame = container_of(task_pt_regs(p), struct fake_frame, childregs); 130 frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
160 p->thread.ksp = (unsigned long) frame; 131 p->thread.ksp = (unsigned long) frame;
161 /* Store access registers to kernel stack of new process. */ 132 /* Save access registers to new thread structure. */
162 frame->childregs = *regs; 133 save_access_regs(&p->thread.acrs[0]);
163 frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ 134 /* start new process with ar4 pointing to the correct address space */
164 frame->childregs.gprs[15] = new_stackp; 135 p->thread.mm_segment = get_fs();
165 frame->sf.back_chain = 0; 136 /* Don't copy debug registers */
137 memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
138 memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
139 clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
140 clear_tsk_thread_flag(p, TIF_PER_TRAP);
141 /* Initialize per thread user and system timer values */
142 ti = task_thread_info(p);
143 ti->user_timer = 0;
144 ti->system_timer = 0;
166 145
146 frame->sf.back_chain = 0;
167 /* new return point is ret_from_fork */ 147 /* new return point is ret_from_fork */
168 frame->sf.gprs[8] = (unsigned long) ret_from_fork; 148 frame->sf.gprs[8] = (unsigned long) ret_from_fork;
169
170 /* fake return stack for resume(), don't go back to schedule */ 149 /* fake return stack for resume(), don't go back to schedule */
171 frame->sf.gprs[9] = (unsigned long) frame; 150 frame->sf.gprs[9] = (unsigned long) frame;
172 151
173 /* Save access registers to new thread structure. */ 152 /* Store access registers to kernel stack of new process. */
174 save_access_regs(&p->thread.acrs[0]); 153 if (unlikely(!regs)) {
154 /* kernel thread */
155 memset(&frame->childregs, 0, sizeof(struct pt_regs));
156 frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT |
157 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
158 frame->childregs.psw.addr = PSW_ADDR_AMODE |
159 (unsigned long) kernel_thread_starter;
160 frame->childregs.gprs[9] = new_stackp; /* function */
161 frame->childregs.gprs[10] = arg;
162 frame->childregs.gprs[11] = (unsigned long) do_exit;
163 frame->childregs.orig_gpr2 = -1;
164
165 return 0;
166 }
167 frame->childregs = *regs;
168 frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */
169 frame->childregs.gprs[15] = new_stackp;
175 170
176 /* Don't copy runtime instrumentation info */ 171 /* Don't copy runtime instrumentation info */
177 p->thread.ri_cb = NULL; 172 p->thread.ri_cb = NULL;
@@ -202,17 +197,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
202 } 197 }
203 } 198 }
204#endif /* CONFIG_64BIT */ 199#endif /* CONFIG_64BIT */
205 /* start new process with ar4 pointing to the correct address space */
206 p->thread.mm_segment = get_fs();
207 /* Don't copy debug registers */
208 memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
209 memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
210 clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
211 clear_tsk_thread_flag(p, TIF_PER_TRAP);
212 /* Initialize per thread user and system timer values */
213 ti = task_thread_info(p);
214 ti->user_timer = 0;
215 ti->system_timer = 0;
216 return 0; 200 return 0;
217} 201}
218 202
@@ -258,31 +242,6 @@ asmlinkage void execve_tail(void)
258} 242}
259 243
260/* 244/*
261 * sys_execve() executes a new program.
262 */
263SYSCALL_DEFINE3(execve, const char __user *, name,
264 const char __user *const __user *, argv,
265 const char __user *const __user *, envp)
266{
267 struct pt_regs *regs = task_pt_regs(current);
268 char *filename;
269 long rc;
270
271 filename = getname(name);
272 rc = PTR_ERR(filename);
273 if (IS_ERR(filename))
274 return rc;
275 rc = do_execve(filename, argv, envp, regs);
276 if (rc)
277 goto out;
278 execve_tail();
279 rc = regs->gprs[2];
280out:
281 putname(filename);
282 return rc;
283}
284
285/*
286 * fill in the FPU structure for a core dump. 245 * fill in the FPU structure for a core dump.
287 */ 246 */
288int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) 247int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)