1*ed093b41SRobert Mustacchi /*
2*ed093b41SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*ed093b41SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*ed093b41SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*ed093b41SRobert Mustacchi  * 1.0 of the CDDL.
6*ed093b41SRobert Mustacchi  *
7*ed093b41SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*ed093b41SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*ed093b41SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*ed093b41SRobert Mustacchi  */
11*ed093b41SRobert Mustacchi 
12*ed093b41SRobert Mustacchi /*
13*ed093b41SRobert Mustacchi  * Copyright 2023 Oxide Computer Company
14*ed093b41SRobert Mustacchi  */
15*ed093b41SRobert Mustacchi 
16*ed093b41SRobert Mustacchi /*
17*ed093b41SRobert Mustacchi  * Basic test for getcontext_extd() variant. We have two cases that we need to
18*ed093b41SRobert Mustacchi  * consider. A ucontext_t that is allocated and initialized from the stack and
19*ed093b41SRobert Mustacchi  * then one that comes from a ucontext_alloc(). We test both that setcontext()
20*ed093b41SRobert Mustacchi  * and makecontext() work with these.
21*ed093b41SRobert Mustacchi  */
22*ed093b41SRobert Mustacchi 
23*ed093b41SRobert Mustacchi #include <ucontext.h>
24*ed093b41SRobert Mustacchi #include <unistd.h>
25*ed093b41SRobert Mustacchi #include <stdlib.h>
26*ed093b41SRobert Mustacchi #include <err.h>
27*ed093b41SRobert Mustacchi #include <string.h>
28*ed093b41SRobert Mustacchi #include <errno.h>
29*ed093b41SRobert Mustacchi #include <upanic.h>
30*ed093b41SRobert Mustacchi 
31*ed093b41SRobert Mustacchi #define	STACK_MAGIC	42
32*ed093b41SRobert Mustacchi #define	EXIT_MAGIC	23
33*ed093b41SRobert Mustacchi static volatile uint32_t count = 0;
34*ed093b41SRobert Mustacchi static volatile uint32_t stack_count = 0;
35*ed093b41SRobert Mustacchi 
36*ed093b41SRobert Mustacchi static void
successful_exit(uint32_t test)37*ed093b41SRobert Mustacchi successful_exit(uint32_t test)
38*ed093b41SRobert Mustacchi {
39*ed093b41SRobert Mustacchi 	if (test != EXIT_MAGIC) {
40*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: makecontext had wrong "
41*ed093b41SRobert Mustacchi 		    "argument, found 0x%x, expected 0x%x", test, EXIT_MAGIC);
42*ed093b41SRobert Mustacchi 	}
43*ed093b41SRobert Mustacchi 
44*ed093b41SRobert Mustacchi 	printf("TEST PASSED: makecontext called with right argument\n");
45*ed093b41SRobert Mustacchi 	exit(0);
46*ed093b41SRobert Mustacchi }
47*ed093b41SRobert Mustacchi 
48*ed093b41SRobert Mustacchi static void
getcontext_stack(uint32_t test)49*ed093b41SRobert Mustacchi getcontext_stack(uint32_t test)
50*ed093b41SRobert Mustacchi {
51*ed093b41SRobert Mustacchi 	ucontext_t ctx;
52*ed093b41SRobert Mustacchi 
53*ed093b41SRobert Mustacchi 	if (test != STACK_MAGIC) {
54*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: makecontext had wrong "
55*ed093b41SRobert Mustacchi 		    "argument, found 0x%x, expected 0x%x", test, STACK_MAGIC);
56*ed093b41SRobert Mustacchi 	}
57*ed093b41SRobert Mustacchi 
58*ed093b41SRobert Mustacchi 	(void) memset(&ctx, 0, sizeof (ctx));
59*ed093b41SRobert Mustacchi 
60*ed093b41SRobert Mustacchi 	if (getcontext_extd(&ctx, 0) != 0) {
61*ed093b41SRobert Mustacchi 		err(EXIT_FAILURE, "failed to get extended context from stack");
62*ed093b41SRobert Mustacchi 	}
63*ed093b41SRobert Mustacchi 
64*ed093b41SRobert Mustacchi 	count++;
65*ed093b41SRobert Mustacchi 	if (count < 5) {
66*ed093b41SRobert Mustacchi 		const char *msg = "stack setcontext returned, sorry";
67*ed093b41SRobert Mustacchi 		(void) setcontext(&ctx);
68*ed093b41SRobert Mustacchi 		upanic(msg, strlen(msg) + 1);
69*ed093b41SRobert Mustacchi 	}
70*ed093b41SRobert Mustacchi 
71*ed093b41SRobert Mustacchi 	(void) printf("TEST PASSED: stack ucontext_t / getcontext_extd() / "
72*ed093b41SRobert Mustacchi 	    "setcontext() combo worked\n");
73*ed093b41SRobert Mustacchi 	ctx.uc_stack.ss_sp = calloc(SIGSTKSZ, sizeof (uint8_t));
74*ed093b41SRobert Mustacchi 	if (ctx.uc_stack.ss_sp == NULL) {
75*ed093b41SRobert Mustacchi 		err(EXIT_FAILURE, "failed to allocate second makecontext "
76*ed093b41SRobert Mustacchi 		    "stack");
77*ed093b41SRobert Mustacchi 	}
78*ed093b41SRobert Mustacchi 	ctx.uc_stack.ss_size = SIGSTKSZ;
79*ed093b41SRobert Mustacchi 	ctx.uc_stack.ss_flags = 0;
80*ed093b41SRobert Mustacchi 	makecontext(&ctx, successful_exit, 1, EXIT_MAGIC);
81*ed093b41SRobert Mustacchi 	(void) setcontext(&ctx);
82*ed093b41SRobert Mustacchi 
83*ed093b41SRobert Mustacchi 	err(EXIT_FAILURE, "TEST FAILED: stack ucontext_t / makecontext() "
84*ed093b41SRobert Mustacchi 	    "returned from setcontext()");
85*ed093b41SRobert Mustacchi }
86*ed093b41SRobert Mustacchi 
87*ed093b41SRobert Mustacchi int
main(void)88*ed093b41SRobert Mustacchi main(void)
89*ed093b41SRobert Mustacchi {
90*ed093b41SRobert Mustacchi 	ucontext_t *ctx = ucontext_alloc(0);
91*ed093b41SRobert Mustacchi 	if (ctx == NULL) {
92*ed093b41SRobert Mustacchi 		err(EXIT_FAILURE, "failed to get allocate ucontext_t");
93*ed093b41SRobert Mustacchi 	}
94*ed093b41SRobert Mustacchi 
95*ed093b41SRobert Mustacchi 	if (getcontext_extd(ctx, 23) == 0) {
96*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: getcontext_extd worked with "
97*ed093b41SRobert Mustacchi 		    "bad flags");
98*ed093b41SRobert Mustacchi 	}
99*ed093b41SRobert Mustacchi 
100*ed093b41SRobert Mustacchi 	if (errno != EINVAL) {
101*ed093b41SRobert Mustacchi 		errx(EXIT_FAILURE, "TEST FAILED: getcontext_extd returned "
102*ed093b41SRobert Mustacchi 		    "wrong errno for bad flags: 0x%x", errno);
103*ed093b41SRobert Mustacchi 	}
104*ed093b41SRobert Mustacchi 
105*ed093b41SRobert Mustacchi 	if (getcontext_extd(ctx, 0) != 0) {
106*ed093b41SRobert Mustacchi 		err(EXIT_FAILURE, "failed to get extended context");
107*ed093b41SRobert Mustacchi 	}
108*ed093b41SRobert Mustacchi 
109*ed093b41SRobert Mustacchi 	count++;
110*ed093b41SRobert Mustacchi 	if (count < 5) {
111*ed093b41SRobert Mustacchi 		const char *msg = "setcontext returned, sorry";
112*ed093b41SRobert Mustacchi 		(void) setcontext(ctx);
113*ed093b41SRobert Mustacchi 		upanic(msg, strlen(msg) + 1);
114*ed093b41SRobert Mustacchi 	}
115*ed093b41SRobert Mustacchi 
116*ed093b41SRobert Mustacchi 	(void) printf("TEST PASSED: ucontext_alloc() / getcontext_extd() / "
117*ed093b41SRobert Mustacchi 	    "setcontext() combo worked\n");
118*ed093b41SRobert Mustacchi 	ctx->uc_stack.ss_sp = calloc(SIGSTKSZ, sizeof (uint8_t));
119*ed093b41SRobert Mustacchi 	if (ctx->uc_stack.ss_sp == NULL) {
120*ed093b41SRobert Mustacchi 		err(EXIT_FAILURE, "failed to allocate first makecontext "
121*ed093b41SRobert Mustacchi 		    "stack");
122*ed093b41SRobert Mustacchi 	}
123*ed093b41SRobert Mustacchi 	ctx->uc_stack.ss_size = SIGSTKSZ;
124*ed093b41SRobert Mustacchi 	ctx->uc_stack.ss_flags = 0;
125*ed093b41SRobert Mustacchi 	makecontext(ctx, getcontext_stack, 1, STACK_MAGIC);
126*ed093b41SRobert Mustacchi 	(void) setcontext(ctx);
127*ed093b41SRobert Mustacchi 
128*ed093b41SRobert Mustacchi 	warn("TEST FAILED: failed to setcontext() to makecontext() from "
129*ed093b41SRobert Mustacchi 	    "ucontext_alloc() / getcontext_extd()");
130*ed093b41SRobert Mustacchi 	return (EXIT_FAILURE);
131*ed093b41SRobert Mustacchi }
132