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