makecontext.c revision 124191
1115518Smarcel/* 2115518Smarcel * Copyright (c) 2003 Marcel Moolenaar 3115518Smarcel * All rights reserved. 4115518Smarcel * 5115518Smarcel * Redistribution and use in source and binary forms, with or without 6115518Smarcel * modification, are permitted provided that the following conditions 7115518Smarcel * are met: 8115518Smarcel * 9115518Smarcel * 1. Redistributions of source code must retain the above copyright 10115518Smarcel * notice, this list of conditions and the following disclaimer. 11115518Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12115518Smarcel * notice, this list of conditions and the following disclaimer in the 13115518Smarcel * documentation and/or other materials provided with the distribution. 14115518Smarcel * 15115518Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16115518Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17115518Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18115518Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19115518Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20115518Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21115518Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22115518Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23115518Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24115518Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25115518Smarcel */ 26115518Smarcel 27115518Smarcel#include <sys/cdefs.h> 28115518Smarcel__FBSDID("$FreeBSD: head/lib/libc/ia64/gen/makecontext.c 124191 2004-01-06 19:40:28Z nectar $"); 29115518Smarcel 30115518Smarcel#include <sys/types.h> 31115518Smarcel#include <sys/ucontext.h> 32115518Smarcel#include <machine/fpu.h> 33115518Smarcel#include <stdarg.h> 34115518Smarcel#include <stdio.h> 35124191Snectar#include <stdlib.h> 36124191Snectar#include <string.h> 37115518Smarcel 38115518Smarcelstruct fdesc { 39115518Smarcel uint64_t ip; 40115518Smarcel uint64_t gp; 41115518Smarcel}; 42115518Smarcel 43115518Smarceltypedef void (*func_t)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, 44115518Smarcel uint64_t, uint64_t, uint64_t); 45115518Smarcel 46115518Smarcelstatic __inline uint64_t * 47115518Smarcelspill(uint64_t *bsp, uint64_t arg) 48115518Smarcel{ 49115518Smarcel *bsp++ = arg; 50115518Smarcel if (((intptr_t)bsp & 0x1ff) == 0x1f8) 51115518Smarcel *bsp++ = 0; 52115518Smarcel return (bsp); 53115518Smarcel} 54115518Smarcel 55115518Smarcelstatic void 56115518Smarcelctx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args) 57115518Smarcel{ 58115518Smarcel 59115518Smarcel (*func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], 60115518Smarcel args[7]); 61115518Smarcel if (ucp->uc_link == NULL) 62115518Smarcel exit(0); 63115518Smarcel setcontext((const ucontext_t *)ucp->uc_link); 64115518Smarcel /* should never get here */ 65115518Smarcel abort(); 66115518Smarcel /* NOTREACHED */ 67115518Smarcel} 68115518Smarcel 69115518Smarcel__weak_reference(__makecontext, makecontext); 70115518Smarcel 71115518Smarcelvoid 72115518Smarcel__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) 73115518Smarcel{ 74115518Smarcel uint64_t *args, *bsp; 75115518Smarcel va_list ap; 76115518Smarcel int i; 77115518Smarcel 78115518Smarcel /* 79115518Smarcel * Drop the ball completely if something's not right. We only 80115518Smarcel * support general registers as arguments and not more than 8 81115518Smarcel * of them. Things get hairy if we need to support FP registers 82115518Smarcel * (alignment issues) or more than 8 arguments (stack based). 83115518Smarcel */ 84115518Smarcel if (argc < 0 || argc > 8 || ucp == NULL || 85115518Smarcel ucp->uc_stack.ss_sp == NULL || (ucp->uc_stack.ss_size & 15) || 86115518Smarcel ((intptr_t)ucp->uc_stack.ss_sp & 15) || 87115518Smarcel ucp->uc_stack.ss_size < MINSIGSTKSZ) 88115518Smarcel abort(); 89115518Smarcel 90115518Smarcel /* 91115518Smarcel * Copy the arguments of function 'func' onto the (memory) stack. 92115518Smarcel * Always take up space for 8 arguments. 93115518Smarcel */ 94115518Smarcel va_start(ap, argc); 95115518Smarcel args = (uint64_t*)(ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) - 8; 96115518Smarcel i = 0; 97115518Smarcel while (i < argc) 98115518Smarcel args[i++] = va_arg(ap, uint64_t); 99115518Smarcel while (i < 8) 100115518Smarcel args[i++] = 0; 101115518Smarcel va_end(ap); 102115518Smarcel 103115518Smarcel /* 104115518Smarcel * Push (spill) the arguments of the context wrapper onto the register 105115518Smarcel * stack. They get loaded by the RSE on a context switch. 106115518Smarcel */ 107115518Smarcel bsp = (uint64_t*)ucp->uc_stack.ss_sp; 108115518Smarcel bsp = spill(bsp, (intptr_t)ucp); 109115518Smarcel bsp = spill(bsp, (intptr_t)func); 110115518Smarcel bsp = spill(bsp, (intptr_t)args); 111115518Smarcel 112115518Smarcel /* 113115518Smarcel * Setup the MD portion of the context. 114115518Smarcel */ 115115518Smarcel memset(&ucp->uc_mcontext, 0, sizeof(ucp->uc_mcontext)); 116115518Smarcel ucp->uc_mcontext.mc_special.sp = (intptr_t)args - 16; 117115518Smarcel ucp->uc_mcontext.mc_special.bspstore = (intptr_t)bsp; 118115657Smarcel ucp->uc_mcontext.mc_special.pfs = (3 << 7) | 3; 119115518Smarcel ucp->uc_mcontext.mc_special.rsc = 0xf; 120115518Smarcel ucp->uc_mcontext.mc_special.rp = ((struct fdesc*)ctx_wrapper)->ip; 121115657Smarcel ucp->uc_mcontext.mc_special.gp = ((struct fdesc*)ctx_wrapper)->gp; 122115518Smarcel ucp->uc_mcontext.mc_special.fpsr = IA64_FPSR_DEFAULT; 123115518Smarcel} 124