signalcontext.c revision 116775
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: head/lib/libc/ia64/gen/signalcontext.c 116775 2003-06-24 05:06:42Z marcel $"); 29116775Smarcel 30116775Smarcel#include <sys/types.h> 31116775Smarcel#include <sys/ucontext.h> 32116775Smarcel#include <machine/fpu.h> 33116775Smarcel#include <signal.h> 34116775Smarcel#include <stdio.h> 35116775Smarcel#include <strings.h> 36116775Smarcel 37116775Smarcelstruct fdesc { 38116775Smarcel uint64_t ip; 39116775Smarcel uint64_t gp; 40116775Smarcel}; 41116775Smarcel 42116775Smarceltypedef void (*handler_t)(uint64_t, uint64_t, uint64_t); 43116775Smarcel 44116775Smarcelstatic __inline uint64_t * 45116775Smarcelspill(uint64_t *bsp, uint64_t arg) 46116775Smarcel{ 47116775Smarcel *bsp++ = arg; 48116775Smarcel if (((intptr_t)bsp & 0x1ff) == 0x1f8) 49116775Smarcel *bsp++ = 0; 50116775Smarcel return (bsp); 51116775Smarcel} 52116775Smarcel 53116775Smarcelstatic void 54116775Smarcelctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args) 55116775Smarcel{ 56116775Smarcel 57116775Smarcel (*func)(args[0], args[1], args[2]); 58116775Smarcel if (ucp->uc_link == NULL) 59116775Smarcel exit(0); 60116775Smarcel setcontext((const ucontext_t *)ucp->uc_link); 61116775Smarcel /* should never get here */ 62116775Smarcel abort(); 63116775Smarcel /* NOTREACHED */ 64116775Smarcel} 65116775Smarcel 66116775Smarcel__weak_reference(__signalcontext, signalcontext); 67116775Smarcel 68116775Smarcelint 69116775Smarcel__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func) 70116775Smarcel{ 71116775Smarcel uint64_t *args, *bsp; 72116775Smarcel siginfo_t *sig_si; 73116775Smarcel ucontext_t *sig_uc; 74116775Smarcel uint64_t sp; 75116775Smarcel 76116775Smarcel /* Bail out if we don't have a valid ucontext pointer. */ 77116775Smarcel if (ucp == NULL) 78116775Smarcel abort(); 79116775Smarcel 80116775Smarcel /* 81116775Smarcel * Build a signal frame and copy the arguments of signal handler 82116775Smarcel * 'func' onto the (memory) stack. We only need 3 arguments, but 83116775Smarcel * we create room for 4 so that we are 16-byte aligned. 84116775Smarcel */ 85116775Smarcel sp = (ucp->uc_mcontext.mc_special.sp - sizeof(ucontext_t)) & ~15UL; 86116775Smarcel sig_uc = (ucontext_t*)sp; 87116775Smarcel bcopy(ucp, sig_uc, sizeof(*sig_uc)); 88116775Smarcel sp = (sp - sizeof(siginfo_t)) & ~15UL; 89116775Smarcel sig_si = (siginfo_t*)sp; 90116775Smarcel bzero(sig_si, sizeof(*sig_si)); 91116775Smarcel sig_si->si_signo = sig; 92116775Smarcel sp -= 4 * sizeof(uint64_t); 93116775Smarcel args = (uint64_t*)sp; 94116775Smarcel args[0] = sig; 95116775Smarcel args[1] = (intptr_t)sig_si; 96116775Smarcel args[2] = (intptr_t)sig_uc; 97116775Smarcel 98116775Smarcel /* 99116775Smarcel * Push (spill) the arguments of the context wrapper onto the register 100116775Smarcel * stack. They get loaded by the RSE on a context switch. 101116775Smarcel */ 102116775Smarcel bsp = (uint64_t*)ucp->uc_mcontext.mc_special.bspstore; 103116775Smarcel bsp = spill(bsp, (intptr_t)ucp); 104116775Smarcel bsp = spill(bsp, (intptr_t)func); 105116775Smarcel bsp = spill(bsp, (intptr_t)args); 106116775Smarcel 107116775Smarcel /* 108116775Smarcel * Setup the ucontext of the signal handler. 109116775Smarcel */ 110116775Smarcel memset(&ucp->uc_mcontext, 0, sizeof(ucp->uc_mcontext)); 111116775Smarcel ucp->uc_link = sig_uc; 112116775Smarcel sigdelset(&ucp->uc_sigmask, sig); 113116775Smarcel ucp->uc_mcontext.mc_special.sp = (intptr_t)args - 16; 114116775Smarcel ucp->uc_mcontext.mc_special.bspstore = (intptr_t)bsp; 115116775Smarcel ucp->uc_mcontext.mc_special.pfs = (3 << 7) | 3; 116116775Smarcel ucp->uc_mcontext.mc_special.rsc = 0xf; 117116775Smarcel ucp->uc_mcontext.mc_special.rp = ((struct fdesc*)ctx_wrapper)->ip; 118116775Smarcel ucp->uc_mcontext.mc_special.gp = ((struct fdesc*)ctx_wrapper)->gp; 119116775Smarcel ucp->uc_mcontext.mc_special.fpsr = IA64_FPSR_DEFAULT; 120116775Smarcel return (0); 121116775Smarcel} 122