Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nds32: Signal handling support

This patch adds support for signal handling.

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>

+384
+60
arch/nds32/include/uapi/asm/sigcontext.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2005-2017 Andes Technology Corporation 3 + 4 + #ifndef _ASMNDS32_SIGCONTEXT_H 5 + #define _ASMNDS32_SIGCONTEXT_H 6 + 7 + /* 8 + * Signal context structure - contains all info to do with the state 9 + * before the signal handler was invoked. Note: only add new entries 10 + * to the end of the structure. 11 + */ 12 + 13 + struct zol_struct { 14 + unsigned long nds32_lc; /* $LC */ 15 + unsigned long nds32_le; /* $LE */ 16 + unsigned long nds32_lb; /* $LB */ 17 + }; 18 + 19 + struct sigcontext { 20 + unsigned long trap_no; 21 + unsigned long error_code; 22 + unsigned long oldmask; 23 + unsigned long nds32_r0; 24 + unsigned long nds32_r1; 25 + unsigned long nds32_r2; 26 + unsigned long nds32_r3; 27 + unsigned long nds32_r4; 28 + unsigned long nds32_r5; 29 + unsigned long nds32_r6; 30 + unsigned long nds32_r7; 31 + unsigned long nds32_r8; 32 + unsigned long nds32_r9; 33 + unsigned long nds32_r10; 34 + unsigned long nds32_r11; 35 + unsigned long nds32_r12; 36 + unsigned long nds32_r13; 37 + unsigned long nds32_r14; 38 + unsigned long nds32_r15; 39 + unsigned long nds32_r16; 40 + unsigned long nds32_r17; 41 + unsigned long nds32_r18; 42 + unsigned long nds32_r19; 43 + unsigned long nds32_r20; 44 + unsigned long nds32_r21; 45 + unsigned long nds32_r22; 46 + unsigned long nds32_r23; 47 + unsigned long nds32_r24; 48 + unsigned long nds32_r25; 49 + unsigned long nds32_fp; /* $r28 */ 50 + unsigned long nds32_gp; /* $r29 */ 51 + unsigned long nds32_lp; /* $r30 */ 52 + unsigned long nds32_sp; /* $r31 */ 53 + unsigned long nds32_ipc; 54 + unsigned long fault_address; 55 + unsigned long used_math_flag; 56 + /* FPU Registers */ 57 + struct zol_struct zol; 58 + }; 59 + 60 + #endif
+324
arch/nds32/kernel/signal.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2005-2017 Andes Technology Corporation 3 + 4 + #include <linux/errno.h> 5 + #include <linux/signal.h> 6 + #include <linux/ptrace.h> 7 + #include <linux/personality.h> 8 + #include <linux/freezer.h> 9 + #include <linux/tracehook.h> 10 + #include <linux/uaccess.h> 11 + 12 + #include <asm/cacheflush.h> 13 + #include <asm/ucontext.h> 14 + #include <asm/unistd.h> 15 + 16 + #include <asm/ptrace.h> 17 + #include <asm/vdso.h> 18 + 19 + struct rt_sigframe { 20 + struct siginfo info; 21 + struct ucontext uc; 22 + }; 23 + 24 + static int restore_sigframe(struct pt_regs *regs, 25 + struct rt_sigframe __user * sf) 26 + { 27 + sigset_t set; 28 + int err; 29 + 30 + err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); 31 + if (err == 0) { 32 + set_current_blocked(&set); 33 + } 34 + 35 + __get_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err); 36 + __get_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err); 37 + __get_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err); 38 + __get_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err); 39 + __get_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err); 40 + __get_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err); 41 + __get_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err); 42 + __get_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err); 43 + __get_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err); 44 + __get_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err); 45 + __get_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err); 46 + __get_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err); 47 + __get_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err); 48 + __get_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err); 49 + __get_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err); 50 + __get_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err); 51 + __get_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err); 52 + __get_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err); 53 + __get_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err); 54 + __get_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err); 55 + __get_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err); 56 + __get_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err); 57 + __get_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err); 58 + __get_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err); 59 + __get_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err); 60 + __get_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err); 61 + 62 + __get_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err); 63 + __get_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err); 64 + __get_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err); 65 + __get_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err); 66 + __get_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err); 67 + #if defined(CONFIG_HWZOL) 68 + __get_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err); 69 + __get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err); 70 + __get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err); 71 + #endif 72 + 73 + /* 74 + * Avoid sys_rt_sigreturn() restarting. 75 + */ 76 + forget_syscall(regs); 77 + return err; 78 + } 79 + 80 + asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) 81 + { 82 + struct rt_sigframe __user *frame; 83 + 84 + /* Always make any pending restarted system calls return -EINTR */ 85 + current->restart_block.fn = do_no_restart_syscall; 86 + 87 + /* 88 + * Since we stacked the signal on a 64-bit boundary, 89 + * then 'sp' should be two-word aligned here. If it's 90 + * not, then the user is trying to mess with us. 91 + */ 92 + if (regs->sp & 7) 93 + goto badframe; 94 + 95 + frame = (struct rt_sigframe __user *)regs->sp; 96 + 97 + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 98 + goto badframe; 99 + 100 + if (restore_sigframe(regs, frame)) 101 + goto badframe; 102 + 103 + if (restore_altstack(&frame->uc.uc_stack)) 104 + goto badframe; 105 + 106 + return regs->uregs[0]; 107 + 108 + badframe: 109 + force_sig(SIGSEGV, current); 110 + return 0; 111 + } 112 + 113 + static int 114 + setup_sigframe(struct rt_sigframe __user * sf, struct pt_regs *regs, 115 + sigset_t * set) 116 + { 117 + int err = 0; 118 + 119 + __put_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err); 120 + __put_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err); 121 + __put_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err); 122 + __put_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err); 123 + __put_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err); 124 + __put_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err); 125 + __put_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err); 126 + __put_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err); 127 + __put_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err); 128 + __put_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err); 129 + __put_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err); 130 + __put_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err); 131 + __put_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err); 132 + __put_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err); 133 + __put_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err); 134 + __put_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err); 135 + __put_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err); 136 + __put_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err); 137 + __put_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err); 138 + __put_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err); 139 + __put_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err); 140 + 141 + __put_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err); 142 + __put_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err); 143 + __put_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err); 144 + __put_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err); 145 + __put_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err); 146 + __put_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err); 147 + __put_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err); 148 + __put_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err); 149 + __put_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err); 150 + __put_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err); 151 + #if defined(CONFIG_HWZOL) 152 + __put_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err); 153 + __put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err); 154 + __put_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err); 155 + #endif 156 + 157 + __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, 158 + err); 159 + __put_user_error(current->thread.error_code, 160 + &sf->uc.uc_mcontext.error_code, err); 161 + __put_user_error(current->thread.address, 162 + &sf->uc.uc_mcontext.fault_address, err); 163 + __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err); 164 + 165 + err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); 166 + 167 + return err; 168 + } 169 + 170 + static inline void __user *get_sigframe(struct ksignal *ksig, 171 + struct pt_regs *regs, int framesize) 172 + { 173 + unsigned long sp; 174 + 175 + /* Default to using normal stack */ 176 + sp = regs->sp; 177 + 178 + /* 179 + * If we are on the alternate signal stack and would overflow it, don't. 180 + * Return an always-bogus address instead so we will die with SIGSEGV. 181 + */ 182 + if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) 183 + return (void __user __force *)(-1UL); 184 + 185 + /* This is the X/Open sanctioned signal stack switching. */ 186 + sp = (sigsp(sp, ksig) - framesize); 187 + 188 + /* 189 + * nds32 mandates 8-byte alignment 190 + */ 191 + sp &= ~0x7UL; 192 + 193 + return (void __user *)sp; 194 + } 195 + 196 + static int 197 + setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame) 198 + { 199 + unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler; 200 + unsigned long retcode; 201 + 202 + retcode = VDSO_SYMBOL(current->mm->context.vdso, rt_sigtramp); 203 + regs->uregs[0] = ksig->sig; 204 + regs->sp = (unsigned long)frame; 205 + regs->lp = retcode; 206 + regs->ipc = handler; 207 + 208 + return 0; 209 + } 210 + 211 + static int 212 + setup_rt_frame(struct ksignal *ksig, sigset_t * set, struct pt_regs *regs) 213 + { 214 + struct rt_sigframe __user *frame = 215 + get_sigframe(ksig, regs, sizeof(*frame)); 216 + int err = 0; 217 + 218 + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 219 + return -EFAULT; 220 + 221 + __put_user_error(0, &frame->uc.uc_flags, err); 222 + __put_user_error(NULL, &frame->uc.uc_link, err); 223 + 224 + err |= __save_altstack(&frame->uc.uc_stack, regs->sp); 225 + err |= setup_sigframe(frame, regs, set); 226 + if (err == 0) { 227 + setup_return(regs, ksig, frame); 228 + if (ksig->ka.sa.sa_flags & SA_SIGINFO) { 229 + err |= copy_siginfo_to_user(&frame->info, &ksig->info); 230 + regs->uregs[1] = (unsigned long)&frame->info; 231 + regs->uregs[2] = (unsigned long)&frame->uc; 232 + } 233 + } 234 + return err; 235 + } 236 + 237 + /* 238 + * OK, we're invoking a handler 239 + */ 240 + static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 241 + { 242 + int ret; 243 + sigset_t *oldset = sigmask_to_save(); 244 + 245 + if (in_syscall(regs)) { 246 + /* Avoid additional syscall restarting via ret_slow_syscall. */ 247 + forget_syscall(regs); 248 + 249 + switch (regs->uregs[0]) { 250 + case -ERESTART_RESTARTBLOCK: 251 + case -ERESTARTNOHAND: 252 + regs->uregs[0] = -EINTR; 253 + break; 254 + case -ERESTARTSYS: 255 + if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 256 + regs->uregs[0] = -EINTR; 257 + break; 258 + } 259 + case -ERESTARTNOINTR: 260 + regs->uregs[0] = regs->orig_r0; 261 + regs->ipc -= 4; 262 + break; 263 + } 264 + } 265 + /* 266 + * Set up the stack frame 267 + */ 268 + ret = setup_rt_frame(ksig, oldset, regs); 269 + 270 + signal_setup_done(ret, ksig, 0); 271 + } 272 + 273 + /* 274 + * Note that 'init' is a special process: it doesn't get signals it doesn't 275 + * want to handle. Thus you cannot kill init even with a SIGKILL even by 276 + * mistake. 277 + * 278 + * Note that we go through the signals twice: once to check the signals that 279 + * the kernel can handle, and then we build all the user-level signal handling 280 + * stack-frames in one go after that. 281 + */ 282 + static void do_signal(struct pt_regs *regs) 283 + { 284 + struct ksignal ksig; 285 + 286 + if (get_signal(&ksig)) { 287 + handle_signal(&ksig, regs); 288 + return; 289 + } 290 + 291 + /* 292 + * If we were from a system call, check for system call restarting... 293 + */ 294 + if (in_syscall(regs)) { 295 + /* Restart the system call - no handlers present */ 296 + 297 + /* Avoid additional syscall restarting via ret_slow_syscall. */ 298 + forget_syscall(regs); 299 + 300 + switch (regs->uregs[0]) { 301 + case -ERESTART_RESTARTBLOCK: 302 + regs->uregs[15] = __NR_restart_syscall; 303 + case -ERESTARTNOHAND: 304 + case -ERESTARTSYS: 305 + case -ERESTARTNOINTR: 306 + regs->uregs[0] = regs->orig_r0; 307 + regs->ipc -= 0x4; 308 + break; 309 + } 310 + } 311 + restore_saved_sigmask(); 312 + } 313 + 314 + asmlinkage void 315 + do_notify_resume(struct pt_regs *regs, unsigned int thread_flags) 316 + { 317 + if (thread_flags & _TIF_SIGPENDING) 318 + do_signal(regs); 319 + 320 + if (thread_flags & _TIF_NOTIFY_RESUME) { 321 + clear_thread_flag(TIF_NOTIFY_RESUME); 322 + tracehook_notify_resume(regs); 323 + } 324 + }