linux/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright 2016, Cyril Bur, IBM Corp.
   4 *
   5 * Test the kernel's signal frame code.
   6 *
   7 * The kernel sets up two sets of ucontexts if the signal was to be
   8 * delivered while the thread was in a transaction.
   9 * Expected behaviour is that the checkpointed state is in the user
  10 * context passed to the signal handler. The speculated state can be
  11 * accessed with the uc_link pointer.
  12 *
  13 * The rationale for this is that if TM unaware code (which linked
  14 * against TM libs) installs a signal handler it will not know of the
  15 * speculative nature of the 'live' registers and may infer the wrong
  16 * thing.
  17 */
  18
  19#include <stdlib.h>
  20#include <stdio.h>
  21#include <signal.h>
  22#include <unistd.h>
  23
  24#include <altivec.h>
  25
  26#include "utils.h"
  27#include "tm.h"
  28
  29#define MAX_ATTEMPT 500000
  30
  31#define NV_FPU_REGS 18
  32
  33long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
  34
  35/* Be sure there are 2x as many as there are NV FPU regs (2x18) */
  36static double fps[] = {
  37         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
  38        -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
  39};
  40
  41static sig_atomic_t fail;
  42
  43static void signal_usr1(int signum, siginfo_t *info, void *uc)
  44{
  45        int i;
  46        ucontext_t *ucp = uc;
  47        ucontext_t *tm_ucp = ucp->uc_link;
  48
  49        for (i = 0; i < NV_FPU_REGS && !fail; i++) {
  50                fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]);
  51                fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]);
  52                if (fail)
  53                        printf("Failed on %d FP %g or %g\n", i, ucp->uc_mcontext.fp_regs[i + 14], tm_ucp->uc_mcontext.fp_regs[i + 14]);
  54        }
  55}
  56
  57static int tm_signal_context_chk_fpu()
  58{
  59        struct sigaction act;
  60        int i;
  61        long rc;
  62        pid_t pid = getpid();
  63
  64        SKIP_IF(!have_htm());
  65
  66        act.sa_sigaction = signal_usr1;
  67        sigemptyset(&act.sa_mask);
  68        act.sa_flags = SA_SIGINFO;
  69        if (sigaction(SIGUSR1, &act, NULL) < 0) {
  70                perror("sigaction sigusr1");
  71                exit(1);
  72        }
  73
  74        i = 0;
  75        while (i < MAX_ATTEMPT && !fail) {
  76                rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL);
  77                FAIL_IF(rc != pid);
  78                i++;
  79        }
  80
  81        return fail;
  82}
  83
  84int main(void)
  85{
  86        return test_harness(tm_signal_context_chk_fpu, "tm_signal_context_chk_fpu");
  87}
  88