1/* MN10300 Signal handling 2 * 3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11 12#include <linux/sched.h> 13#include <linux/mm.h> 14#include <linux/smp.h> 15#include <linux/kernel.h> 16#include <linux/signal.h> 17#include <linux/errno.h> 18#include <linux/wait.h> 19#include <linux/ptrace.h> 20#include <linux/unistd.h> 21#include <linux/stddef.h> 22#include <linux/tty.h> 23#include <linux/personality.h> 24#include <linux/suspend.h> 25#include <linux/tracehook.h> 26#include <asm/cacheflush.h> 27#include <asm/ucontext.h> 28#include <asm/uaccess.h> 29#include <asm/fpu.h> 30#include "sigframe.h" 31 32#define DEBUG_SIG 0 33 34/* 35 * do a signal return; undo the signal stack. 36 */ 37static int restore_sigcontext(struct pt_regs *regs, 38 struct sigcontext __user *sc, long *_d0) 39{ 40 unsigned int err = 0; 41 42 /* Always make any pending restarted system calls return -EINTR */ 43 current->restart_block.fn = do_no_restart_syscall; 44 45 if (is_using_fpu(current)) 46 fpu_kill_state(current); 47 48#define COPY(x) err |= __get_user(regs->x, &sc->x) 49 COPY(d1); COPY(d2); COPY(d3); 50 COPY(a0); COPY(a1); COPY(a2); COPY(a3); 51 COPY(e0); COPY(e1); COPY(e2); COPY(e3); 52 COPY(e4); COPY(e5); COPY(e6); COPY(e7); 53 COPY(lar); COPY(lir); 54 COPY(mdr); COPY(mdrq); 55 COPY(mcvf); COPY(mcrl); COPY(mcrh); 56 COPY(sp); COPY(pc); 57#undef COPY 58 59 { 60 unsigned int tmpflags; 61#ifndef CONFIG_MN10300_USING_JTAG 62#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \ 63 EPSW_T | EPSW_nAR) 64#else 65#define USER_EPSW (EPSW_FLAG_Z | EPSW_FLAG_N | EPSW_FLAG_C | EPSW_FLAG_V | \ 66 EPSW_nAR) 67#endif 68 err |= __get_user(tmpflags, &sc->epsw); 69 regs->epsw = (regs->epsw & ~USER_EPSW) | 70 (tmpflags & USER_EPSW); 71 regs->orig_d0 = -1; /* disable syscall checks */ 72 } 73 74 { 75 struct fpucontext *buf; 76 err |= __get_user(buf, &sc->fpucontext); 77 if (buf) { 78 if (verify_area(VERIFY_READ, buf, sizeof(*buf))) 79 goto badframe; 80 err |= fpu_restore_sigcontext(buf); 81 } 82 } 83 84 err |= __get_user(*_d0, &sc->d0); 85 return err; 86 87badframe: 88 return 1; 89} 90 91/* 92 * standard signal return syscall 93 */ 94asmlinkage long sys_sigreturn(void) 95{ 96 struct sigframe __user *frame; 97 sigset_t set; 98 long d0; 99 100 frame = (struct sigframe __user *) current_frame()->sp; 101 if (verify_area(VERIFY_READ, frame, sizeof(*frame))) 102 goto badframe; 103 if (__get_user(set.sig[0], &frame->sc.oldmask)) 104 goto badframe; 105 106 if (_NSIG_WORDS > 1 && 107 __copy_from_user(&set.sig[1], &frame->extramask, 108 sizeof(frame->extramask))) 109 goto badframe; 110 111 set_current_blocked(&set); 112 113 if (restore_sigcontext(current_frame(), &frame->sc, &d0)) 114 goto badframe; 115 116 return d0; 117 118badframe: 119 force_sig(SIGSEGV, current); 120 return 0; 121} 122 123/* 124 * realtime signal return syscall 125 */ 126asmlinkage long sys_rt_sigreturn(void) 127{ 128 struct rt_sigframe __user *frame; 129 sigset_t set; 130 long d0; 131 132 frame = (struct rt_sigframe __user *) current_frame()->sp; 133 if (verify_area(VERIFY_READ, frame, sizeof(*frame))) 134 goto badframe; 135 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 136 goto badframe; 137 138 set_current_blocked(&set); 139 140 if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0)) 141 goto badframe; 142 143 if (restore_altstack(&frame->uc.uc_stack)) 144 goto badframe; 145 146 return d0; 147 148badframe: 149 force_sig(SIGSEGV, current); 150 return 0; 151} 152 153/* 154 * store the userspace context into a signal frame 155 */ 156static int setup_sigcontext(struct sigcontext __user *sc, 157 struct fpucontext *fpuctx, 158 struct pt_regs *regs, 159 unsigned long mask) 160{ 161 int tmp, err = 0; 162 163#define COPY(x) err |= __put_user(regs->x, &sc->x) 164 COPY(d0); COPY(d1); COPY(d2); COPY(d3); 165 COPY(a0); COPY(a1); COPY(a2); COPY(a3); 166 COPY(e0); COPY(e1); COPY(e2); COPY(e3); 167 COPY(e4); COPY(e5); COPY(e6); COPY(e7); 168 COPY(lar); COPY(lir); 169 COPY(mdr); COPY(mdrq); 170 COPY(mcvf); COPY(mcrl); COPY(mcrh); 171 COPY(sp); COPY(epsw); COPY(pc); 172#undef COPY 173 174 tmp = fpu_setup_sigcontext(fpuctx); 175 if (tmp < 0) 176 err = 1; 177 else 178 err |= __put_user(tmp ? fpuctx : NULL, &sc->fpucontext); 179 180 /* non-iBCS2 extensions.. */ 181 err |= __put_user(mask, &sc->oldmask); 182 183 return err; 184} 185 186/* 187 * determine which stack to use.. 188 */ 189static inline void __user *get_sigframe(struct ksignal *ksig, 190 struct pt_regs *regs, 191 size_t frame_size) 192{ 193 unsigned long sp = sigsp(regs->sp, ksig); 194 195 return (void __user *) ((sp - frame_size) & ~7UL); 196} 197 198/* 199 * set up a normal signal frame 200 */ 201static int setup_frame(struct ksignal *ksig, sigset_t *set, 202 struct pt_regs *regs) 203{ 204 struct sigframe __user *frame; 205 int sig = ksig->sig; 206 207 frame = get_sigframe(ksig, regs, sizeof(*frame)); 208 209 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 210 return -EFAULT; 211 212 if (__put_user(sig, &frame->sig) < 0 || 213 __put_user(&frame->sc, &frame->psc) < 0) 214 return -EFAULT; 215 216 if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0])) 217 return -EFAULT; 218 219 if (_NSIG_WORDS > 1) { 220 if (__copy_to_user(frame->extramask, &set->sig[1], 221 sizeof(frame->extramask))) 222 return -EFAULT; 223 } 224 225 /* set up to return from userspace. If provided, use a stub already in 226 * userspace */ 227 if (ksig->ka.sa.sa_flags & SA_RESTORER) { 228 if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode)) 229 return -EFAULT; 230 } else { 231 if (__put_user((void (*)(void))frame->retcode, 232 &frame->pretcode)) 233 return -EFAULT; 234 /* this is mov $,d0; syscall 0 */ 235 if (__put_user(0x2c, (char *)(frame->retcode + 0)) || 236 __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) || 237 __put_user(0x00, (char *)(frame->retcode + 2)) || 238 __put_user(0xf0, (char *)(frame->retcode + 3)) || 239 __put_user(0xe0, (char *)(frame->retcode + 4))) 240 return -EFAULT; 241 flush_icache_range((unsigned long) frame->retcode, 242 (unsigned long) frame->retcode + 5); 243 } 244 245 /* set up registers for signal handler */ 246 regs->sp = (unsigned long) frame; 247 regs->pc = (unsigned long) ksig->ka.sa.sa_handler; 248 regs->d0 = sig; 249 regs->d1 = (unsigned long) &frame->sc; 250 251#if DEBUG_SIG 252 printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", 253 sig, current->comm, current->pid, frame, regs->pc, 254 frame->pretcode); 255#endif 256 257 return 0; 258} 259 260/* 261 * set up a realtime signal frame 262 */ 263static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, 264 struct pt_regs *regs) 265{ 266 struct rt_sigframe __user *frame; 267 int sig = ksig->sig; 268 269 frame = get_sigframe(ksig, regs, sizeof(*frame)); 270 271 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 272 return -EFAULT; 273 274 if (__put_user(sig, &frame->sig) || 275 __put_user(&frame->info, &frame->pinfo) || 276 __put_user(&frame->uc, &frame->puc) || 277 copy_siginfo_to_user(&frame->info, &ksig->info)) 278 return -EFAULT; 279 280 /* create the ucontext. */ 281 if (__put_user(0, &frame->uc.uc_flags) || 282 __put_user(0, &frame->uc.uc_link) || 283 __save_altstack(&frame->uc.uc_stack, regs->sp) || 284 setup_sigcontext(&frame->uc.uc_mcontext, 285 &frame->fpuctx, regs, set->sig[0]) || 286 __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) 287 return -EFAULT; 288 289 /* set up to return from userspace. If provided, use a stub already in 290 * userspace */ 291 if (ksig->ka.sa.sa_flags & SA_RESTORER) { 292 if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode)) 293 return -EFAULT; 294 295 } else { 296 if (__put_user((void(*)(void))frame->retcode, 297 &frame->pretcode) || 298 /* This is mov $,d0; syscall 0 */ 299 __put_user(0x2c, (char *)(frame->retcode + 0)) || 300 __put_user(__NR_rt_sigreturn, 301 (char *)(frame->retcode + 1)) || 302 __put_user(0x00, (char *)(frame->retcode + 2)) || 303 __put_user(0xf0, (char *)(frame->retcode + 3)) || 304 __put_user(0xe0, (char *)(frame->retcode + 4))) 305 return -EFAULT; 306 307 flush_icache_range((u_long) frame->retcode, 308 (u_long) frame->retcode + 5); 309 } 310 311 /* Set up registers for signal handler */ 312 regs->sp = (unsigned long) frame; 313 regs->pc = (unsigned long) ksig->ka.sa.sa_handler; 314 regs->d0 = sig; 315 regs->d1 = (long) &frame->info; 316 317#if DEBUG_SIG 318 printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", 319 sig, current->comm, current->pid, frame, regs->pc, 320 frame->pretcode); 321#endif 322 323 return 0; 324} 325 326static inline void stepback(struct pt_regs *regs) 327{ 328 regs->pc -= 2; 329 regs->orig_d0 = -1; 330} 331 332/* 333 * handle the actual delivery of a signal to userspace 334 */ 335static int handle_signal(struct ksignal *ksig, struct pt_regs *regs) 336{ 337 sigset_t *oldset = sigmask_to_save(); 338 int ret; 339 340 /* Are we from a system call? */ 341 if (regs->orig_d0 >= 0) { 342 /* If so, check system call restarting.. */ 343 switch (regs->d0) { 344 case -ERESTART_RESTARTBLOCK: 345 case -ERESTARTNOHAND: 346 regs->d0 = -EINTR; 347 break; 348 349 case -ERESTARTSYS: 350 if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 351 regs->d0 = -EINTR; 352 break; 353 } 354 355 /* fallthrough */ 356 case -ERESTARTNOINTR: 357 regs->d0 = regs->orig_d0; 358 stepback(regs); 359 } 360 } 361 362 /* Set up the stack frame */ 363 if (ksig->ka.sa.sa_flags & SA_SIGINFO) 364 ret = setup_rt_frame(ksig, oldset, regs); 365 else 366 ret = setup_frame(ksig, oldset, regs); 367 368 signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); 369 return 0; 370} 371 372/* 373 * handle a potential signal 374 */ 375static void do_signal(struct pt_regs *regs) 376{ 377 struct ksignal ksig; 378 379 if (get_signal(&ksig)) { 380 handle_signal(&ksig, regs); 381 return; 382 } 383 384 /* did we come from a system call? */ 385 if (regs->orig_d0 >= 0) { 386 /* restart the system call - no handlers present */ 387 switch (regs->d0) { 388 case -ERESTARTNOHAND: 389 case -ERESTARTSYS: 390 case -ERESTARTNOINTR: 391 regs->d0 = regs->orig_d0; 392 stepback(regs); 393 break; 394 395 case -ERESTART_RESTARTBLOCK: 396 regs->d0 = __NR_restart_syscall; 397 stepback(regs); 398 break; 399 } 400 } 401 402 /* if there's no signal to deliver, we just put the saved sigmask 403 * back */ 404 restore_saved_sigmask(); 405} 406 407/* 408 * notification of userspace execution resumption 409 * - triggered by current->work.notify_resume 410 */ 411asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) 412{ 413 /* Pending single-step? */ 414 if (thread_info_flags & _TIF_SINGLESTEP) { 415#ifndef CONFIG_MN10300_USING_JTAG 416 regs->epsw |= EPSW_T; 417 clear_thread_flag(TIF_SINGLESTEP); 418#else 419 BUG(); /* no h/w single-step if using JTAG unit */ 420#endif 421 } 422 423 /* deal with pending signal delivery */ 424 if (thread_info_flags & _TIF_SIGPENDING) 425 do_signal(regs); 426 427 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 428 clear_thread_flag(TIF_NOTIFY_RESUME); 429 tracehook_notify_resume(current_frame()); 430 } 431} 432