1840b91ccSNathan Whitehorn /* 2840b91ccSNathan Whitehorn * Copyright (c) 2004 Suleiman Souhlal 3840b91ccSNathan Whitehorn * All rights reserved. 4840b91ccSNathan Whitehorn * 5840b91ccSNathan Whitehorn * Redistribution and use in source and binary forms, with or without 6840b91ccSNathan Whitehorn * modification, are permitted provided that the following conditions 7840b91ccSNathan Whitehorn * are met: 8840b91ccSNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 9840b91ccSNathan Whitehorn * notice, this list of conditions and the following disclaimer. 10840b91ccSNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 11840b91ccSNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 12840b91ccSNathan Whitehorn * documentation and/or other materials provided with the distribution. 13840b91ccSNathan Whitehorn * 14840b91ccSNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15840b91ccSNathan Whitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16840b91ccSNathan Whitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17840b91ccSNathan Whitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18840b91ccSNathan Whitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19840b91ccSNathan Whitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20840b91ccSNathan Whitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21840b91ccSNathan Whitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22840b91ccSNathan Whitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23840b91ccSNathan Whitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24840b91ccSNathan Whitehorn * SUCH DAMAGE. 25840b91ccSNathan Whitehorn */ 26840b91ccSNathan Whitehorn 27840b91ccSNathan Whitehorn #include <sys/cdefs.h> 28840b91ccSNathan Whitehorn __FBSDID("$FreeBSD$"); 29840b91ccSNathan Whitehorn 30840b91ccSNathan Whitehorn #include <sys/param.h> 31840b91ccSNathan Whitehorn 32840b91ccSNathan Whitehorn #include <stdarg.h> 33840b91ccSNathan Whitehorn #include <stdlib.h> 34840b91ccSNathan Whitehorn #include <unistd.h> 35840b91ccSNathan Whitehorn #include <stdio.h> 36840b91ccSNathan Whitehorn #include <ucontext.h> 37840b91ccSNathan Whitehorn 38840b91ccSNathan Whitehorn __weak_reference(__makecontext, makecontext); 39840b91ccSNathan Whitehorn 40840b91ccSNathan Whitehorn void _ctx_done(ucontext_t *ucp); 41840b91ccSNathan Whitehorn void _ctx_start(void); 42840b91ccSNathan Whitehorn 43840b91ccSNathan Whitehorn void 44840b91ccSNathan Whitehorn _ctx_done(ucontext_t *ucp) 45840b91ccSNathan Whitehorn { 46840b91ccSNathan Whitehorn if (ucp->uc_link == NULL) 47840b91ccSNathan Whitehorn exit(0); 48840b91ccSNathan Whitehorn else { 49840b91ccSNathan Whitehorn /* invalidate context */ 50840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_len = 0; 51840b91ccSNathan Whitehorn 52840b91ccSNathan Whitehorn setcontext((const ucontext_t *)ucp->uc_link); 53840b91ccSNathan Whitehorn 54840b91ccSNathan Whitehorn abort(); /* should never return from above call */ 55840b91ccSNathan Whitehorn } 56840b91ccSNathan Whitehorn } 57840b91ccSNathan Whitehorn 58840b91ccSNathan Whitehorn void 59840b91ccSNathan Whitehorn __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...) 60840b91ccSNathan Whitehorn { 61840b91ccSNathan Whitehorn mcontext_t *mc; 62840b91ccSNathan Whitehorn char *sp; 63840b91ccSNathan Whitehorn va_list ap; 64840b91ccSNathan Whitehorn int i, regargs, stackargs; 65840b91ccSNathan Whitehorn 66840b91ccSNathan Whitehorn /* Sanity checks */ 67840b91ccSNathan Whitehorn if ((ucp == NULL) || (argc < 0) || (argc > NCARGS) 68840b91ccSNathan Whitehorn || (ucp->uc_stack.ss_sp == NULL) 69840b91ccSNathan Whitehorn || (ucp->uc_stack.ss_size < MINSIGSTKSZ)) { 70840b91ccSNathan Whitehorn /* invalidate context */ 71840b91ccSNathan Whitehorn ucp->uc_mcontext.mc_len = 0; 72840b91ccSNathan Whitehorn return; 73840b91ccSNathan Whitehorn } 74840b91ccSNathan Whitehorn 75840b91ccSNathan Whitehorn /* 76840b91ccSNathan Whitehorn * The stack must have space for the frame pointer, saved 77840b91ccSNathan Whitehorn * link register, overflow arguments, and be 16-byte 78840b91ccSNathan Whitehorn * aligned. 79840b91ccSNathan Whitehorn */ 80840b91ccSNathan Whitehorn stackargs = (argc > 8) ? argc - 8 : 0; 81840b91ccSNathan Whitehorn sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size 82840b91ccSNathan Whitehorn - sizeof(uintptr_t)*(stackargs + 2); 83840b91ccSNathan Whitehorn sp = (char *)((uintptr_t)sp & ~0x1f); 84840b91ccSNathan Whitehorn 85840b91ccSNathan Whitehorn mc = &ucp->uc_mcontext; 86840b91ccSNathan Whitehorn 87840b91ccSNathan Whitehorn /* 88840b91ccSNathan Whitehorn * Up to 8 register args. Assumes all args are 64-bit and 89840b91ccSNathan Whitehorn * integer only. Not sure how to cater for floating point. 90840b91ccSNathan Whitehorn */ 91840b91ccSNathan Whitehorn regargs = (argc > 8) ? 8 : argc; 92840b91ccSNathan Whitehorn va_start(ap, argc); 93840b91ccSNathan Whitehorn for (i = 0; i < regargs; i++) 94840b91ccSNathan Whitehorn mc->mc_gpr[3 + i] = va_arg(ap, uint64_t); 95840b91ccSNathan Whitehorn 96840b91ccSNathan Whitehorn /* 97840b91ccSNathan Whitehorn * Overflow args go onto the stack 98840b91ccSNathan Whitehorn */ 99840b91ccSNathan Whitehorn if (argc > 8) { 100840b91ccSNathan Whitehorn uint64_t *argp; 101840b91ccSNathan Whitehorn 102840b91ccSNathan Whitehorn /* Skip past frame pointer and saved LR */ 103840b91ccSNathan Whitehorn argp = (uint64_t *)sp + 6; 104840b91ccSNathan Whitehorn 105840b91ccSNathan Whitehorn for (i = 0; i < stackargs; i++) 106840b91ccSNathan Whitehorn *argp++ = va_arg(ap, uint64_t); 107840b91ccSNathan Whitehorn } 108840b91ccSNathan Whitehorn va_end(ap); 109840b91ccSNathan Whitehorn 110840b91ccSNathan Whitehorn /* 111840b91ccSNathan Whitehorn * Use caller-saved regs 14/15 to hold params that _ctx_start 112840b91ccSNathan Whitehorn * will use to invoke the user-supplied func 113840b91ccSNathan Whitehorn */ 114*351f3052SNathan Whitehorn mc->mc_srr0 = *(uintptr_t *)_ctx_start; 115840b91ccSNathan Whitehorn mc->mc_gpr[1] = (uintptr_t) sp; /* new stack pointer */ 116840b91ccSNathan Whitehorn mc->mc_gpr[14] = (uintptr_t) start; /* r14 <- start */ 117840b91ccSNathan Whitehorn mc->mc_gpr[15] = (uintptr_t) ucp; /* r15 <- ucp */ 118840b91ccSNathan Whitehorn } 119