1/* $NetBSD: sig_machdep.c,v 1.5 2023/05/07 12:41:49 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33 34#ifndef COMPATNAME1 35__RCSID("$NetBSD: sig_machdep.c,v 1.5 2023/05/07 12:41:49 skrll Exp $"); 36#endif 37 38#include <sys/param.h> 39#include <sys/cpu.h> 40#include <sys/mount.h> 41#include <sys/kernel.h> 42#include <sys/proc.h> 43#include <sys/signal.h> 44#include <sys/signalvar.h> 45 46#include <riscv/locore.h> 47#include <riscv/frame.h> 48 49#ifndef COMPATNAME1 50#define COMPATNAME1(x) x 51#define COMPATNAME2(x) x 52#define COMPATTYPE(x) __CONCAT(x,_t) 53#define UCLINK_SET(uc,c) ((uc)->uc_link = (c)) 54#define COPY_SIGINFO(d,s) ((d)->sf_si._info = (s)->ksi_info) 55 56void * 57cpu_sendsig_getframe(struct lwp *l, int signo, bool *onstack) 58{ 59 struct trapframe * const tf = l->l_md.md_utf; 60 struct proc * const p = l->l_proc; 61 62 /* Do we need to jump onto the signal stack? */ 63 *onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 64 && (SIGACTION(p, signo).sa_flags & SA_ONSTACK) != 0; 65 if (*onstack) 66 return (char *)stack_align((intptr_t)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); 67 return (void *)(intptr_t)stack_align(tf->tf_sp); 68} 69#endif 70 71#ifdef COMPATINC 72#include COMPATINC 73#endif 74 75struct COMPATNAME2(sigframe_siginfo) { 76 COMPATTYPE(siginfo) sf_si __aligned(__BIGGEST_ALIGNMENT__); 77 COMPATTYPE(ucontext) sf_uc; 78}; 79 80/* 81 * Send a signal to process. 82 */ 83void 84sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 85{ 86 struct lwp * const l = curlwp; 87 struct proc * const p = l->l_proc; 88 struct sigacts * const sa = p->p_sigacts; 89 struct trapframe * const tf = l->l_md.md_utf; 90 const int signo = ksi->ksi_signo; 91 const sig_t catcher = SIGACTION(p, signo).sa_handler; 92 bool onstack; 93 struct COMPATNAME2(sigframe_siginfo) *sf = 94 cpu_sendsig_getframe(l, signo, &onstack); 95 struct COMPATNAME2(sigframe_siginfo) ksf; 96 97 sf--; // allocate sigframe 98 99 memset(&ksf, 0, sizeof(ksf)); 100 COPY_SIGINFO(&ksf, ksi); 101 ksf.sf_uc.uc_flags = _UC_SIGMASK 102 | (l->l_sigstk.ss_flags & SS_ONSTACK ? _UC_SETSTACK : _UC_CLRSTACK); 103 ksf.sf_uc.uc_sigmask = *mask; 104 UCLINK_SET(&ksf.sf_uc, l->l_ctxlink); 105 memset(&ksf.sf_uc.uc_stack, 0, sizeof(ksf.sf_uc.uc_stack)); 106 sendsig_reset(l, signo); 107 108 mutex_exit(p->p_lock); 109 COMPATNAME2(cpu_getmcontext)(l, &ksf.sf_uc.uc_mcontext, 110 &ksf.sf_uc.uc_flags); 111 int error = copyout(&ksf, sf, sizeof(ksf)); 112 mutex_enter(p->p_lock); 113 114 if (error != 0) { 115 /* 116 * Process has trashed its stack; give it an illegal 117 * instruction to halt it in its tracks. 118 */ 119 sigexit(l, SIGILL); 120 /* NOTREACHED */ 121 } 122 123 /* 124 * Set up the registers to directly invoke the signal 125 * handler. The return address will be set up to point 126 * to the signal trampoline to bounce us back. 127 */ 128 tf->tf_a0 = signo; 129 tf->tf_a1 = (intptr_t)&sf->sf_si; 130 tf->tf_a2 = (intptr_t)&sf->sf_uc; 131 132 tf->tf_pc = (intptr_t)catcher; 133 tf->tf_sp = (intptr_t)sf; 134 tf->tf_ra = (intptr_t)sa->sa_sigdesc[signo].sd_tramp; 135 136 /* Remember that we're now on the signal stack. */ 137 if (onstack) 138 l->l_sigstk.ss_flags |= SS_ONSTACK; 139} 140