18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (C) 2005-2017 Andes Technology Corporation 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/errno.h> 58c2ecf20Sopenharmony_ci#include <linux/signal.h> 68c2ecf20Sopenharmony_ci#include <linux/ptrace.h> 78c2ecf20Sopenharmony_ci#include <linux/personality.h> 88c2ecf20Sopenharmony_ci#include <linux/freezer.h> 98c2ecf20Sopenharmony_ci#include <linux/tracehook.h> 108c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 138c2ecf20Sopenharmony_ci#include <asm/ucontext.h> 148c2ecf20Sopenharmony_ci#include <asm/unistd.h> 158c2ecf20Sopenharmony_ci#include <asm/fpu.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 188c2ecf20Sopenharmony_ci#include <asm/vdso.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct rt_sigframe { 218c2ecf20Sopenharmony_ci struct siginfo info; 228c2ecf20Sopenharmony_ci struct ucontext uc; 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_FPU) 258c2ecf20Sopenharmony_cistatic inline int restore_sigcontext_fpu(struct pt_regs *regs, 268c2ecf20Sopenharmony_ci struct sigcontext __user *sc) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci struct task_struct *tsk = current; 298c2ecf20Sopenharmony_ci unsigned long used_math_flag; 308c2ecf20Sopenharmony_ci int ret = 0; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci clear_used_math(); 338c2ecf20Sopenharmony_ci __get_user_error(used_math_flag, &sc->used_math_flag, ret); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (!used_math_flag) 368c2ecf20Sopenharmony_ci return 0; 378c2ecf20Sopenharmony_ci set_used_math(); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_LAZY_FPU) 408c2ecf20Sopenharmony_ci preempt_disable(); 418c2ecf20Sopenharmony_ci if (current == last_task_used_math) { 428c2ecf20Sopenharmony_ci last_task_used_math = NULL; 438c2ecf20Sopenharmony_ci disable_ptreg_fpu(regs); 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci preempt_enable(); 468c2ecf20Sopenharmony_ci#else 478c2ecf20Sopenharmony_ci clear_fpu(regs); 488c2ecf20Sopenharmony_ci#endif 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci return __copy_from_user(&tsk->thread.fpu, &sc->fpu, 518c2ecf20Sopenharmony_ci sizeof(struct fpu_struct)); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic inline int setup_sigcontext_fpu(struct pt_regs *regs, 558c2ecf20Sopenharmony_ci struct sigcontext __user *sc) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci struct task_struct *tsk = current; 588c2ecf20Sopenharmony_ci int ret = 0; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci __put_user_error(used_math(), &sc->used_math_flag, ret); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (!used_math()) 638c2ecf20Sopenharmony_ci return ret; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci preempt_disable(); 668c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_LAZY_FPU) 678c2ecf20Sopenharmony_ci if (last_task_used_math == tsk) 688c2ecf20Sopenharmony_ci save_fpu(last_task_used_math); 698c2ecf20Sopenharmony_ci#else 708c2ecf20Sopenharmony_ci unlazy_fpu(tsk); 718c2ecf20Sopenharmony_ci#endif 728c2ecf20Sopenharmony_ci ret = __copy_to_user(&sc->fpu, &tsk->thread.fpu, 738c2ecf20Sopenharmony_ci sizeof(struct fpu_struct)); 748c2ecf20Sopenharmony_ci preempt_enable(); 758c2ecf20Sopenharmony_ci return ret; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci#endif 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int restore_sigframe(struct pt_regs *regs, 808c2ecf20Sopenharmony_ci struct rt_sigframe __user * sf) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci sigset_t set; 838c2ecf20Sopenharmony_ci int err; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); 868c2ecf20Sopenharmony_ci if (err == 0) { 878c2ecf20Sopenharmony_ci set_current_blocked(&set); 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err); 918c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err); 928c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err); 938c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err); 948c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err); 958c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err); 968c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err); 978c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err); 988c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err); 998c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err); 1008c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err); 1018c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err); 1028c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err); 1038c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err); 1048c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err); 1058c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err); 1068c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err); 1078c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err); 1088c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err); 1098c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err); 1108c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err); 1118c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err); 1128c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err); 1138c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err); 1148c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err); 1158c2ecf20Sopenharmony_ci __get_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci __get_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err); 1188c2ecf20Sopenharmony_ci __get_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err); 1198c2ecf20Sopenharmony_ci __get_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err); 1208c2ecf20Sopenharmony_ci __get_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err); 1218c2ecf20Sopenharmony_ci __get_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err); 1228c2ecf20Sopenharmony_ci#if defined(CONFIG_HWZOL) 1238c2ecf20Sopenharmony_ci __get_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err); 1248c2ecf20Sopenharmony_ci __get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err); 1258c2ecf20Sopenharmony_ci __get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err); 1268c2ecf20Sopenharmony_ci#endif 1278c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_FPU) 1288c2ecf20Sopenharmony_ci err |= restore_sigcontext_fpu(regs, &sf->uc.uc_mcontext); 1298c2ecf20Sopenharmony_ci#endif 1308c2ecf20Sopenharmony_ci /* 1318c2ecf20Sopenharmony_ci * Avoid sys_rt_sigreturn() restarting. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci forget_syscall(regs); 1348c2ecf20Sopenharmony_ci return err; 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ciasmlinkage long sys_rt_sigreturn(struct pt_regs *regs) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci struct rt_sigframe __user *frame; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Always make any pending restarted system calls return -EINTR */ 1428c2ecf20Sopenharmony_ci current->restart_block.fn = do_no_restart_syscall; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* 1458c2ecf20Sopenharmony_ci * Since we stacked the signal on a 64-bit boundary, 1468c2ecf20Sopenharmony_ci * then 'sp' should be two-word aligned here. If it's 1478c2ecf20Sopenharmony_ci * not, then the user is trying to mess with us. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci if (regs->sp & 7) 1508c2ecf20Sopenharmony_ci goto badframe; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci frame = (struct rt_sigframe __user *)regs->sp; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (!access_ok(frame, sizeof(*frame))) 1558c2ecf20Sopenharmony_ci goto badframe; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (restore_sigframe(regs, frame)) 1588c2ecf20Sopenharmony_ci goto badframe; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (restore_altstack(&frame->uc.uc_stack)) 1618c2ecf20Sopenharmony_ci goto badframe; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci return regs->uregs[0]; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cibadframe: 1668c2ecf20Sopenharmony_ci force_sig(SIGSEGV); 1678c2ecf20Sopenharmony_ci return 0; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic int 1718c2ecf20Sopenharmony_cisetup_sigframe(struct rt_sigframe __user * sf, struct pt_regs *regs, 1728c2ecf20Sopenharmony_ci sigset_t * set) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci int err = 0; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err); 1778c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err); 1788c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err); 1798c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err); 1808c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err); 1818c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err); 1828c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err); 1838c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err); 1848c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err); 1858c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err); 1868c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err); 1878c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err); 1888c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err); 1898c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err); 1908c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err); 1918c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err); 1928c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err); 1938c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err); 1948c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err); 1958c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err); 1968c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err); 1998c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err); 2008c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err); 2018c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err); 2028c2ecf20Sopenharmony_ci __put_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err); 2038c2ecf20Sopenharmony_ci __put_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err); 2048c2ecf20Sopenharmony_ci __put_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err); 2058c2ecf20Sopenharmony_ci __put_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err); 2068c2ecf20Sopenharmony_ci __put_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err); 2078c2ecf20Sopenharmony_ci __put_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err); 2088c2ecf20Sopenharmony_ci#if defined(CONFIG_HWZOL) 2098c2ecf20Sopenharmony_ci __put_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err); 2108c2ecf20Sopenharmony_ci __put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err); 2118c2ecf20Sopenharmony_ci __put_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err); 2128c2ecf20Sopenharmony_ci#endif 2138c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_FPU) 2148c2ecf20Sopenharmony_ci err |= setup_sigcontext_fpu(regs, &sf->uc.uc_mcontext); 2158c2ecf20Sopenharmony_ci#endif 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, 2188c2ecf20Sopenharmony_ci err); 2198c2ecf20Sopenharmony_ci __put_user_error(current->thread.error_code, 2208c2ecf20Sopenharmony_ci &sf->uc.uc_mcontext.error_code, err); 2218c2ecf20Sopenharmony_ci __put_user_error(current->thread.address, 2228c2ecf20Sopenharmony_ci &sf->uc.uc_mcontext.fault_address, err); 2238c2ecf20Sopenharmony_ci __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return err; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic inline void __user *get_sigframe(struct ksignal *ksig, 2318c2ecf20Sopenharmony_ci struct pt_regs *regs, int framesize) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci unsigned long sp; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* Default to using normal stack */ 2368c2ecf20Sopenharmony_ci sp = regs->sp; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci /* 2398c2ecf20Sopenharmony_ci * If we are on the alternate signal stack and would overflow it, don't. 2408c2ecf20Sopenharmony_ci * Return an always-bogus address instead so we will die with SIGSEGV. 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_ci if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) 2438c2ecf20Sopenharmony_ci return (void __user __force *)(-1UL); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci /* This is the X/Open sanctioned signal stack switching. */ 2468c2ecf20Sopenharmony_ci sp = (sigsp(sp, ksig) - framesize); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* 2498c2ecf20Sopenharmony_ci * nds32 mandates 8-byte alignment 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_ci sp &= ~0x7UL; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return (void __user *)sp; 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_cistatic int 2578c2ecf20Sopenharmony_cisetup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler; 2608c2ecf20Sopenharmony_ci unsigned long retcode; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci retcode = VDSO_SYMBOL(current->mm->context.vdso, rt_sigtramp); 2638c2ecf20Sopenharmony_ci regs->uregs[0] = ksig->sig; 2648c2ecf20Sopenharmony_ci regs->sp = (unsigned long)frame; 2658c2ecf20Sopenharmony_ci regs->lp = retcode; 2668c2ecf20Sopenharmony_ci regs->ipc = handler; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci return 0; 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cistatic int 2728c2ecf20Sopenharmony_cisetup_rt_frame(struct ksignal *ksig, sigset_t * set, struct pt_regs *regs) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci struct rt_sigframe __user *frame = 2758c2ecf20Sopenharmony_ci get_sigframe(ksig, regs, sizeof(*frame)); 2768c2ecf20Sopenharmony_ci int err = 0; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (!access_ok(frame, sizeof(*frame))) 2798c2ecf20Sopenharmony_ci return -EFAULT; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci __put_user_error(0, &frame->uc.uc_flags, err); 2828c2ecf20Sopenharmony_ci __put_user_error(NULL, &frame->uc.uc_link, err); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci err |= __save_altstack(&frame->uc.uc_stack, regs->sp); 2858c2ecf20Sopenharmony_ci err |= setup_sigframe(frame, regs, set); 2868c2ecf20Sopenharmony_ci if (err == 0) { 2878c2ecf20Sopenharmony_ci setup_return(regs, ksig, frame); 2888c2ecf20Sopenharmony_ci if (ksig->ka.sa.sa_flags & SA_SIGINFO) { 2898c2ecf20Sopenharmony_ci err |= copy_siginfo_to_user(&frame->info, &ksig->info); 2908c2ecf20Sopenharmony_ci regs->uregs[1] = (unsigned long)&frame->info; 2918c2ecf20Sopenharmony_ci regs->uregs[2] = (unsigned long)&frame->uc; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci return err; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci/* 2988c2ecf20Sopenharmony_ci * OK, we're invoking a handler 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_cistatic void handle_signal(struct ksignal *ksig, struct pt_regs *regs) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci int ret; 3038c2ecf20Sopenharmony_ci sigset_t *oldset = sigmask_to_save(); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (in_syscall(regs)) { 3068c2ecf20Sopenharmony_ci /* Avoid additional syscall restarting via ret_slow_syscall. */ 3078c2ecf20Sopenharmony_ci forget_syscall(regs); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci switch (regs->uregs[0]) { 3108c2ecf20Sopenharmony_ci case -ERESTART_RESTARTBLOCK: 3118c2ecf20Sopenharmony_ci case -ERESTARTNOHAND: 3128c2ecf20Sopenharmony_ci regs->uregs[0] = -EINTR; 3138c2ecf20Sopenharmony_ci break; 3148c2ecf20Sopenharmony_ci case -ERESTARTSYS: 3158c2ecf20Sopenharmony_ci if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { 3168c2ecf20Sopenharmony_ci regs->uregs[0] = -EINTR; 3178c2ecf20Sopenharmony_ci break; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci fallthrough; 3208c2ecf20Sopenharmony_ci case -ERESTARTNOINTR: 3218c2ecf20Sopenharmony_ci regs->uregs[0] = regs->orig_r0; 3228c2ecf20Sopenharmony_ci regs->ipc -= 4; 3238c2ecf20Sopenharmony_ci break; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci /* 3278c2ecf20Sopenharmony_ci * Set up the stack frame 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_ci ret = setup_rt_frame(ksig, oldset, regs); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci signal_setup_done(ret, ksig, 0); 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci/* 3358c2ecf20Sopenharmony_ci * Note that 'init' is a special process: it doesn't get signals it doesn't 3368c2ecf20Sopenharmony_ci * want to handle. Thus you cannot kill init even with a SIGKILL even by 3378c2ecf20Sopenharmony_ci * mistake. 3388c2ecf20Sopenharmony_ci * 3398c2ecf20Sopenharmony_ci * Note that we go through the signals twice: once to check the signals that 3408c2ecf20Sopenharmony_ci * the kernel can handle, and then we build all the user-level signal handling 3418c2ecf20Sopenharmony_ci * stack-frames in one go after that. 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_cistatic void do_signal(struct pt_regs *regs) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct ksignal ksig; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (get_signal(&ksig)) { 3488c2ecf20Sopenharmony_ci handle_signal(&ksig, regs); 3498c2ecf20Sopenharmony_ci return; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* 3538c2ecf20Sopenharmony_ci * If we were from a system call, check for system call restarting... 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_ci if (in_syscall(regs)) { 3568c2ecf20Sopenharmony_ci /* Restart the system call - no handlers present */ 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci /* Avoid additional syscall restarting via ret_slow_syscall. */ 3598c2ecf20Sopenharmony_ci forget_syscall(regs); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci switch (regs->uregs[0]) { 3628c2ecf20Sopenharmony_ci case -ERESTART_RESTARTBLOCK: 3638c2ecf20Sopenharmony_ci regs->uregs[15] = __NR_restart_syscall; 3648c2ecf20Sopenharmony_ci fallthrough; 3658c2ecf20Sopenharmony_ci case -ERESTARTNOHAND: 3668c2ecf20Sopenharmony_ci case -ERESTARTSYS: 3678c2ecf20Sopenharmony_ci case -ERESTARTNOINTR: 3688c2ecf20Sopenharmony_ci regs->uregs[0] = regs->orig_r0; 3698c2ecf20Sopenharmony_ci regs->ipc -= 0x4; 3708c2ecf20Sopenharmony_ci break; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci restore_saved_sigmask(); 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ciasmlinkage void 3778c2ecf20Sopenharmony_cido_notify_resume(struct pt_regs *regs, unsigned int thread_flags) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) 3808c2ecf20Sopenharmony_ci do_signal(regs); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (thread_flags & _TIF_NOTIFY_RESUME) 3838c2ecf20Sopenharmony_ci tracehook_notify_resume(regs); 3848c2ecf20Sopenharmony_ci} 385