makecontext.c revision 256281
1139823Simp/* 2139365Srik * Copyright (c) 2004 Suleiman Souhlal 3139365Srik * All rights reserved. 4139365Srik * 5139365Srik * Redistribution and use in source and binary forms, with or without 6139365Srik * modification, are permitted provided that the following conditions 7139365Srik * are met: 8139365Srik * 1. Redistributions of source code must retain the above copyright 9139365Srik * notice, this list of conditions and the following disclaimer. 10139365Srik * 2. Redistributions in binary form must reproduce the above copyright 11139365Srik * notice, this list of conditions and the following disclaimer in the 12139365Srik * documentation and/or other materials provided with the distribution. 13139365Srik * 14139365Srik * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15139365Srik * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16139365Srik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17139365Srik * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18139365Srik * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19139365Srik * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20139365Srik * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21139365Srik * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22139365Srik * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23139365Srik * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24139365Srik * SUCH DAMAGE. 25139365Srik */ 26139365Srik 27139365Srik#include <sys/cdefs.h> 28139365Srik__FBSDID("$FreeBSD: stable/10/lib/libc/powerpc64/gen/makecontext.c 234003 2012-04-07 22:28:50Z nwhitehorn $"); 29139365Srik 30139365Srik#include <sys/param.h> 31139365Srik 32139365Srik#include <stdarg.h> 33139365Srik#include <stdlib.h> 34139365Srik#include <unistd.h> 35139365Srik#include <stdio.h> 36139365Srik#include <ucontext.h> 37139365Srik 38139365Srik__weak_reference(__makecontext, makecontext); 39139365Srik 40139365Srikvoid _ctx_done(ucontext_t *ucp); 41139365Srikvoid _ctx_start(void); 42139365Srik 43139365Srikvoid 44139365Srik_ctx_done(ucontext_t *ucp) 45139365Srik{ 46139365Srik if (ucp->uc_link == NULL) 47139365Srik exit(0); 48139365Srik else { 49139365Srik /* invalidate context */ 50139365Srik ucp->uc_mcontext.mc_len = 0; 51139365Srik 52139365Srik setcontext((const ucontext_t *)ucp->uc_link); 53139365Srik 54139365Srik abort(); /* should never return from above call */ 55139365Srik } 56139365Srik} 57139365Srik 58139365Srikvoid 59139365Srik__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...) 60139365Srik{ 61139365Srik mcontext_t *mc; 62139365Srik char *sp; 63139365Srik va_list ap; 64139365Srik int i, regargs, stackargs; 65139365Srik 66139365Srik /* Sanity checks */ 67139365Srik if ((ucp == NULL) || (argc < 0) || (argc > NCARGS) 68139365Srik || (ucp->uc_stack.ss_sp == NULL) 69139365Srik || (ucp->uc_stack.ss_size < MINSIGSTKSZ)) { 70139365Srik /* invalidate context */ 71139365Srik ucp->uc_mcontext.mc_len = 0; 72139365Srik return; 73139365Srik } 74139365Srik 75139365Srik /* 76139365Srik * The stack must have space for the frame pointer, saved 77139365Srik * link register, overflow arguments, and be 16-byte 78139365Srik * aligned. 79139365Srik */ 80139365Srik stackargs = (argc > 8) ? argc - 8 : 0; 81139365Srik sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size 82139365Srik - sizeof(uintptr_t)*(stackargs + 2); 83139365Srik sp = (char *)((uintptr_t)sp & ~0x1f); 84139365Srik 85139365Srik mc = &ucp->uc_mcontext; 86139365Srik 87139365Srik /* 88139365Srik * Up to 8 register args. Assumes all args are 64-bit and 89139365Srik * integer only. Not sure how to cater for floating point. 90139365Srik */ 91139365Srik regargs = (argc > 8) ? 8 : argc; 92139365Srik va_start(ap, argc); 93139365Srik for (i = 0; i < regargs; i++) 94139365Srik mc->mc_gpr[3 + i] = va_arg(ap, uint64_t); 95139365Srik 96139365Srik /* 97139365Srik * Overflow args go onto the stack 98139365Srik */ 99139365Srik if (argc > 8) { 100139365Srik uint64_t *argp; 101139365Srik 102139365Srik /* Skip past frame pointer and saved LR */ 103139365Srik argp = (uint64_t *)sp + 6; 104139365Srik 105139365Srik for (i = 0; i < stackargs; i++) 106139365Srik *argp++ = va_arg(ap, uint64_t); 107139365Srik } 108139365Srik va_end(ap); 109139365Srik 110139365Srik /* 111139365Srik * Use caller-saved regs 14/15 to hold params that _ctx_start 112139365Srik * will use to invoke the user-supplied func 113139365Srik */ 114139365Srik mc->mc_srr0 = *(uintptr_t *)_ctx_start; 115139365Srik mc->mc_gpr[1] = (uintptr_t) sp; /* new stack pointer */ 116139365Srik mc->mc_gpr[14] = (uintptr_t) start; /* r14 <- start */ 117139365Srik mc->mc_gpr[15] = (uintptr_t) ucp; /* r15 <- ucp */ 118139365Srik} 119139365Srik