1116775Smarcel/* 2116775Smarcel * Copyright (c) 2003 Marcel Moolenaar 3116775Smarcel * All rights reserved. 4116775Smarcel * 5116775Smarcel * Redistribution and use in source and binary forms, with or without 6116775Smarcel * modification, are permitted provided that the following conditions 7116775Smarcel * are met: 8116775Smarcel * 9116775Smarcel * 1. Redistributions of source code must retain the above copyright 10116775Smarcel * notice, this list of conditions and the following disclaimer. 11116775Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12116775Smarcel * notice, this list of conditions and the following disclaimer in the 13116775Smarcel * documentation and/or other materials provided with the distribution. 14116775Smarcel * 15116775Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16116775Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17116775Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18116775Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19116775Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20116775Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21116775Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22116775Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23116775Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24116775Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25116775Smarcel */ 26116775Smarcel 27116775Smarcel#include <sys/cdefs.h> 28116775Smarcel__FBSDID("$FreeBSD: releng/10.2/lib/libc/ia64/gen/signalcontext.c 124191 2004-01-06 19:40:28Z nectar $"); 29116775Smarcel 30116775Smarcel#include <sys/types.h> 31116775Smarcel#include <sys/ucontext.h> 32116775Smarcel#include <machine/fpu.h> 33116775Smarcel#include <signal.h> 34116775Smarcel#include <stdio.h> 35124191Snectar#include <stdlib.h> 36124191Snectar#include <string.h> 37116775Smarcel#include <strings.h> 38116775Smarcel 39116775Smarcelstruct fdesc { 40116775Smarcel uint64_t ip; 41116775Smarcel uint64_t gp; 42116775Smarcel}; 43116775Smarcel 44116775Smarceltypedef void (*handler_t)(uint64_t, uint64_t, uint64_t); 45116775Smarcel 46116775Smarcelstatic __inline uint64_t * 47116775Smarcelspill(uint64_t *bsp, uint64_t arg) 48116775Smarcel{ 49116775Smarcel *bsp++ = arg; 50116775Smarcel if (((intptr_t)bsp & 0x1ff) == 0x1f8) 51116775Smarcel *bsp++ = 0; 52116775Smarcel return (bsp); 53116775Smarcel} 54116775Smarcel 55116775Smarcelstatic void 56116775Smarcelctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args) 57116775Smarcel{ 58116775Smarcel 59116775Smarcel (*func)(args[0], args[1], args[2]); 60116775Smarcel if (ucp->uc_link == NULL) 61116775Smarcel exit(0); 62116775Smarcel setcontext((const ucontext_t *)ucp->uc_link); 63116775Smarcel /* should never get here */ 64116775Smarcel abort(); 65116775Smarcel /* NOTREACHED */ 66116775Smarcel} 67116775Smarcel 68116775Smarcel__weak_reference(__signalcontext, signalcontext); 69116775Smarcel 70116775Smarcelint 71116775Smarcel__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func) 72116775Smarcel{ 73116775Smarcel uint64_t *args, *bsp; 74116775Smarcel siginfo_t *sig_si; 75116775Smarcel ucontext_t *sig_uc; 76116775Smarcel uint64_t sp; 77116775Smarcel 78116775Smarcel /* Bail out if we don't have a valid ucontext pointer. */ 79116775Smarcel if (ucp == NULL) 80116775Smarcel abort(); 81116775Smarcel 82116775Smarcel /* 83116775Smarcel * Build a signal frame and copy the arguments of signal handler 84116775Smarcel * 'func' onto the (memory) stack. We only need 3 arguments, but 85116775Smarcel * we create room for 4 so that we are 16-byte aligned. 86116775Smarcel */ 87116775Smarcel sp = (ucp->uc_mcontext.mc_special.sp - sizeof(ucontext_t)) & ~15UL; 88116775Smarcel sig_uc = (ucontext_t*)sp; 89116775Smarcel bcopy(ucp, sig_uc, sizeof(*sig_uc)); 90116775Smarcel sp = (sp - sizeof(siginfo_t)) & ~15UL; 91116775Smarcel sig_si = (siginfo_t*)sp; 92116775Smarcel bzero(sig_si, sizeof(*sig_si)); 93116775Smarcel sig_si->si_signo = sig; 94116775Smarcel sp -= 4 * sizeof(uint64_t); 95116775Smarcel args = (uint64_t*)sp; 96116775Smarcel args[0] = sig; 97116775Smarcel args[1] = (intptr_t)sig_si; 98116775Smarcel args[2] = (intptr_t)sig_uc; 99116775Smarcel 100116775Smarcel /* 101116775Smarcel * Push (spill) the arguments of the context wrapper onto the register 102116775Smarcel * stack. They get loaded by the RSE on a context switch. 103116775Smarcel */ 104116775Smarcel bsp = (uint64_t*)ucp->uc_mcontext.mc_special.bspstore; 105116775Smarcel bsp = spill(bsp, (intptr_t)ucp); 106116775Smarcel bsp = spill(bsp, (intptr_t)func); 107116775Smarcel bsp = spill(bsp, (intptr_t)args); 108116775Smarcel 109116775Smarcel /* 110116775Smarcel * Setup the ucontext of the signal handler. 111116775Smarcel */ 112116775Smarcel memset(&ucp->uc_mcontext, 0, sizeof(ucp->uc_mcontext)); 113116775Smarcel ucp->uc_link = sig_uc; 114116775Smarcel sigdelset(&ucp->uc_sigmask, sig); 115116775Smarcel ucp->uc_mcontext.mc_special.sp = (intptr_t)args - 16; 116116775Smarcel ucp->uc_mcontext.mc_special.bspstore = (intptr_t)bsp; 117116775Smarcel ucp->uc_mcontext.mc_special.pfs = (3 << 7) | 3; 118116775Smarcel ucp->uc_mcontext.mc_special.rsc = 0xf; 119116775Smarcel ucp->uc_mcontext.mc_special.rp = ((struct fdesc*)ctx_wrapper)->ip; 120116775Smarcel ucp->uc_mcontext.mc_special.gp = ((struct fdesc*)ctx_wrapper)->gp; 121116775Smarcel ucp->uc_mcontext.mc_special.fpsr = IA64_FPSR_DEFAULT; 122116775Smarcel return (0); 123116775Smarcel} 124