hc
2023-05-26 a23f51ed7a39e452c1037343a84d7db1ca2c5bd7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * Copyright 2016, Cyril Bur, IBM Corp.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 *
 * Test the kernel's signal frame code.
 *
 * The kernel sets up two sets of ucontexts if the signal was to be
 * delivered while the thread was in a transaction.
 * Expected behaviour is that the checkpointed state is in the user
 * context passed to the signal handler. The speculated state can be
 * accessed with the uc_link pointer.
 *
 * The rationale for this is that if TM unaware code (which linked
 * against TM libs) installs a signal handler it will not know of the
 * speculative nature of the 'live' registers and may infer the wrong
 * thing.
 */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
 
#include <altivec.h>
 
#include "utils.h"
#include "tm.h"
 
#define MAX_ATTEMPT 500000
 
#define NV_VMX_REGS 12
 
long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
 
static sig_atomic_t fail;
 
vector int vms[] = {
   {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
   {13,14,15,16},{17,18,19,20},{21,22,23,24},
   {25,26,27,28},{29,30,31,32},{33,34,35,36},
   {37,38,39,40},{41,42,43,44},{45,46,47,48},
   {-1, -2, -3, -4}, {-5, -6, -7, -8}, {-9, -10,-11,-12},
   {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
   {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
   {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
};
 
static void signal_usr1(int signum, siginfo_t *info, void *uc)
{
   int i;
   ucontext_t *ucp = uc;
   ucontext_t *tm_ucp = ucp->uc_link;
 
   for (i = 0; i < NV_VMX_REGS && !fail; i++) {
       fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[i + 20],
               &vms[i], sizeof(vector int));
       fail |= memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[i + 20],
               &vms[i + NV_VMX_REGS], sizeof (vector int));
 
       if (fail) {
           int j;
 
           fprintf(stderr, "Failed on %d vmx 0x", i);
           for (j = 0; j < 4; j++)
               fprintf(stderr, "%04x", ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
           fprintf(stderr, " vs 0x");
           for (j = 0 ; j < 4; j++)
               fprintf(stderr, "%04x", tm_ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
           fprintf(stderr, "\n");
       }
   }
}
 
static int tm_signal_context_chk()
{
   struct sigaction act;
   int i;
   long rc;
   pid_t pid = getpid();
 
   SKIP_IF(!have_htm());
 
   act.sa_sigaction = signal_usr1;
   sigemptyset(&act.sa_mask);
   act.sa_flags = SA_SIGINFO;
   if (sigaction(SIGUSR1, &act, NULL) < 0) {
       perror("sigaction sigusr1");
       exit(1);
   }
 
   i = 0;
   while (i < MAX_ATTEMPT && !fail) {
       rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL);
       FAIL_IF(rc != pid);
       i++;
   }
 
   return fail;
}
 
int main(void)
{
   return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vmx");
}