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