11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * Copyright (C) 2003 Broadcom Corporation 41da177e4SLinus Torvalds */ 502416dcfSRalf Baechle #include <linux/cache.h> 602416dcfSRalf Baechle #include <linux/sched.h> 71da177e4SLinus Torvalds #include <linux/mm.h> 81da177e4SLinus Torvalds #include <linux/smp.h> 91da177e4SLinus Torvalds #include <linux/kernel.h> 101da177e4SLinus Torvalds #include <linux/signal.h> 111da177e4SLinus Torvalds #include <linux/errno.h> 121da177e4SLinus Torvalds #include <linux/wait.h> 131da177e4SLinus Torvalds #include <linux/ptrace.h> 141da177e4SLinus Torvalds #include <linux/unistd.h> 151da177e4SLinus Torvalds #include <linux/compat.h> 161da177e4SLinus Torvalds #include <linux/bitops.h> 171da177e4SLinus Torvalds 18151fd6acSRalf Baechle #include <asm/abi.h> 191da177e4SLinus Torvalds #include <asm/asm.h> 201da177e4SLinus Torvalds #include <asm/cacheflush.h> 21431dc804SRalf Baechle #include <asm/compat-signal.h> 221da177e4SLinus Torvalds #include <asm/sim.h> 237c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 241da177e4SLinus Torvalds #include <asm/ucontext.h> 251da177e4SLinus Torvalds #include <asm/fpu.h> 261da177e4SLinus Torvalds #include <asm/cpu-features.h> 2702416dcfSRalf Baechle #include <asm/war.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include "signal-common.h" 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds /* 321da177e4SLinus Torvalds * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... 331da177e4SLinus Torvalds */ 341da177e4SLinus Torvalds #define __NR_N32_restart_syscall 6214 351da177e4SLinus Torvalds 36205d84aaSRalf Baechle extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *); 37205d84aaSRalf Baechle extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *); 38205d84aaSRalf Baechle 391da177e4SLinus Torvalds struct ucontextn32 { 401da177e4SLinus Torvalds u32 uc_flags; 411da177e4SLinus Torvalds s32 uc_link; 42ea536ad4SAl Viro compat_stack_t uc_stack; 431da177e4SLinus Torvalds struct sigcontext uc_mcontext; 44431dc804SRalf Baechle compat_sigset_t uc_sigmask; /* mask last for extensibility */ 451da177e4SLinus Torvalds }; 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds struct rt_sigframe_n32 { 481da177e4SLinus Torvalds u32 rs_ass[4]; /* argument save space for o32 */ 49d814c28cSDavid Daney u32 rs_pad[2]; /* Was: signal trampoline */ 50a76f3a41SPavel Kiryukhin struct compat_siginfo rs_info; 511da177e4SLinus Torvalds struct ucontextn32 rs_uc; 521da177e4SLinus Torvalds }; 531da177e4SLinus Torvalds 5496a68b14SPaul Burton asmlinkage void sysn32_rt_sigreturn(void) 551da177e4SLinus Torvalds { 569bbf28a3SAtsushi Nemoto struct rt_sigframe_n32 __user *frame; 5796a68b14SPaul Burton struct pt_regs *regs; 581da177e4SLinus Torvalds sigset_t set; 59c6a2f467SAtsushi Nemoto int sig; 601da177e4SLinus Torvalds 6196a68b14SPaul Burton regs = current_pt_regs(); 6296a68b14SPaul Burton frame = (struct rt_sigframe_n32 __user *)regs->regs[29]; 6396d4f267SLinus Torvalds if (!access_ok(frame, sizeof(*frame))) 641da177e4SLinus Torvalds goto badframe; 65431dc804SRalf Baechle if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) 661da177e4SLinus Torvalds goto badframe; 671da177e4SLinus Torvalds 688598f3cdSMatt Fleming set_current_blocked(&set); 691da177e4SLinus Torvalds 7096a68b14SPaul Burton sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); 71c6a2f467SAtsushi Nemoto if (sig < 0) 721da177e4SLinus Torvalds goto badframe; 73c6a2f467SAtsushi Nemoto else if (sig) 74c6a2f467SAtsushi Nemoto force_sig(sig, current); 751da177e4SLinus Torvalds 76ea536ad4SAl Viro if (compat_restore_altstack(&frame->rs_uc.uc_stack)) 771da177e4SLinus Torvalds goto badframe; 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds /* 801da177e4SLinus Torvalds * Don't let your children do this ... 811da177e4SLinus Torvalds */ 821da177e4SLinus Torvalds __asm__ __volatile__( 831da177e4SLinus Torvalds "move\t$29, %0\n\t" 841da177e4SLinus Torvalds "j\tsyscall_exit" 851da177e4SLinus Torvalds : /* no outputs */ 8696a68b14SPaul Burton : "r" (regs)); 871da177e4SLinus Torvalds /* Unreached */ 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds badframe: 901da177e4SLinus Torvalds force_sig(SIGSEGV, current); 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 9381d103bfSRichard Weinberger static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig, 9481d103bfSRichard Weinberger struct pt_regs *regs, sigset_t *set) 951da177e4SLinus Torvalds { 969bbf28a3SAtsushi Nemoto struct rt_sigframe_n32 __user *frame; 971da177e4SLinus Torvalds int err = 0; 981da177e4SLinus Torvalds 997c4f5635SRichard Weinberger frame = get_sigframe(ksig, regs, sizeof(*frame)); 10096d4f267SLinus Torvalds if (!access_ok(frame, sizeof (*frame))) 10181d103bfSRichard Weinberger return -EFAULT; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds /* Create siginfo. */ 10481d103bfSRichard Weinberger err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info); 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds /* Create the ucontext. */ 1071da177e4SLinus Torvalds err |= __put_user(0, &frame->rs_uc.uc_flags); 1081da177e4SLinus Torvalds err |= __put_user(0, &frame->rs_uc.uc_link); 109ea536ad4SAl Viro err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); 1101da177e4SLinus Torvalds err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); 111431dc804SRalf Baechle err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds if (err) 11481d103bfSRichard Weinberger return -EFAULT; 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds /* 1171da177e4SLinus Torvalds * Arguments to signal handler: 1181da177e4SLinus Torvalds * 1191da177e4SLinus Torvalds * a0 = signal number 1201da177e4SLinus Torvalds * a1 = 0 (should be cause) 1211da177e4SLinus Torvalds * a2 = pointer to ucontext 1221da177e4SLinus Torvalds * 1231da177e4SLinus Torvalds * $25 and c0_epc point to the signal handler, $29 points to 1241da177e4SLinus Torvalds * the struct rt_sigframe. 1251da177e4SLinus Torvalds */ 12681d103bfSRichard Weinberger regs->regs[ 4] = ksig->sig; 1271da177e4SLinus Torvalds regs->regs[ 5] = (unsigned long) &frame->rs_info; 1281da177e4SLinus Torvalds regs->regs[ 6] = (unsigned long) &frame->rs_uc; 1291da177e4SLinus Torvalds regs->regs[29] = (unsigned long) frame; 130d814c28cSDavid Daney regs->regs[31] = (unsigned long) sig_return; 13181d103bfSRichard Weinberger regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; 1321da177e4SLinus Torvalds 133722bb63dSFranck Bui-Huu DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 1341da177e4SLinus Torvalds current->comm, current->pid, 1351da177e4SLinus Torvalds frame, regs->cp0_epc, regs->regs[31]); 136722bb63dSFranck Bui-Huu 1377b3e2fc8SRalf Baechle return 0; 1381da177e4SLinus Torvalds } 139151fd6acSRalf Baechle 140151fd6acSRalf Baechle struct mips_abi mips_abi_n32 = { 141151fd6acSRalf Baechle .setup_rt_frame = setup_rt_frame_n32, 14277856100SPaul Burton .restart = __NR_N32_restart_syscall, 14377856100SPaul Burton 14477856100SPaul Burton .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs), 14577856100SPaul Burton .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr), 14677856100SPaul Burton .off_sc_used_math = offsetof(struct sigcontext, sc_used_math), 147ebb5e78cSAlex Smith 148ebb5e78cSAlex Smith .vdso = &vdso_image_n32, 149151fd6acSRalf Baechle }; 150