xref: /freebsd/lib/libc/powerpc64/gen/makecontext.c (revision 840b91cc52085d26c112e99d733f71eb92c3ff54)
1*840b91ccSNathan Whitehorn /*
2*840b91ccSNathan Whitehorn  * Copyright (c) 2004 Suleiman Souhlal
3*840b91ccSNathan Whitehorn  * All rights reserved.
4*840b91ccSNathan Whitehorn  *
5*840b91ccSNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
6*840b91ccSNathan Whitehorn  * modification, are permitted provided that the following conditions
7*840b91ccSNathan Whitehorn  * are met:
8*840b91ccSNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
9*840b91ccSNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
10*840b91ccSNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
11*840b91ccSNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
12*840b91ccSNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
13*840b91ccSNathan Whitehorn  *
14*840b91ccSNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*840b91ccSNathan Whitehorn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*840b91ccSNathan Whitehorn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*840b91ccSNathan Whitehorn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*840b91ccSNathan Whitehorn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*840b91ccSNathan Whitehorn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*840b91ccSNathan Whitehorn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*840b91ccSNathan Whitehorn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*840b91ccSNathan Whitehorn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*840b91ccSNathan Whitehorn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*840b91ccSNathan Whitehorn  * SUCH DAMAGE.
25*840b91ccSNathan Whitehorn  */
26*840b91ccSNathan Whitehorn 
27*840b91ccSNathan Whitehorn #include <sys/cdefs.h>
28*840b91ccSNathan Whitehorn __FBSDID("$FreeBSD$");
29*840b91ccSNathan Whitehorn 
30*840b91ccSNathan Whitehorn #include <sys/param.h>
31*840b91ccSNathan Whitehorn 
32*840b91ccSNathan Whitehorn #include <stdarg.h>
33*840b91ccSNathan Whitehorn #include <stdlib.h>
34*840b91ccSNathan Whitehorn #include <unistd.h>
35*840b91ccSNathan Whitehorn #include <stdio.h>
36*840b91ccSNathan Whitehorn #include <ucontext.h>
37*840b91ccSNathan Whitehorn 
38*840b91ccSNathan Whitehorn __weak_reference(__makecontext, makecontext);
39*840b91ccSNathan Whitehorn 
40*840b91ccSNathan Whitehorn void _ctx_done(ucontext_t *ucp);
41*840b91ccSNathan Whitehorn void _ctx_start(void);
42*840b91ccSNathan Whitehorn 
43*840b91ccSNathan Whitehorn void
44*840b91ccSNathan Whitehorn _ctx_done(ucontext_t *ucp)
45*840b91ccSNathan Whitehorn {
46*840b91ccSNathan Whitehorn 	if (ucp->uc_link == NULL)
47*840b91ccSNathan Whitehorn 		exit(0);
48*840b91ccSNathan Whitehorn 	else {
49*840b91ccSNathan Whitehorn 		/* invalidate context */
50*840b91ccSNathan Whitehorn 		ucp->uc_mcontext.mc_len = 0;
51*840b91ccSNathan Whitehorn 
52*840b91ccSNathan Whitehorn 		setcontext((const ucontext_t *)ucp->uc_link);
53*840b91ccSNathan Whitehorn 
54*840b91ccSNathan Whitehorn 		abort(); /* should never return from above call */
55*840b91ccSNathan Whitehorn 	}
56*840b91ccSNathan Whitehorn }
57*840b91ccSNathan Whitehorn 
58*840b91ccSNathan Whitehorn void
59*840b91ccSNathan Whitehorn __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
60*840b91ccSNathan Whitehorn {
61*840b91ccSNathan Whitehorn 	mcontext_t *mc;
62*840b91ccSNathan Whitehorn 	char *sp;
63*840b91ccSNathan Whitehorn 	va_list ap;
64*840b91ccSNathan Whitehorn 	int i, regargs, stackargs;
65*840b91ccSNathan Whitehorn 
66*840b91ccSNathan Whitehorn 	/* Sanity checks */
67*840b91ccSNathan Whitehorn 	if ((ucp == NULL) || (argc < 0) || (argc > NCARGS)
68*840b91ccSNathan Whitehorn 	    || (ucp->uc_stack.ss_sp == NULL)
69*840b91ccSNathan Whitehorn 	    || (ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
70*840b91ccSNathan Whitehorn 		/* invalidate context */
71*840b91ccSNathan Whitehorn 		ucp->uc_mcontext.mc_len = 0;
72*840b91ccSNathan Whitehorn 		return;
73*840b91ccSNathan Whitehorn 	}
74*840b91ccSNathan Whitehorn 
75*840b91ccSNathan Whitehorn 	/*
76*840b91ccSNathan Whitehorn 	 * The stack must have space for the frame pointer, saved
77*840b91ccSNathan Whitehorn 	 * link register, overflow arguments, and be 16-byte
78*840b91ccSNathan Whitehorn 	 * aligned.
79*840b91ccSNathan Whitehorn 	 */
80*840b91ccSNathan Whitehorn 	stackargs = (argc > 8) ? argc - 8 : 0;
81*840b91ccSNathan Whitehorn 	sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size
82*840b91ccSNathan Whitehorn 		- sizeof(uintptr_t)*(stackargs + 2);
83*840b91ccSNathan Whitehorn 	sp = (char *)((uintptr_t)sp & ~0x1f);
84*840b91ccSNathan Whitehorn 
85*840b91ccSNathan Whitehorn 	mc = &ucp->uc_mcontext;
86*840b91ccSNathan Whitehorn 
87*840b91ccSNathan Whitehorn 	/*
88*840b91ccSNathan Whitehorn 	 * Up to 8 register args. Assumes all args are 64-bit and
89*840b91ccSNathan Whitehorn 	 * integer only. Not sure how to cater for floating point.
90*840b91ccSNathan Whitehorn 	 */
91*840b91ccSNathan Whitehorn 	regargs = (argc > 8) ? 8 : argc;
92*840b91ccSNathan Whitehorn 	va_start(ap, argc);
93*840b91ccSNathan Whitehorn 	for (i = 0; i < regargs; i++)
94*840b91ccSNathan Whitehorn 		mc->mc_gpr[3 + i] = va_arg(ap, uint64_t);
95*840b91ccSNathan Whitehorn 
96*840b91ccSNathan Whitehorn 	/*
97*840b91ccSNathan Whitehorn 	 * Overflow args go onto the stack
98*840b91ccSNathan Whitehorn 	 */
99*840b91ccSNathan Whitehorn 	if (argc > 8) {
100*840b91ccSNathan Whitehorn 		uint64_t *argp;
101*840b91ccSNathan Whitehorn 
102*840b91ccSNathan Whitehorn 		/* Skip past frame pointer and saved LR */
103*840b91ccSNathan Whitehorn 		argp = (uint64_t *)sp + 6;
104*840b91ccSNathan Whitehorn 
105*840b91ccSNathan Whitehorn 		for (i = 0; i < stackargs; i++)
106*840b91ccSNathan Whitehorn 			*argp++ = va_arg(ap, uint64_t);
107*840b91ccSNathan Whitehorn 	}
108*840b91ccSNathan Whitehorn 	va_end(ap);
109*840b91ccSNathan Whitehorn 
110*840b91ccSNathan Whitehorn 	/*
111*840b91ccSNathan Whitehorn 	 * Use caller-saved regs 14/15 to hold params that _ctx_start
112*840b91ccSNathan Whitehorn 	 * will use to invoke the user-supplied func
113*840b91ccSNathan Whitehorn 	 */
114*840b91ccSNathan Whitehorn 	mc->mc_srr0 = (uintptr_t) _ctx_start;
115*840b91ccSNathan Whitehorn 	mc->mc_gpr[1] = (uintptr_t) sp;		/* new stack pointer */
116*840b91ccSNathan Whitehorn 	mc->mc_gpr[14] = (uintptr_t) start;	/* r14 <- start */
117*840b91ccSNathan Whitehorn 	mc->mc_gpr[15] = (uintptr_t) ucp;	/* r15 <- ucp */
118*840b91ccSNathan Whitehorn }
119