1/* 2 * Port on Texas Instruments TMS320C6x architecture 3 * 4 * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated 5 * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) 6 * 7 * Updated for 2.6.34: Mark Salter <msalter@redhat.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 */ 13 14#include <linux/kernel.h> 15#include <linux/uaccess.h> 16#include <linux/syscalls.h> 17#include <linux/tracehook.h> 18 19#include <asm/ucontext.h> 20#include <asm/cacheflush.h> 21 22 23/* 24 * Do a signal return, undo the signal stack. 25 */ 26 27#define RETCODE_SIZE (9 << 2) /* 9 instructions = 36 bytes */ 28 29struct rt_sigframe { 30 struct siginfo __user *pinfo; 31 void __user *puc; 32 struct siginfo info; 33 struct ucontext uc; 34 unsigned long retcode[RETCODE_SIZE >> 2]; 35}; 36 37static int restore_sigcontext(struct pt_regs *regs, 38 struct sigcontext __user *sc) 39{ 40 int err = 0; 41 42 /* The access_ok check was done by caller, so use __get_user here */ 43#define COPY(x) (err |= __get_user(regs->x, &sc->sc_##x)) 44 45 COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8); 46 COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9); 47 COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9); 48 49 COPY(a16); COPY(a17); COPY(a18); COPY(a19); 50 COPY(a20); COPY(a21); COPY(a22); COPY(a23); 51 COPY(a24); COPY(a25); COPY(a26); COPY(a27); 52 COPY(a28); COPY(a29); COPY(a30); COPY(a31); 53 COPY(b16); COPY(b17); COPY(b18); COPY(b19); 54 COPY(b20); COPY(b21); COPY(b22); COPY(b23); 55 COPY(b24); COPY(b25); COPY(b26); COPY(b27); 56 COPY(b28); COPY(b29); COPY(b30); COPY(b31); 57 58 COPY(csr); COPY(pc); 59 60#undef COPY 61 62 return err; 63} 64 65asmlinkage int do_rt_sigreturn(struct pt_regs *regs) 66{ 67 struct rt_sigframe __user *frame; 68 sigset_t set; 69 70 /* Always make any pending restarted system calls return -EINTR */ 71 current->restart_block.fn = do_no_restart_syscall; 72 73 /* 74 * Since we stacked the signal on a dword boundary, 75 * 'sp' should be dword aligned here. If it's 76 * not, then the user is trying to mess with us. 77 */ 78 if (regs->sp & 7) 79 goto badframe; 80 81 frame = (struct rt_sigframe __user *) ((unsigned long) regs->sp + 8); 82 83 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 84 goto badframe; 85 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 86 goto badframe; 87 88 set_current_blocked(&set); 89 90 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 91 goto badframe; 92 93 return regs->a4; 94 95badframe: 96 force_sig(SIGSEGV, current); 97 return 0; 98} 99 100static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, 101 unsigned long mask) 102{ 103 int err = 0; 104 105 err |= __put_user(mask, &sc->sc_mask); 106 107 /* The access_ok check was done by caller, so use __put_user here */ 108#define COPY(x) (err |= __put_user(regs->x, &sc->sc_##x)) 109 110 COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8); 111 COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9); 112 COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9); 113 114 COPY(a16); COPY(a17); COPY(a18); COPY(a19); 115 COPY(a20); COPY(a21); COPY(a22); COPY(a23); 116 COPY(a24); COPY(a25); COPY(a26); COPY(a27); 117 COPY(a28); COPY(a29); COPY(a30); COPY(a31); 118 COPY(b16); COPY(b17); COPY(b18); COPY(b19); 119 COPY(b20); COPY(b21); COPY(b22); COPY(b23); 120 COPY(b24); COPY(b25); COPY(b26); COPY(b27); 121 COPY(b28); COPY(b29); COPY(b30); COPY(b31); 122 123 COPY(csr); COPY(pc); 124 125#undef COPY 126 127 return err; 128} 129 130static inline void __user *get_sigframe(struct ksignal *ksig, 131 struct pt_regs *regs, 132 unsigned long framesize) 133{ 134 unsigned long sp = sigsp(regs->sp, ksig); 135 136 /* 137 * No matter what happens, 'sp' must be dword 138 * aligned. Otherwise, nasty things will happen 139 */ 140 return (void __user *)((sp - framesize) & ~7); 141} 142 143static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, 144 struct pt_regs *regs) 145{ 146 struct rt_sigframe __user *frame; 147 unsigned long __user *retcode; 148 int err = 0; 149 150 frame = get_sigframe(ksig, regs, sizeof(*frame)); 151 152 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 153 return -EFAULT; 154 155 err |= __put_user(&frame->info, &frame->pinfo); 156 err |= __put_user(&frame->uc, &frame->puc); 157 err |= copy_siginfo_to_user(&frame->info, &ksig->info); 158 159 /* Clear all the bits of the ucontext we don't use. */ 160 err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); 161 162 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); 163 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 164 165 /* Set up to return from userspace */ 166 retcode = (unsigned long __user *) &frame->retcode; 167 168 /* The access_ok check was done above, so use __put_user here */ 169#define COPY(x) (err |= __put_user(x, retcode++)) 170 171 COPY(0x0000002AUL | (__NR_rt_sigreturn << 7)); 172 /* MVK __NR_rt_sigreturn,B0 */ 173 COPY(0x10000000UL); /* SWE */ 174 COPY(0x00006000UL); /* NOP 4 */ 175 COPY(0x00006000UL); /* NOP 4 */ 176 COPY(0x00006000UL); /* NOP 4 */ 177 COPY(0x00006000UL); /* NOP 4 */ 178 COPY(0x00006000UL); /* NOP 4 */ 179 COPY(0x00006000UL); /* NOP 4 */ 180 COPY(0x00006000UL); /* NOP 4 */ 181 182#undef COPY 183 184 if (err) 185 return -EFAULT; 186 187 flush_icache_range((unsigned long) &frame->retcode, 188 (unsigned long) &frame->retcode + RETCODE_SIZE); 189 190 retcode = (unsigned long __user *) &frame->retcode; 191 192 /* Change user context to branch to signal handler */ 193 regs->sp = (unsigned long) frame - 8; 194 regs->b3 = (unsigned long) retcode; 195 regs->pc = (unsigned long) ksig->ka.sa.sa_handler; 196 197 /* Give the signal number to the handler */ 198 regs->a4 = ksig->sig; 199 200 /* 201 * For realtime signals we must also set the second and third 202 * arguments for the signal handler. 203 * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06 204 */ 205 regs->b4 = (unsigned long)&frame->info; 206 regs->a6 = (unsigned long)&frame->uc; 207 208 return 0; 209} 210 211static inline void 212handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) 213{ 214 switch (regs->a4) { 215 case -ERESTARTNOHAND: 216 if (!has_handler) 217 goto do_restart; 218 regs->a4 = -EINTR; 219 break; 220 221 case -ERESTARTSYS: 222 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { 223 regs->a4 = -EINTR; 224 break; 225 } 226 /* fallthrough */ 227 case -ERESTARTNOINTR: 228do_restart: 229 regs->a4 = regs->orig_a4; 230 regs->pc -= 4; 231 break; 232 } 233} 234 235/* 236 * handle the actual delivery of a signal to userspace 237 */ 238static void handle_signal(struct ksignal *ksig, struct pt_regs *regs, 239 int syscall) 240{ 241 int ret; 242 243 /* Are we from a system call? */ 244 if (syscall) { 245 /* If so, check system call restarting.. */ 246 switch (regs->a4) { 247 case -ERESTART_RESTARTBLOCK: 248 case -ERESTARTNOHAND: 249 regs->a4 = -EINTR; 250 break; 251 252 case -ERESTARTSYS: 253 if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 254 regs->a4 = -EINTR; 255 break; 256 } 257 258 /* fallthrough */ 259 case -ERESTARTNOINTR: 260 regs->a4 = regs->orig_a4; 261 regs->pc -= 4; 262 } 263 } 264 265 /* Set up the stack frame */ 266 ret = setup_rt_frame(ksig, sigmask_to_save(), regs); 267 signal_setup_done(ret, ksig, 0); 268} 269 270/* 271 * handle a potential signal 272 */ 273static void do_signal(struct pt_regs *regs, int syscall) 274{ 275 struct ksignal ksig; 276 277 /* we want the common case to go fast, which is why we may in certain 278 * cases get here from kernel mode */ 279 if (!user_mode(regs)) 280 return; 281 282 if (get_signal(&ksig)) { 283 handle_signal(&ksig, regs, syscall); 284 return; 285 } 286 287 /* did we come from a system call? */ 288 if (syscall) { 289 /* restart the system call - no handlers present */ 290 switch (regs->a4) { 291 case -ERESTARTNOHAND: 292 case -ERESTARTSYS: 293 case -ERESTARTNOINTR: 294 regs->a4 = regs->orig_a4; 295 regs->pc -= 4; 296 break; 297 298 case -ERESTART_RESTARTBLOCK: 299 regs->a4 = regs->orig_a4; 300 regs->b0 = __NR_restart_syscall; 301 regs->pc -= 4; 302 break; 303 } 304 } 305 306 /* if there's no signal to deliver, we just put the saved sigmask 307 * back */ 308 restore_saved_sigmask(); 309} 310 311/* 312 * notification of userspace execution resumption 313 * - triggered by current->work.notify_resume 314 */ 315asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags, 316 int syscall) 317{ 318 /* deal with pending signal delivery */ 319 if (thread_info_flags & (1 << TIF_SIGPENDING)) 320 do_signal(regs, syscall); 321 322 if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) { 323 clear_thread_flag(TIF_NOTIFY_RESUME); 324 tracehook_notify_resume(regs); 325 } 326} 327