1219820Sjeff/* 2219820Sjeff * Copyright (c) 2003 Marcel Moolenaar 3219820Sjeff * All rights reserved. 4219820Sjeff * 5219820Sjeff * Redistribution and use in source and binary forms, with or without 6219820Sjeff * modification, are permitted provided that the following conditions 7219820Sjeff * are met: 8219820Sjeff * 9219820Sjeff * 1. Redistributions of source code must retain the above copyright 10219820Sjeff * notice, this list of conditions and the following disclaimer. 11219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 12219820Sjeff * notice, this list of conditions and the following disclaimer in the 13219820Sjeff * documentation and/or other materials provided with the distribution. 14219820Sjeff * 15219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17219820Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18219820Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19219820Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21219820Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22219820Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23219820Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24219820Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25219820Sjeff */ 26219820Sjeff 27219820Sjeff#include <sys/cdefs.h> 28219820Sjeff__FBSDID("$FreeBSD$"); 29219820Sjeff 30219820Sjeff#include <sys/types.h> 31219820Sjeff#include <sys/ucontext.h> 32219820Sjeff#include <machine/fpu.h> 33219820Sjeff#include <stdarg.h> 34219820Sjeff#include <stdio.h> 35255932Salfred#include <stdlib.h> 36255932Salfred#include <string.h> 37219820Sjeff 38255932Salfredstruct fdesc { 39219820Sjeff uint64_t ip; 40255932Salfred uint64_t gp; 41255932Salfred}; 42219820Sjeff 43219820Sjefftypedef void (*func_t)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, 44219820Sjeff uint64_t, uint64_t, uint64_t); 45219820Sjeff 46219820Sjeffstatic __inline uint64_t * 47219820Sjeffspill(uint64_t *bsp, uint64_t arg) 48219820Sjeff{ 49219820Sjeff *bsp++ = arg; 50255932Salfred if (((intptr_t)bsp & 0x1ff) == 0x1f8) 51255932Salfred *bsp++ = 0; 52255932Salfred return (bsp); 53255932Salfred} 54255932Salfred 55255932Salfredstatic void 56255932Salfredctx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args) 57255932Salfred{ 58255932Salfred 59255932Salfred (*func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], 60255932Salfred args[7]); 61255932Salfred if (ucp->uc_link == NULL) 62255932Salfred exit(0); 63255932Salfred setcontext((const ucontext_t *)ucp->uc_link); 64255932Salfred /* should never get here */ 65255932Salfred abort(); 66255932Salfred /* NOTREACHED */ 67255932Salfred} 68255932Salfred 69255932Salfred__weak_reference(__makecontext, makecontext); 70255932Salfred 71255932Salfredvoid 72255932Salfred__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) 73255932Salfred{ 74255932Salfred uint64_t *args, *bsp; 75255932Salfred va_list ap; 76255932Salfred int i; 77255932Salfred 78255932Salfred /* 79255932Salfred * Drop the ball completely if something's not right. We only 80255932Salfred * support general registers as arguments and not more than 8 81255932Salfred * of them. Things get hairy if we need to support FP registers 82255932Salfred * (alignment issues) or more than 8 arguments (stack based). 83255932Salfred */ 84255932Salfred if (argc < 0 || argc > 8 || ucp == NULL || 85255932Salfred ucp->uc_stack.ss_sp == NULL || (ucp->uc_stack.ss_size & 15) || 86255932Salfred ((intptr_t)ucp->uc_stack.ss_sp & 15) || 87255932Salfred ucp->uc_stack.ss_size < MINSIGSTKSZ) 88255932Salfred abort(); 89255932Salfred 90255932Salfred /* 91255932Salfred * Copy the arguments of function 'func' onto the (memory) stack. 92255932Salfred * Always take up space for 8 arguments. 93255932Salfred */ 94255932Salfred va_start(ap, argc); 95255932Salfred args = (uint64_t*)(ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) - 8; 96255932Salfred i = 0; 97255932Salfred while (i < argc) 98255932Salfred args[i++] = va_arg(ap, uint64_t); 99255932Salfred while (i < 8) 100255932Salfred args[i++] = 0; 101255932Salfred va_end(ap); 102255932Salfred 103255932Salfred /* 104255932Salfred * Push (spill) the arguments of the context wrapper onto the register 105255932Salfred * stack. They get loaded by the RSE on a context switch. 106219820Sjeff */ 107219820Sjeff bsp = (uint64_t*)ucp->uc_stack.ss_sp; 108219820Sjeff bsp = spill(bsp, (intptr_t)ucp); 109219820Sjeff bsp = spill(bsp, (intptr_t)func); 110219820Sjeff bsp = spill(bsp, (intptr_t)args); 111219820Sjeff 112219820Sjeff /* 113219820Sjeff * Setup the MD portion of the context. 114219820Sjeff */ 115219820Sjeff memset(&ucp->uc_mcontext, 0, sizeof(ucp->uc_mcontext)); 116219820Sjeff ucp->uc_mcontext.mc_special.sp = (intptr_t)args - 16; 117219820Sjeff ucp->uc_mcontext.mc_special.bspstore = (intptr_t)bsp; 118219820Sjeff ucp->uc_mcontext.mc_special.pfs = (3 << 7) | 3; 119219820Sjeff ucp->uc_mcontext.mc_special.rsc = 0xf; 120219820Sjeff ucp->uc_mcontext.mc_special.rp = ((struct fdesc*)ctx_wrapper)->ip; 121219820Sjeff ucp->uc_mcontext.mc_special.gp = ((struct fdesc*)ctx_wrapper)->gp; 122219820Sjeff ucp->uc_mcontext.mc_special.fpsr = IA64_FPSR_DEFAULT; 123219820Sjeff} 124219820Sjeff