1/* 2 * arch/score/kernel/signal.c 3 * 4 * Score Processor version. 5 * 6 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd. 7 * Chen Liqin <liqin.chen@sunplusct.com> 8 * Lennox Wu <lennox.wu@sunplusct.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, see the file COPYING, or write 22 * to the Free Software Foundation, Inc., 23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 */ 25 26#include <linux/errno.h> 27#include <linux/signal.h> 28#include <linux/ptrace.h> 29#include <linux/unistd.h> 30#include <linux/uaccess.h> 31#include <linux/tracehook.h> 32 33#include <asm/cacheflush.h> 34#include <asm/syscalls.h> 35#include <asm/ucontext.h> 36 37struct rt_sigframe { 38 u32 rs_ass[4]; /* argument save space */ 39 u32 rs_code[2]; /* signal trampoline */ 40 struct siginfo rs_info; 41 struct ucontext rs_uc; 42}; 43 44static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) 45{ 46 int err = 0; 47 unsigned long reg; 48 49 reg = regs->cp0_epc; err |= __put_user(reg, &sc->sc_pc); 50 err |= __put_user(regs->cp0_psr, &sc->sc_psr); 51 err |= __put_user(regs->cp0_condition, &sc->sc_condition); 52 53 54#define save_gp_reg(i) { \ 55 reg = regs->regs[i]; \ 56 err |= __put_user(reg, &sc->sc_regs[i]); \ 57} while (0) 58 save_gp_reg(0); save_gp_reg(1); save_gp_reg(2); 59 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); 60 save_gp_reg(6); save_gp_reg(7); save_gp_reg(8); 61 save_gp_reg(9); save_gp_reg(10); save_gp_reg(11); 62 save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); 63 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); 64 save_gp_reg(18); save_gp_reg(19); save_gp_reg(20); 65 save_gp_reg(21); save_gp_reg(22); save_gp_reg(23); 66 save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); 67 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); 68#undef save_gp_reg 69 70 reg = regs->ceh; err |= __put_user(reg, &sc->sc_mdceh); 71 reg = regs->cel; err |= __put_user(reg, &sc->sc_mdcel); 72 err |= __put_user(regs->cp0_ecr, &sc->sc_ecr); 73 err |= __put_user(regs->cp0_ema, &sc->sc_ema); 74 75 return err; 76} 77 78static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) 79{ 80 int err = 0; 81 u32 reg; 82 83 err |= __get_user(regs->cp0_epc, &sc->sc_pc); 84 err |= __get_user(regs->cp0_condition, &sc->sc_condition); 85 86 err |= __get_user(reg, &sc->sc_mdceh); 87 regs->ceh = (int) reg; 88 err |= __get_user(reg, &sc->sc_mdcel); 89 regs->cel = (int) reg; 90 91 err |= __get_user(reg, &sc->sc_psr); 92 regs->cp0_psr = (int) reg; 93 err |= __get_user(reg, &sc->sc_ecr); 94 regs->cp0_ecr = (int) reg; 95 err |= __get_user(reg, &sc->sc_ema); 96 regs->cp0_ema = (int) reg; 97 98#define restore_gp_reg(i) do { \ 99 err |= __get_user(reg, &sc->sc_regs[i]); \ 100 regs->regs[i] = reg; \ 101} while (0) 102 restore_gp_reg(0); restore_gp_reg(1); restore_gp_reg(2); 103 restore_gp_reg(3); restore_gp_reg(4); restore_gp_reg(5); 104 restore_gp_reg(6); restore_gp_reg(7); restore_gp_reg(8); 105 restore_gp_reg(9); restore_gp_reg(10); restore_gp_reg(11); 106 restore_gp_reg(12); restore_gp_reg(13); restore_gp_reg(14); 107 restore_gp_reg(15); restore_gp_reg(16); restore_gp_reg(17); 108 restore_gp_reg(18); restore_gp_reg(19); restore_gp_reg(20); 109 restore_gp_reg(21); restore_gp_reg(22); restore_gp_reg(23); 110 restore_gp_reg(24); restore_gp_reg(25); restore_gp_reg(26); 111 restore_gp_reg(27); restore_gp_reg(28); restore_gp_reg(29); 112#undef restore_gp_reg 113 114 return err; 115} 116 117/* 118 * Determine which stack to use.. 119 */ 120static void __user *get_sigframe(struct k_sigaction *ka, 121 struct pt_regs *regs, size_t frame_size) 122{ 123 unsigned long sp; 124 125 /* Default to using normal stack */ 126 sp = regs->regs[0]; 127 sp -= 32; 128 129 /* This is the X/Open sanctioned signal stack switching. */ 130 if ((ka->sa.sa_flags & SA_ONSTACK) && (!on_sig_stack(sp))) 131 sp = current->sas_ss_sp + current->sas_ss_size; 132 133 return (void __user*)((sp - frame_size) & ~7); 134} 135 136asmlinkage long 137score_rt_sigreturn(struct pt_regs *regs) 138{ 139 struct rt_sigframe __user *frame; 140 sigset_t set; 141 int sig; 142 143 /* Always make any pending restarted system calls return -EINTR */ 144 current->restart_block.fn = do_no_restart_syscall; 145 146 frame = (struct rt_sigframe __user *) regs->regs[0]; 147 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 148 goto badframe; 149 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) 150 goto badframe; 151 152 set_current_blocked(&set); 153 154 sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); 155 if (sig < 0) 156 goto badframe; 157 else if (sig) 158 force_sig(sig, current); 159 160 if (restore_altstack(&frame->rs_uc.uc_stack)) 161 goto badframe; 162 regs->is_syscall = 0; 163 164 __asm__ __volatile__( 165 "mv\tr0, %0\n\t" 166 "la\tr8, syscall_exit\n\t" 167 "br\tr8\n\t" 168 : : "r" (regs) : "r8"); 169 170badframe: 171 force_sig(SIGSEGV, current); 172 173 return 0; 174} 175 176static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs, 177 sigset_t *set) 178{ 179 struct rt_sigframe __user *frame; 180 int err = 0; 181 182 frame = get_sigframe(&ksig->ka, regs, sizeof(*frame)); 183 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 184 return -EFAULT; 185 186 /* 187 * Set up the return code ... 188 * 189 * li v0, __NR_rt_sigreturn 190 * syscall 191 */ 192 err |= __put_user(0x87788000 + __NR_rt_sigreturn*2, 193 frame->rs_code + 0); 194 err |= __put_user(0x80008002, frame->rs_code + 1); 195 flush_cache_sigtramp((unsigned long) frame->rs_code); 196 197 err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info); 198 err |= __put_user(0, &frame->rs_uc.uc_flags); 199 err |= __put_user(NULL, &frame->rs_uc.uc_link); 200 err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]); 201 err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); 202 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); 203 204 if (err) 205 return -EFAULT; 206 207 regs->regs[0] = (unsigned long) frame; 208 regs->regs[3] = (unsigned long) frame->rs_code; 209 regs->regs[4] = ksig->sig; 210 regs->regs[5] = (unsigned long) &frame->rs_info; 211 regs->regs[6] = (unsigned long) &frame->rs_uc; 212 regs->regs[29] = (unsigned long) ksig->ka.sa.sa_handler; 213 regs->cp0_epc = (unsigned long) ksig->ka.sa.sa_handler; 214 215 return 0; 216} 217 218static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 219{ 220 int ret; 221 222 if (regs->is_syscall) { 223 switch (regs->regs[4]) { 224 case ERESTART_RESTARTBLOCK: 225 case ERESTARTNOHAND: 226 regs->regs[4] = EINTR; 227 break; 228 case ERESTARTSYS: 229 if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 230 regs->regs[4] = EINTR; 231 break; 232 } 233 case ERESTARTNOINTR: 234 regs->regs[4] = regs->orig_r4; 235 regs->regs[7] = regs->orig_r7; 236 regs->cp0_epc -= 8; 237 } 238 239 regs->is_syscall = 0; 240 } 241 242 /* 243 * Set up the stack frame 244 */ 245 ret = setup_rt_frame(ksig, regs, sigmask_to_save()); 246 247 signal_setup_done(ret, ksig, 0); 248} 249 250static void do_signal(struct pt_regs *regs) 251{ 252 struct ksignal ksig; 253 254 /* 255 * We want the common case to go fast, which is why we may in certain 256 * cases get here from kernel mode. Just return without doing anything 257 * if so. 258 */ 259 if (!user_mode(regs)) 260 return; 261 262 if (get_signal(&ksig)) { 263 /* Actually deliver the signal. */ 264 handle_signal(&ksig, regs); 265 return; 266 } 267 268 if (regs->is_syscall) { 269 if (regs->regs[4] == ERESTARTNOHAND || 270 regs->regs[4] == ERESTARTSYS || 271 regs->regs[4] == ERESTARTNOINTR) { 272 regs->regs[4] = regs->orig_r4; 273 regs->regs[7] = regs->orig_r7; 274 regs->cp0_epc -= 8; 275 } 276 277 if (regs->regs[4] == ERESTART_RESTARTBLOCK) { 278 regs->regs[27] = __NR_restart_syscall; 279 regs->regs[4] = regs->orig_r4; 280 regs->regs[7] = regs->orig_r7; 281 regs->cp0_epc -= 8; 282 } 283 284 regs->is_syscall = 0; /* Don't deal with this again. */ 285 } 286 287 /* 288 * If there's no signal to deliver, we just put the saved sigmask 289 * back 290 */ 291 restore_saved_sigmask(); 292} 293 294/* 295 * notification of userspace execution resumption 296 * - triggered by the TIF_WORK_MASK flags 297 */ 298asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, 299 __u32 thread_info_flags) 300{ 301 /* deal with pending signal delivery */ 302 if (thread_info_flags & _TIF_SIGPENDING) 303 do_signal(regs); 304 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 305 clear_thread_flag(TIF_NOTIFY_RESUME); 306 tracehook_notify_resume(regs); 307 } 308} 309