#ifdef _KERNEL_OPT
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_multiprocessor.h"
#include "opt_dec_3000_300.h"
#include "opt_dec_3000_500.h"
#include "opt_compat_netbsd.h"
#include "opt_execfmt.h"
#endif
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/syscall.h>
#include <sys/syscallargs.h>
#if defined(COMPAT_13)
#include <compat/sys/signal.h>
#include <compat/sys/signalvar.h>
#endif
#include <machine/cpu.h>
#include <machine/reg.h>
__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.24 2025/04/25 00:59:26 riastradh Exp $");
#ifdef DEBUG
#include <machine/sigdebug.h>
#endif
#include <machine/alpha.h>
#include <sys/ksyms.h>
void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
struct lwp *l = curlwp;
struct proc *p = l->l_proc;
struct pcb *pcb = lwp_getpcb(l);
struct sigacts *ps = p->p_sigacts;
int onstack, sig = ksi->ksi_signo, error;
struct sigframe_sigcontext *fp, frame;
struct trapframe *tf;
sig_t catcher = SIGACTION(p, sig).sa_handler;
tf = l->l_md.md_tf;
fp = getframe(l, sig, &onstack, sizeof(*fp), _Alignof(*fp));
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig_sigcontext(%d): sig %d ssp %p usp %p\n",
p->p_pid, sig, &onstack, fp);
#endif
frame.sf_sc.sc_pc = tf->tf_regs[FRAME_PC];
frame.sf_sc.sc_ps = tf->tf_regs[FRAME_PS];
frametoreg(tf, (struct reg *)frame.sf_sc.sc_regs);
frame.sf_sc.sc_regs[R_ZERO] = 0xACEDBADE;
frame.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();
fpu_save(l);
frame.sf_sc.sc_ownedfp = fpu_valid_p(l);
memcpy((struct fpreg *)frame.sf_sc.sc_fpregs, &pcb->pcb_fp,
sizeof(struct fpreg));
frame.sf_sc.sc_fp_control = alpha_read_fp_c(l);
memset(frame.sf_sc.sc_reserved, 0, sizeof frame.sf_sc.sc_reserved);
memset(frame.sf_sc.sc_xxx, 0, sizeof frame.sf_sc.sc_xxx);
frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
frame.sf_sc.sc_mask = *mask;
#if defined(COMPAT_13)
{
sigset13_t mask13;
native_sigset_to_sigset13(mask, &mask13);
frame.sf_sc.__sc_mask13 = mask13;
}
#endif
sendsig_reset(l, sig);
mutex_exit(p->p_lock);
error = copyout(&frame, (void *)fp, sizeof(frame));
mutex_enter(p->p_lock);
if (error != 0) {
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig_sigcontext(%d): copyout failed on sig %d\n",
p->p_pid, sig);
#endif
sigexit(l, SIGILL);
}
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
printf("sendsig_sigcontext(%d): sig %d usp %p code %x\n",
p->p_pid, sig, fp, ksi->ksi_code);
#endif
switch (ps->sa_sigdesc[sig].sd_vers) {
case __SIGTRAMP_SIGCODE_VERSION:
buildcontext(l,(void *)catcher,
(void *)p->p_sigctx.ps_sigcode,
(void *)fp);
break;
#ifdef COMPAT_16
case __SIGTRAMP_SIGCONTEXT_VERSION:
buildcontext(l,(void *)catcher,
(const void *)ps->sa_sigdesc[sig].sd_tramp,
(void *)fp);
break;
#endif
default:
sigexit(l, SIGILL);
}
tf->tf_regs[FRAME_A0] = sig;
tf->tf_regs[FRAME_A1] = KSI_TRAPCODE(ksi);
tf->tf_regs[FRAME_A2] = (uint64_t)&fp->sf_sc;
if (onstack)
l->l_sigstk.ss_flags |= SS_ONSTACK;
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]);
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig(%d): sig %d returns\n",
p->p_pid, sig);
#endif
}
#ifdef COMPAT_16
int
compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval)
{
struct sigcontext *scp, ksc;
struct proc *p = l->l_proc;
struct pcb *pcb;
scp = SCARG(uap, sigcntxp);
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
#endif
if (ALIGN(scp) != (uint64_t)scp)
return (EINVAL);
if (copyin((void *)scp, &ksc, sizeof(ksc)) != 0)
return (EFAULT);
if (ksc.sc_regs[R_ZERO] != 0xACEDBADE)
return (EINVAL);
l->l_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
l->l_md.md_tf->tf_regs[FRAME_PS] =
(ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;
regtoframe((struct reg *)ksc.sc_regs, l->l_md.md_tf);
alpha_pal_wrusp(ksc.sc_regs[R_SP]);
pcb = lwp_getpcb(l);
fpu_discard(l, true);
memcpy(&pcb->pcb_fp, (struct fpreg *)ksc.sc_fpregs,
sizeof(struct fpreg));
pcb->pcb_fp.fpr_cr = ksc.sc_fpcr;
l->l_md.md_flags = ksc.sc_fp_control & MDLWP_FP_C;
mutex_enter(p->p_lock);
if (ksc.sc_onstack & SS_ONSTACK)
l->l_sigstk.ss_flags |= SS_ONSTACK;
else
l->l_sigstk.ss_flags &= ~SS_ONSTACK;
(void) sigprocmask1(l, SIG_SETMASK, &ksc.sc_mask, 0);
mutex_exit(p->p_lock);
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW)
printf("sigreturn(%d): returns\n", p->p_pid);
#endif
return (EJUSTRETURN);
}
#endif