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  * This test goes through and verifies that the FPU contents are properly
  18  * restored with a setcontext call.
  19  */
  20 
  21 #include <err.h>
  22 #include <stdlib.h>
  23 #include <ucontext.h>
  24 #include <limits.h>
  25 
  26 #include "xsave_util.h"
  27 
  28 xsu_fpu_t init_set, override, found;
  29 volatile int exit_status = EXIT_SUCCESS;
  30 
  31 static void
  32 setcontext_restore_check(uint32_t hwsup)
  33 {
  34         xsu_getfpu(&found, hwsup);
  35         if (xsu_same(&init_set, &found, hwsup)) {
  36                 (void) printf("TEST PASSED: setcontext() correctly restored "
  37                     "clobbered FPU contents\n");
  38                 exit(exit_status);
  39         } else {
  40                 errx(EXIT_FAILURE, "TEST_FAILED: setcontext() did not properly "
  41                     "restore clobbered FPU contents");
  42         }
  43 }
  44 
  45 int
  46 main(void)
  47 {
  48         ucontext_t *ctx;
  49         uint32_t start = arc4random();
  50         uint32_t hwsup = xsu_hwsupport();
  51 
  52         ctx = ucontext_alloc(0);
  53         if (ctx == NULL) {
  54                 err(EXIT_FAILURE, "failed to get allocate ucontext_t");
  55         }
  56         (void) printf("filling starting at 0x%x\n", start);
  57         xsu_fill(&init_set, hwsup, start);
  58         xsu_fill(&override, hwsup, start + INT_MAX);
  59         xsu_setfpu(&init_set, hwsup);
  60 
  61         if (getcontext_extd(ctx, 0) != 0) {
  62                 err(EXIT_FAILURE, "failed to get extended context");
  63         }
  64 
  65         makecontext(ctx, setcontext_restore_check, 1, hwsup);
  66         xsu_setfpu(&override, hwsup);
  67         xsu_getfpu(&found, hwsup);
  68         if (!xsu_same(&override, &found, hwsup)) {
  69                 warnx("TEST FAILED: override FPU data not found!");
  70                 exit_status = EXIT_FAILURE;
  71         }
  72         (void) setcontext(ctx);
  73 
  74         err(EXIT_FAILURE, "TEST FAILED: set context did not work!");
  75 }