linux/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.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_GPR_REGS 18
  32
  33long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
  34
  35static sig_atomic_t fail;
  36
  37static long gps[] = { 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
  40static void signal_usr1(int signum, siginfo_t *info, void *uc)
  41{
  42        int i;
  43        ucontext_t *ucp = uc;
  44        ucontext_t *tm_ucp = ucp->uc_link;
  45
  46        for (i = 0; i < NV_GPR_REGS && !fail; i++) {
  47                fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]);
  48                fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]);
  49                if (fail)
  50                        printf("Failed on %d GPR %lu or %lu\n", i,
  51                                        ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]);
  52        }
  53}
  54
  55static int tm_signal_context_chk_gpr()
  56{
  57        struct sigaction act;
  58        int i;
  59        long rc;
  60        pid_t pid = getpid();
  61
  62        SKIP_IF(!have_htm());
  63
  64        act.sa_sigaction = signal_usr1;
  65        sigemptyset(&act.sa_mask);
  66        act.sa_flags = SA_SIGINFO;
  67        if (sigaction(SIGUSR1, &act, NULL) < 0) {
  68                perror("sigaction sigusr1");
  69                exit(1);
  70        }
  71
  72        i = 0;
  73        while (i < MAX_ATTEMPT && !fail) {
  74                rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL);
  75                FAIL_IF(rc != pid);
  76                i++;
  77        }
  78
  79        return fail;
  80}
  81
  82int main(void)
  83{
  84        return test_harness(tm_signal_context_chk_gpr, "tm_signal_context_chk_gpr");
  85}
  86