summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorGustavo Romero <gromero@linux.ibm.com>2019-08-14 16:52:11 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2019-08-25 20:47:54 -0400
commit9d535e200f09ce347afc38c81ec7f2901187e5f0 (patch)
treef4ad995f1e9676965eae556c71f90d83ca182088 /tools
parent7e04a46d84f73ef0f21d2257d6ba2a194c0f1511 (diff)
selftests/powerpc: Fix and enhance TM signal context tests
Currently TM signal context tests for GPR, FPR, VMX, and VSX registers print wrong register numbers (wrongly starting from register 0 instead of the first register in the non-volatile subset). Besides it the output when a mismatch happens is poor giving not much information about which context and which register mismatches, because it prints both contexts at the same time and not a comparison between the value that mismatches and the value expected and, moreover, it stops printing on the first mismatch, but it's important to know if there are other mismatches happening beyond the first one. For instance, this is the current output when a mismatch happens: test: tm_signal_context_chk_gpr tags: git_version:v5.2-8249-g02e970fae465-dirty Failed on 0 GPR 1 or 18446744073709551615 failure: tm_signal_context_chk_gpr test: tm_signal_context_chk_fpu tags: git_version:v5.2-8248-g09c289e3ef80 Failed on 0 FP -1 or -1 failure: tm_signal_context_chk_fpu test: tm_signal_context_chk_vmx tags: git_version:v5.2-8248-g09c289e3ef80 Failed on 0 vmx 0xfffffffffffffffefffffffdfffffffc vs 0xfffffffffffffffefffffffdfffffffc failure: tm_signal_context_chk_vmx test: tm_signal_context_chk_vsx tags: git_version:v5.2-8248-g09c289e3ef80 Failed on 0 vsx 0xfffffffffefffffffdfffffffcffffff vs 0xfffffffffefffffffdfffffffcffffff failure: tm_signal_context_chk_vsx This commit fixes the register numbers printed and enhances the error output by providing a full list of mismatching registers separated by the context (non-speculative or speculative context), for example: test: tm_signal_context_chk_gpr tags: git_version:v5.2-8249-g02e970fae465-dirty GPR14 (1st context) == 1 instead of -1 (expected) GPR15 (1st context) == 2 instead of -2 (expected) GPR14 (2nd context) == 0 instead of 18446744073709551615 (expected) GPR15 (2nd context) == 0 instead of 18446744073709551614 (expected) failure: tm_signal_context_chk_gpr test: tm_signal_context_chk_fpu tags: git_version:v5.2-8249-g02e970fae465-dirty FPR14 (1st context) == -1 instead of 1 (expected) FPR15 (1st context) == -2 instead of 2 (expected) failure: tm_signal_context_chk_fpu test: tm_signal_context_chk_vmx tags: git_version:v5.2-8249-g02e970fae465-dirty VMX20 (1st context) == 0xfffffffffffffffefffffffdfffffffc instead of 0x00000001000000020000000300000004 (expected) VMX21 (1st context) == 0xfffffffbfffffffafffffff9fffffff8 instead of 0x00000005000000060000000700000008 (expected) failure: tm_signal_context_chk_vmx test: tm_signal_context_chk_vsx tags: git_version:v5.2-8249-g02e970fae465-dirty VSX20 (1st context) == 0xfffffffffefffffffdfffffffcffffff instead of 0x00000001000000020000000300000004 (expected) VSX21 (1st context) == 0xfbfffffffafffffff9fffffff8ffffff instead of 0x00000005000000060000000700000008 (expected) failure: tm_signal_context_chk_vsx Finally, this commit adds comments to the tests in the hope that it will help people not so familiar with TM understand the tests. Signed-off-by: Gustavo Romero <gromero@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20190814205211.24840-1-gromero@linux.ibm.com
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c49
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c59
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c74
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c130
4 files changed, 228 insertions, 84 deletions
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
index d57c2d2ab6ec..254f912ad611 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
@@ -5,10 +5,11 @@
5 * Test the kernel's signal frame code. 5 * Test the kernel's signal frame code.
6 * 6 *
7 * The kernel sets up two sets of ucontexts if the signal was to be 7 * The kernel sets up two sets of ucontexts if the signal was to be
8 * delivered while the thread was in a transaction. 8 * delivered while the thread was in a transaction (referred too as
9 * first and second contexts).
9 * Expected behaviour is that the checkpointed state is in the user 10 * Expected behaviour is that the checkpointed state is in the user
10 * context passed to the signal handler. The speculated state can be 11 * context passed to the signal handler (first context). The speculated
11 * accessed with the uc_link pointer. 12 * state can be accessed with the uc_link pointer (second context).
12 * 13 *
13 * The rationale for this is that if TM unaware code (which linked 14 * 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 * against TM libs) installs a signal handler it will not know of the
@@ -28,17 +29,20 @@
28 29
29#define MAX_ATTEMPT 500000 30#define MAX_ATTEMPT 500000
30 31
31#define NV_FPU_REGS 18 32#define NV_FPU_REGS 18 /* Number of non-volatile FP registers */
33#define FPR14 14 /* First non-volatile FP register to check in f14-31 subset */
32 34
33long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); 35long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
34 36
35/* Be sure there are 2x as many as there are NV FPU regs (2x18) */ 37/* Test only non-volatile registers, i.e. 18 fpr registers from f14 to f31 */
36static double fps[] = { 38static double fps[] = {
39 /* First context will be set with these values, i.e. non-speculative */
37 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 40 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
41 /* Second context will be set with these values, i.e. speculative */
38 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18 42 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
39}; 43};
40 44
41static sig_atomic_t fail; 45static sig_atomic_t fail, broken;
42 46
43static void signal_usr1(int signum, siginfo_t *info, void *uc) 47static void signal_usr1(int signum, siginfo_t *info, void *uc)
44{ 48{
@@ -46,11 +50,24 @@ static void signal_usr1(int signum, siginfo_t *info, void *uc)
46 ucontext_t *ucp = uc; 50 ucontext_t *ucp = uc;
47 ucontext_t *tm_ucp = ucp->uc_link; 51 ucontext_t *tm_ucp = ucp->uc_link;
48 52
49 for (i = 0; i < NV_FPU_REGS && !fail; i++) { 53 for (i = 0; i < NV_FPU_REGS; i++) {
50 fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]); 54 /* Check first context. Print all mismatches. */
51 fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]); 55 fail = (ucp->uc_mcontext.fp_regs[FPR14 + i] != fps[i]);
52 if (fail) 56 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]); 57 broken = 1;
58 printf("FPR%d (1st context) == %g instead of %g (expected)\n",
59 FPR14 + i, ucp->uc_mcontext.fp_regs[FPR14 + i], fps[i]);
60 }
61 }
62
63 for (i = 0; i < NV_FPU_REGS; i++) {
64 /* Check second context. Print all mismatches. */
65 fail = (tm_ucp->uc_mcontext.fp_regs[FPR14 + i] != fps[NV_FPU_REGS + i]);
66 if (fail) {
67 broken = 1;
68 printf("FPR%d (2nd context) == %g instead of %g (expected)\n",
69 FPR14 + i, tm_ucp->uc_mcontext.fp_regs[FPR14 + i], fps[NV_FPU_REGS + i]);
70 }
54 } 71 }
55} 72}
56 73
@@ -72,13 +89,19 @@ static int tm_signal_context_chk_fpu()
72 } 89 }
73 90
74 i = 0; 91 i = 0;
75 while (i < MAX_ATTEMPT && !fail) { 92 while (i < MAX_ATTEMPT && !broken) {
93 /*
94 * tm_signal_self_context_load will set both first and second
95 * contexts accordingly to the values passed through non-NULL
96 * array pointers to it, in that case 'fps', and invoke the
97 * signal handler installed for SIGUSR1.
98 */
76 rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL); 99 rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL);
77 FAIL_IF(rc != pid); 100 FAIL_IF(rc != pid);
78 i++; 101 i++;
79 } 102 }
80 103
81 return fail; 104 return (broken);
82} 105}
83 106
84int main(void) 107int main(void)
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
index 4d05f8b0254c..0cc680f61828 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
@@ -5,10 +5,11 @@
5 * Test the kernel's signal frame code. 5 * Test the kernel's signal frame code.
6 * 6 *
7 * The kernel sets up two sets of ucontexts if the signal was to be 7 * The kernel sets up two sets of ucontexts if the signal was to be
8 * delivered while the thread was in a transaction. 8 * delivered while the thread was in a transaction (referred too as
9 * first and second contexts).
9 * Expected behaviour is that the checkpointed state is in the user 10 * Expected behaviour is that the checkpointed state is in the user
10 * context passed to the signal handler. The speculated state can be 11 * context passed to the signal handler (first context). The speculated
11 * accessed with the uc_link pointer. 12 * state can be accessed with the uc_link pointer (second context).
12 * 13 *
13 * The rationale for this is that if TM unaware code (which linked 14 * 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 * against TM libs) installs a signal handler it will not know of the
@@ -28,14 +29,22 @@
28 29
29#define MAX_ATTEMPT 500000 30#define MAX_ATTEMPT 500000
30 31
31#define NV_GPR_REGS 18 32#define NV_GPR_REGS 18 /* Number of non-volatile GPR registers */
33#define R14 14 /* First non-volatile register to check in r14-r31 subset */
32 34
33long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); 35long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
34 36
35static sig_atomic_t fail; 37static sig_atomic_t fail, broken;
36 38
37static long gps[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 39/* Test only non-volatile general purpose registers, i.e. r14-r31 */
38 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18}; 40static long gprs[] = {
41 /* First context will be set with these values, i.e. non-speculative */
42 /* R14, R15, ... */
43 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
44 /* Second context will be set with these values, i.e. speculative */
45 /* R14, R15, ... */
46 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
47};
39 48
40static void signal_usr1(int signum, siginfo_t *info, void *uc) 49static void signal_usr1(int signum, siginfo_t *info, void *uc)
41{ 50{
@@ -43,12 +52,24 @@ static void signal_usr1(int signum, siginfo_t *info, void *uc)
43 ucontext_t *ucp = uc; 52 ucontext_t *ucp = uc;
44 ucontext_t *tm_ucp = ucp->uc_link; 53 ucontext_t *tm_ucp = ucp->uc_link;
45 54
46 for (i = 0; i < NV_GPR_REGS && !fail; i++) { 55 /* Check first context. Print all mismatches. */
47 fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]); 56 for (i = 0; i < NV_GPR_REGS; i++) {
48 fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]); 57 fail = (ucp->uc_mcontext.gp_regs[R14 + i] != gprs[i]);
49 if (fail) 58 if (fail) {
50 printf("Failed on %d GPR %lu or %lu\n", i, 59 broken = 1;
51 ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]); 60 printf("GPR%d (1st context) == %lu instead of %lu (expected)\n",
61 R14 + i, ucp->uc_mcontext.gp_regs[R14 + i], gprs[i]);
62 }
63 }
64
65 /* Check second context. Print all mismatches. */
66 for (i = 0; i < NV_GPR_REGS; i++) {
67 fail = (tm_ucp->uc_mcontext.gp_regs[R14 + i] != gprs[NV_GPR_REGS + i]);
68 if (fail) {
69 broken = 1;
70 printf("GPR%d (2nd context) == %lu instead of %lu (expected)\n",
71 R14 + i, tm_ucp->uc_mcontext.gp_regs[R14 + i], gprs[NV_GPR_REGS + i]);
72 }
52 } 73 }
53} 74}
54 75
@@ -70,13 +91,19 @@ static int tm_signal_context_chk_gpr()
70 } 91 }
71 92
72 i = 0; 93 i = 0;
73 while (i < MAX_ATTEMPT && !fail) { 94 while (i < MAX_ATTEMPT && !broken) {
74 rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL); 95 /*
96 * tm_signal_self_context_load will set both first and second
97 * contexts accordingly to the values passed through non-NULL
98 * array pointers to it, in that case 'gprs', and invoke the
99 * signal handler installed for SIGUSR1.
100 */
101 rc = tm_signal_self_context_load(pid, gprs, NULL, NULL, NULL);
75 FAIL_IF(rc != pid); 102 FAIL_IF(rc != pid);
76 i++; 103 i++;
77 } 104 }
78 105
79 return fail; 106 return broken;
80} 107}
81 108
82int main(void) 109int main(void)
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
index 48ad01499b1a..b6d52730a0d8 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
@@ -5,10 +5,11 @@
5 * Test the kernel's signal frame code. 5 * Test the kernel's signal frame code.
6 * 6 *
7 * The kernel sets up two sets of ucontexts if the signal was to be 7 * The kernel sets up two sets of ucontexts if the signal was to be
8 * delivered while the thread was in a transaction. 8 * delivered while the thread was in a transaction (referred too as
9 * first and second contexts).
9 * Expected behaviour is that the checkpointed state is in the user 10 * Expected behaviour is that the checkpointed state is in the user
10 * context passed to the signal handler. The speculated state can be 11 * context passed to the signal handler (first context). The speculated
11 * accessed with the uc_link pointer. 12 * state can be accessed with the uc_link pointer (second context).
12 * 13 *
13 * The rationale for this is that if TM unaware code (which linked 14 * 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 * against TM libs) installs a signal handler it will not know of the
@@ -29,18 +30,24 @@
29 30
30#define MAX_ATTEMPT 500000 31#define MAX_ATTEMPT 500000
31 32
32#define NV_VMX_REGS 12 33#define NV_VMX_REGS 12 /* Number of non-volatile VMX registers */
34#define VMX20 20 /* First non-volatile register to check in vr20-31 subset */
33 35
34long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); 36long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
35 37
36static sig_atomic_t fail; 38static sig_atomic_t fail, broken;
37 39
40/* Test only non-volatile registers, i.e. 12 vmx registers from vr20 to vr31 */
38vector int vms[] = { 41vector int vms[] = {
39 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12}, 42 /* First context will be set with these values, i.e. non-speculative */
43 /* VMX20 , VMX21 , ... */
44 { 1, 2, 3, 4},{ 5, 6, 7, 8},{ 9,10,11,12},
40 {13,14,15,16},{17,18,19,20},{21,22,23,24}, 45 {13,14,15,16},{17,18,19,20},{21,22,23,24},
41 {25,26,27,28},{29,30,31,32},{33,34,35,36}, 46 {25,26,27,28},{29,30,31,32},{33,34,35,36},
42 {37,38,39,40},{41,42,43,44},{45,46,47,48}, 47 {37,38,39,40},{41,42,43,44},{45,46,47,48},
43 {-1, -2, -3, -4}, {-5, -6, -7, -8}, {-9, -10,-11,-12}, 48 /* Second context will be set with these values, i.e. speculative */
49 /* VMX20 , VMX21 , ... */
50 { -1, -2, -3, -4},{ -5, -6, -7, -8},{ -9,-10,-11,-12},
44 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24}, 51 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
45 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36}, 52 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
46 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48} 53 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
@@ -48,26 +55,43 @@ vector int vms[] = {
48 55
49static void signal_usr1(int signum, siginfo_t *info, void *uc) 56static void signal_usr1(int signum, siginfo_t *info, void *uc)
50{ 57{
51 int i; 58 int i, j;
52 ucontext_t *ucp = uc; 59 ucontext_t *ucp = uc;
53 ucontext_t *tm_ucp = ucp->uc_link; 60 ucontext_t *tm_ucp = ucp->uc_link;
54 61
55 for (i = 0; i < NV_VMX_REGS && !fail; i++) { 62 for (i = 0; i < NV_VMX_REGS; i++) {
56 fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[i + 20], 63 /* Check first context. Print all mismatches. */
64 fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[VMX20 + i],
57 &vms[i], sizeof(vector int)); 65 &vms[i], sizeof(vector int));
58 fail |= memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[i + 20],
59 &vms[i + NV_VMX_REGS], sizeof (vector int));
60
61 if (fail) { 66 if (fail) {
62 int j; 67 broken = 1;
68 printf("VMX%d (1st context) == 0x", VMX20 + i);
69 /* Print actual value in first context. */
70 for (j = 0; j < 4; j++)
71 printf("%08x", ucp->uc_mcontext.v_regs->vrregs[VMX20 + i][j]);
72 printf(" instead of 0x");
73 /* Print expected value. */
74 for (j = 0; j < 4; j++)
75 printf("%08x", vms[i][j]);
76 printf(" (expected)\n");
77 }
78 }
63 79
64 fprintf(stderr, "Failed on %d vmx 0x", i); 80 for (i = 0; i < NV_VMX_REGS; i++) {
81 /* Check second context. Print all mismatches. */
82 fail = memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[VMX20 + i],
83 &vms[NV_VMX_REGS + i], sizeof (vector int));
84 if (fail) {
85 broken = 1;
86 printf("VMX%d (2nd context) == 0x", NV_VMX_REGS + i);
87 /* Print actual value in second context. */
88 for (j = 0; j < 4; j++)
89 printf("%08x", tm_ucp->uc_mcontext.v_regs->vrregs[VMX20 + i][j]);
90 printf(" instead of 0x");
91 /* Print expected value. */
65 for (j = 0; j < 4; j++) 92 for (j = 0; j < 4; j++)
66 fprintf(stderr, "%04x", ucp->uc_mcontext.v_regs->vrregs[i + 20][j]); 93 printf("%08x", vms[NV_VMX_REGS + i][j]);
67 fprintf(stderr, " vs 0x"); 94 printf(" (expected)\n");
68 for (j = 0 ; j < 4; j++)
69 fprintf(stderr, "%04x", tm_ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
70 fprintf(stderr, "\n");
71 } 95 }
72 } 96 }
73} 97}
@@ -90,13 +114,19 @@ static int tm_signal_context_chk()
90 } 114 }
91 115
92 i = 0; 116 i = 0;
93 while (i < MAX_ATTEMPT && !fail) { 117 while (i < MAX_ATTEMPT && !broken) {
118 /*
119 * tm_signal_self_context_load will set both first and second
120 * contexts accordingly to the values passed through non-NULL
121 * array pointers to it, in that case 'vms', and invoke the
122 * signal handler installed for SIGUSR1.
123 */
94 rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL); 124 rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL);
95 FAIL_IF(rc != pid); 125 FAIL_IF(rc != pid);
96 i++; 126 i++;
97 } 127 }
98 128
99 return fail; 129 return (broken);
100} 130}
101 131
102int main(void) 132int main(void)
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
index 8c8677a408bb..8e25e2072ecd 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
@@ -5,10 +5,11 @@
5 * Test the kernel's signal frame code. 5 * Test the kernel's signal frame code.
6 * 6 *
7 * The kernel sets up two sets of ucontexts if the signal was to be 7 * The kernel sets up two sets of ucontexts if the signal was to be
8 * delivered while the thread was in a transaction. 8 * delivered while the thread was in a transaction (referred too as
9 * first and second contexts).
9 * Expected behaviour is that the checkpointed state is in the user 10 * Expected behaviour is that the checkpointed state is in the user
10 * context passed to the signal handler. The speculated state can be 11 * context passed to the signal handler (first context). The speculated
11 * accessed with the uc_link pointer. 12 * state can be accessed with the uc_link pointer (second context).
12 * 13 *
13 * The rationale for this is that if TM unaware code (which linked 14 * 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 * against TM libs) installs a signal handler it will not know of the
@@ -29,17 +30,24 @@
29 30
30#define MAX_ATTEMPT 500000 31#define MAX_ATTEMPT 500000
31 32
32#define NV_VSX_REGS 12 33#define NV_VSX_REGS 12 /* Number of VSX registers to check. */
34#define VSX20 20 /* First VSX register to check in vsr20-vsr31 subset */
35#define FPR20 20 /* FPR20 overlaps VSX20 most significant doubleword */
33 36
34long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss); 37long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
35 38
36static sig_atomic_t fail; 39static sig_atomic_t fail, broken;
37 40
38vector int vss[] = { 41/* Test only 12 vsx registers from vsr20 to vsr31 */
39 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12}, 42vector int vsxs[] = {
43 /* First context will be set with these values, i.e. non-speculative */
44 /* VSX20 , VSX21 , ... */
45 { 1, 2, 3, 4},{ 5, 6, 7, 8},{ 9,10,11,12},
40 {13,14,15,16},{17,18,19,20},{21,22,23,24}, 46 {13,14,15,16},{17,18,19,20},{21,22,23,24},
41 {25,26,27,28},{29,30,31,32},{33,34,35,36}, 47 {25,26,27,28},{29,30,31,32},{33,34,35,36},
42 {37,38,39,40},{41,42,43,44},{45,46,47,48}, 48 {37,38,39,40},{41,42,43,44},{45,46,47,48},
49 /* Second context will be set with these values, i.e. speculative */
50 /* VSX20 , VSX21 , ... */
43 {-1, -2, -3, -4 },{-5, -6, -7, -8 },{-9, -10,-11,-12}, 51 {-1, -2, -3, -4 },{-5, -6, -7, -8 },{-9, -10,-11,-12},
44 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24}, 52 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
45 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36}, 53 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
@@ -48,41 +56,91 @@ vector int vss[] = {
48 56
49static void signal_usr1(int signum, siginfo_t *info, void *uc) 57static void signal_usr1(int signum, siginfo_t *info, void *uc)
50{ 58{
51 int i; 59 int i, j;
52 uint8_t vsc[sizeof(vector int)]; 60 uint8_t vsx[sizeof(vector int)];
53 uint8_t vst[sizeof(vector int)]; 61 uint8_t vsx_tm[sizeof(vector int)];
54 ucontext_t *ucp = uc; 62 ucontext_t *ucp = uc;
55 ucontext_t *tm_ucp = ucp->uc_link; 63 ucontext_t *tm_ucp = ucp->uc_link;
56 64
57 /* 65 /*
58 * The other half of the VSX regs will be after v_regs. 66 * FP registers and VMX registers overlap the VSX registers.
67 *
68 * FP registers (f0-31) overlap the most significant 64 bits of VSX
69 * registers vsr0-31, whilst VMX registers vr0-31, being 128-bit like
70 * the VSX registers, overlap fully the other half of VSX registers,
71 * i.e. vr0-31 overlaps fully vsr32-63.
72 *
73 * Due to compatibility and historical reasons (VMX/Altivec support
74 * appeared first on the architecture), VMX registers vr0-31 (so VSX
75 * half vsr32-63 too) are stored right after the v_regs pointer, in an
76 * area allocated for 'vmx_reverse' array (please see
77 * arch/powerpc/include/uapi/asm/sigcontext.h for details about the
78 * mcontext_t structure on Power).
79 *
80 * The other VSX half (vsr0-31) is hence stored below vr0-31/vsr32-63
81 * registers, but only the least significant 64 bits of vsr0-31. The
82 * most significant 64 bits of vsr0-31 (f0-31), as it overlaps the FP
83 * registers, is kept in fp_regs.
84 *
85 * v_regs is a 16 byte aligned pointer at the start of vmx_reserve
86 * (vmx_reserve may or may not be 16 aligned) where the v_regs structure
87 * exists, so v_regs points to where vr0-31 / vsr32-63 registers are
88 * fully stored. Since v_regs type is elf_vrregset_t, v_regs + 1
89 * skips all the slots used to store vr0-31 / vsr32-64 and points to
90 * part of one VSX half, i.e. v_regs + 1 points to the least significant
91 * 64 bits of vsr0-31. The other part of this half (the most significant
92 * part of vsr0-31) is stored in fp_regs.
59 * 93 *
60 * In short, vmx_reserve array holds everything. v_regs is a 16
61 * byte aligned pointer at the start of vmx_reserve (vmx_reserve
62 * may or may not be 16 aligned) where the v_regs structure exists.
63 * (half of) The VSX regsters are directly after v_regs so the
64 * easiest way to find them below.
65 */ 94 */
95 /* Get pointer to least significant doubleword of vsr0-31 */
66 long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1); 96 long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1);
67 long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1); 97 long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1);
68 for (i = 0; i < NV_VSX_REGS && !fail; i++) {
69 memcpy(vsc, &ucp->uc_mcontext.fp_regs[i + 20], 8);
70 memcpy(vsc + 8, &vsx_ptr[20 + i], 8);
71 fail = memcmp(vsc, &vss[i], sizeof(vector int));
72 memcpy(vst, &tm_ucp->uc_mcontext.fp_regs[i + 20], 8);
73 memcpy(vst + 8, &tm_vsx_ptr[20 + i], 8);
74 fail |= memcmp(vst, &vss[i + NV_VSX_REGS], sizeof(vector int));
75 98
76 if (fail) { 99 /* Check first context. Print all mismatches. */
77 int j; 100 for (i = 0; i < NV_VSX_REGS; i++) {
101 /*
102 * Copy VSX most significant doubleword from fp_regs and
103 * copy VSX least significant one from 64-bit slots below
104 * saved VMX registers.
105 */
106 memcpy(vsx, &ucp->uc_mcontext.fp_regs[FPR20 + i], 8);
107 memcpy(vsx + 8, &vsx_ptr[VSX20 + i], 8);
108
109 fail = memcmp(vsx, &vsxs[i], sizeof(vector int));
78 110
79 fprintf(stderr, "Failed on %d vsx 0x", i); 111 if (fail) {
112 broken = 1;
113 printf("VSX%d (1st context) == 0x", VSX20 + i);
80 for (j = 0; j < 16; j++) 114 for (j = 0; j < 16; j++)
81 fprintf(stderr, "%02x", vsc[j]); 115 printf("%02x", vsx[j]);
82 fprintf(stderr, " vs 0x"); 116 printf(" instead of 0x");
117 for (j = 0; j < 4; j++)
118 printf("%08x", vsxs[i][j]);
119 printf(" (expected)\n");
120 }
121 }
122
123 /* Check second context. Print all mismatches. */
124 for (i = 0; i < NV_VSX_REGS; i++) {
125 /*
126 * Copy VSX most significant doubleword from fp_regs and
127 * copy VSX least significant one from 64-bit slots below
128 * saved VMX registers.
129 */
130 memcpy(vsx_tm, &tm_ucp->uc_mcontext.fp_regs[FPR20 + i], 8);
131 memcpy(vsx_tm + 8, &tm_vsx_ptr[VSX20 + i], 8);
132
133 fail = memcmp(vsx_tm, &vsxs[NV_VSX_REGS + i], sizeof(vector int));
134
135 if (fail) {
136 broken = 1;
137 printf("VSX%d (2nd context) == 0x", VSX20 + i);
83 for (j = 0; j < 16; j++) 138 for (j = 0; j < 16; j++)
84 fprintf(stderr, "%02x", vst[j]); 139 printf("%02x", vsx_tm[j]);
85 fprintf(stderr, "\n"); 140 printf(" instead of 0x");
141 for (j = 0; j < 4; j++)
142 printf("%08x", vsxs[NV_VSX_REGS + i][j]);
143 printf("(expected)\n");
86 } 144 }
87 } 145 }
88} 146}
@@ -105,13 +163,19 @@ static int tm_signal_context_chk()
105 } 163 }
106 164
107 i = 0; 165 i = 0;
108 while (i < MAX_ATTEMPT && !fail) { 166 while (i < MAX_ATTEMPT && !broken) {
109 rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vss); 167 /*
168 * tm_signal_self_context_load will set both first and second
169 * contexts accordingly to the values passed through non-NULL
170 * array pointers to it, in that case 'vsxs', and invoke the
171 * signal handler installed for SIGUSR1.
172 */
173 rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vsxs);
110 FAIL_IF(rc != pid); 174 FAIL_IF(rc != pid);
111 i++; 175 i++;
112 } 176 }
113 177
114 return fail; 178 return (broken);
115} 179}
116 180
117int main(void) 181int main(void)