diff options
Diffstat (limited to 'arch/mn10300/kernel/signal.c')
-rw-r--r-- | arch/mn10300/kernel/signal.c | 102 |
1 files changed, 38 insertions, 64 deletions
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 9dfac5cd16e6..a6c0858592c3 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c | |||
@@ -186,20 +186,11 @@ static int setup_sigcontext(struct sigcontext __user *sc, | |||
186 | /* | 186 | /* |
187 | * determine which stack to use.. | 187 | * determine which stack to use.. |
188 | */ | 188 | */ |
189 | static inline void __user *get_sigframe(struct k_sigaction *ka, | 189 | static inline void __user *get_sigframe(struct ksignal *ksig, |
190 | struct pt_regs *regs, | 190 | struct pt_regs *regs, |
191 | size_t frame_size) | 191 | size_t frame_size) |
192 | { | 192 | { |
193 | unsigned long sp; | 193 | unsigned long sp = sigsp(regs->sp, ksig); |
194 | |||
195 | /* default to using normal stack */ | ||
196 | sp = regs->sp; | ||
197 | |||
198 | /* this is the X/Open sanctioned signal stack switching. */ | ||
199 | if (ka->sa.sa_flags & SA_ONSTACK) { | ||
200 | if (sas_ss_flags(sp) == 0) | ||
201 | sp = current->sas_ss_sp + current->sas_ss_size; | ||
202 | } | ||
203 | 194 | ||
204 | return (void __user *) ((sp - frame_size) & ~7UL); | 195 | return (void __user *) ((sp - frame_size) & ~7UL); |
205 | } | 196 | } |
@@ -207,16 +198,16 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, | |||
207 | /* | 198 | /* |
208 | * set up a normal signal frame | 199 | * set up a normal signal frame |
209 | */ | 200 | */ |
210 | static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | 201 | static int setup_frame(struct ksignal *ksig, sigset_t *set, |
211 | struct pt_regs *regs) | 202 | struct pt_regs *regs) |
212 | { | 203 | { |
213 | struct sigframe __user *frame; | 204 | struct sigframe __user *frame; |
214 | int rsig; | 205 | int rsig, sig = ksig->sig; |
215 | 206 | ||
216 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 207 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
217 | 208 | ||
218 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 209 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
219 | goto give_sigsegv; | 210 | return -EFAULT; |
220 | 211 | ||
221 | rsig = sig; | 212 | rsig = sig; |
222 | if (sig < 32 && | 213 | if (sig < 32 && |
@@ -226,40 +217,40 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
226 | 217 | ||
227 | if (__put_user(rsig, &frame->sig) < 0 || | 218 | if (__put_user(rsig, &frame->sig) < 0 || |
228 | __put_user(&frame->sc, &frame->psc) < 0) | 219 | __put_user(&frame->sc, &frame->psc) < 0) |
229 | goto give_sigsegv; | 220 | return -EFAULT; |
230 | 221 | ||
231 | if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0])) | 222 | if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0])) |
232 | goto give_sigsegv; | 223 | return -EFAULT; |
233 | 224 | ||
234 | if (_NSIG_WORDS > 1) { | 225 | if (_NSIG_WORDS > 1) { |
235 | if (__copy_to_user(frame->extramask, &set->sig[1], | 226 | if (__copy_to_user(frame->extramask, &set->sig[1], |
236 | sizeof(frame->extramask))) | 227 | sizeof(frame->extramask))) |
237 | goto give_sigsegv; | 228 | return -EFAULT; |
238 | } | 229 | } |
239 | 230 | ||
240 | /* set up to return from userspace. If provided, use a stub already in | 231 | /* set up to return from userspace. If provided, use a stub already in |
241 | * userspace */ | 232 | * userspace */ |
242 | if (ka->sa.sa_flags & SA_RESTORER) { | 233 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
243 | if (__put_user(ka->sa.sa_restorer, &frame->pretcode)) | 234 | if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode)) |
244 | goto give_sigsegv; | 235 | return -EFAULT; |
245 | } else { | 236 | } else { |
246 | if (__put_user((void (*)(void))frame->retcode, | 237 | if (__put_user((void (*)(void))frame->retcode, |
247 | &frame->pretcode)) | 238 | &frame->pretcode)) |
248 | goto give_sigsegv; | 239 | return -EFAULT; |
249 | /* this is mov $,d0; syscall 0 */ | 240 | /* this is mov $,d0; syscall 0 */ |
250 | if (__put_user(0x2c, (char *)(frame->retcode + 0)) || | 241 | if (__put_user(0x2c, (char *)(frame->retcode + 0)) || |
251 | __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) || | 242 | __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) || |
252 | __put_user(0x00, (char *)(frame->retcode + 2)) || | 243 | __put_user(0x00, (char *)(frame->retcode + 2)) || |
253 | __put_user(0xf0, (char *)(frame->retcode + 3)) || | 244 | __put_user(0xf0, (char *)(frame->retcode + 3)) || |
254 | __put_user(0xe0, (char *)(frame->retcode + 4))) | 245 | __put_user(0xe0, (char *)(frame->retcode + 4))) |
255 | goto give_sigsegv; | 246 | return -EFAULT; |
256 | flush_icache_range((unsigned long) frame->retcode, | 247 | flush_icache_range((unsigned long) frame->retcode, |
257 | (unsigned long) frame->retcode + 5); | 248 | (unsigned long) frame->retcode + 5); |
258 | } | 249 | } |
259 | 250 | ||
260 | /* set up registers for signal handler */ | 251 | /* set up registers for signal handler */ |
261 | regs->sp = (unsigned long) frame; | 252 | regs->sp = (unsigned long) frame; |
262 | regs->pc = (unsigned long) ka->sa.sa_handler; | 253 | regs->pc = (unsigned long) ksig->ka.sa.sa_handler; |
263 | regs->d0 = sig; | 254 | regs->d0 = sig; |
264 | regs->d1 = (unsigned long) &frame->sc; | 255 | regs->d1 = (unsigned long) &frame->sc; |
265 | 256 | ||
@@ -270,25 +261,21 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
270 | #endif | 261 | #endif |
271 | 262 | ||
272 | return 0; | 263 | return 0; |
273 | |||
274 | give_sigsegv: | ||
275 | force_sigsegv(sig, current); | ||
276 | return -EFAULT; | ||
277 | } | 264 | } |
278 | 265 | ||
279 | /* | 266 | /* |
280 | * set up a realtime signal frame | 267 | * set up a realtime signal frame |
281 | */ | 268 | */ |
282 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 269 | static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, |
283 | sigset_t *set, struct pt_regs *regs) | 270 | struct pt_regs *regs) |
284 | { | 271 | { |
285 | struct rt_sigframe __user *frame; | 272 | struct rt_sigframe __user *frame; |
286 | int rsig; | 273 | int rsig, sig = ksig->sig; |
287 | 274 | ||
288 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 275 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
289 | 276 | ||
290 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 277 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
291 | goto give_sigsegv; | 278 | return -EFAULT; |
292 | 279 | ||
293 | rsig = sig; | 280 | rsig = sig; |
294 | if (sig < 32 && | 281 | if (sig < 32 && |
@@ -299,8 +286,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
299 | if (__put_user(rsig, &frame->sig) || | 286 | if (__put_user(rsig, &frame->sig) || |
300 | __put_user(&frame->info, &frame->pinfo) || | 287 | __put_user(&frame->info, &frame->pinfo) || |
301 | __put_user(&frame->uc, &frame->puc) || | 288 | __put_user(&frame->uc, &frame->puc) || |
302 | copy_siginfo_to_user(&frame->info, info)) | 289 | copy_siginfo_to_user(&frame->info, &ksig->info)) |
303 | goto give_sigsegv; | 290 | return -EFAULT; |
304 | 291 | ||
305 | /* create the ucontext. */ | 292 | /* create the ucontext. */ |
306 | if (__put_user(0, &frame->uc.uc_flags) || | 293 | if (__put_user(0, &frame->uc.uc_flags) || |
@@ -309,13 +296,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
309 | setup_sigcontext(&frame->uc.uc_mcontext, | 296 | setup_sigcontext(&frame->uc.uc_mcontext, |
310 | &frame->fpuctx, regs, set->sig[0]) || | 297 | &frame->fpuctx, regs, set->sig[0]) || |
311 | __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) | 298 | __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) |
312 | goto give_sigsegv; | 299 | return -EFAULT; |
313 | 300 | ||
314 | /* set up to return from userspace. If provided, use a stub already in | 301 | /* set up to return from userspace. If provided, use a stub already in |
315 | * userspace */ | 302 | * userspace */ |
316 | if (ka->sa.sa_flags & SA_RESTORER) { | 303 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
317 | if (__put_user(ka->sa.sa_restorer, &frame->pretcode)) | 304 | if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode)) |
318 | goto give_sigsegv; | 305 | return -EFAULT; |
306 | |||
319 | } else { | 307 | } else { |
320 | if (__put_user((void(*)(void))frame->retcode, | 308 | if (__put_user((void(*)(void))frame->retcode, |
321 | &frame->pretcode) || | 309 | &frame->pretcode) || |
@@ -326,7 +314,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
326 | __put_user(0x00, (char *)(frame->retcode + 2)) || | 314 | __put_user(0x00, (char *)(frame->retcode + 2)) || |
327 | __put_user(0xf0, (char *)(frame->retcode + 3)) || | 315 | __put_user(0xf0, (char *)(frame->retcode + 3)) || |
328 | __put_user(0xe0, (char *)(frame->retcode + 4))) | 316 | __put_user(0xe0, (char *)(frame->retcode + 4))) |
329 | goto give_sigsegv; | 317 | return -EFAULT; |
330 | 318 | ||
331 | flush_icache_range((u_long) frame->retcode, | 319 | flush_icache_range((u_long) frame->retcode, |
332 | (u_long) frame->retcode + 5); | 320 | (u_long) frame->retcode + 5); |
@@ -334,7 +322,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
334 | 322 | ||
335 | /* Set up registers for signal handler */ | 323 | /* Set up registers for signal handler */ |
336 | regs->sp = (unsigned long) frame; | 324 | regs->sp = (unsigned long) frame; |
337 | regs->pc = (unsigned long) ka->sa.sa_handler; | 325 | regs->pc = (unsigned long) ksig->ka.sa.sa_handler; |
338 | regs->d0 = sig; | 326 | regs->d0 = sig; |
339 | regs->d1 = (long) &frame->info; | 327 | regs->d1 = (long) &frame->info; |
340 | 328 | ||
@@ -345,10 +333,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
345 | #endif | 333 | #endif |
346 | 334 | ||
347 | return 0; | 335 | return 0; |
348 | |||
349 | give_sigsegv: | ||
350 | force_sigsegv(sig, current); | ||
351 | return -EFAULT; | ||
352 | } | 336 | } |
353 | 337 | ||
354 | static inline void stepback(struct pt_regs *regs) | 338 | static inline void stepback(struct pt_regs *regs) |
@@ -360,9 +344,7 @@ static inline void stepback(struct pt_regs *regs) | |||
360 | /* | 344 | /* |
361 | * handle the actual delivery of a signal to userspace | 345 | * handle the actual delivery of a signal to userspace |
362 | */ | 346 | */ |
363 | static int handle_signal(int sig, | 347 | static int handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
364 | siginfo_t *info, struct k_sigaction *ka, | ||
365 | struct pt_regs *regs) | ||
366 | { | 348 | { |
367 | sigset_t *oldset = sigmask_to_save(); | 349 | sigset_t *oldset = sigmask_to_save(); |
368 | int ret; | 350 | int ret; |
@@ -377,7 +359,7 @@ static int handle_signal(int sig, | |||
377 | break; | 359 | break; |
378 | 360 | ||
379 | case -ERESTARTSYS: | 361 | case -ERESTARTSYS: |
380 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 362 | if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { |
381 | regs->d0 = -EINTR; | 363 | regs->d0 = -EINTR; |
382 | break; | 364 | break; |
383 | } | 365 | } |
@@ -390,15 +372,12 @@ static int handle_signal(int sig, | |||
390 | } | 372 | } |
391 | 373 | ||
392 | /* Set up the stack frame */ | 374 | /* Set up the stack frame */ |
393 | if (ka->sa.sa_flags & SA_SIGINFO) | 375 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
394 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 376 | ret = setup_rt_frame(ksig, oldset, regs); |
395 | else | 377 | else |
396 | ret = setup_frame(sig, ka, oldset, regs); | 378 | ret = setup_frame(ksig, oldset, regs); |
397 | if (ret) | ||
398 | return ret; | ||
399 | 379 | ||
400 | signal_delivered(sig, info, ka, regs, | 380 | signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); |
401 | test_thread_flag(TIF_SINGLESTEP)); | ||
402 | return 0; | 381 | return 0; |
403 | } | 382 | } |
404 | 383 | ||
@@ -407,15 +386,10 @@ static int handle_signal(int sig, | |||
407 | */ | 386 | */ |
408 | static void do_signal(struct pt_regs *regs) | 387 | static void do_signal(struct pt_regs *regs) |
409 | { | 388 | { |
410 | struct k_sigaction ka; | 389 | struct ksignal ksig; |
411 | siginfo_t info; | ||
412 | int signr; | ||
413 | |||
414 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | ||
415 | if (signr > 0) { | ||
416 | if (handle_signal(signr, &info, &ka, regs) == 0) { | ||
417 | } | ||
418 | 390 | ||
391 | if (get_signal(&ksig)) { | ||
392 | handle_signal(&ksig, regs); | ||
419 | return; | 393 | return; |
420 | } | 394 | } |
421 | 395 | ||