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