* 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.
+ * delivered while the thread was in a transaction (referred too as
+ * first and second contexts).
  * 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.
+ * context passed to the signal handler (first context). The speculated
+ * state can be accessed with the uc_link pointer (second context).
  *
  * 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
 
 #define MAX_ATTEMPT 500000
 
-#define NV_FPU_REGS 18
+#define NV_FPU_REGS 18 /* Number of non-volatile FP registers */
+#define FPR14 14 /* First non-volatile FP register to check in f14-31 subset */
 
 long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
 
-/* Be sure there are 2x as many as there are NV FPU regs (2x18) */
+/* Test only non-volatile registers, i.e. 18 fpr registers from f14 to f31 */
 static double fps[] = {
+       /* First context will be set with these values, i.e. non-speculative */
         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+       /* Second context will be set with these values, i.e. speculative */
        -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
 };
 
-static sig_atomic_t fail;
+static sig_atomic_t fail, broken;
 
 static void signal_usr1(int signum, siginfo_t *info, void *uc)
 {
        ucontext_t *ucp = uc;
        ucontext_t *tm_ucp = ucp->uc_link;
 
-       for (i = 0; i < NV_FPU_REGS && !fail; i++) {
-               fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]);
-               fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]);
-               if (fail)
-                       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]);
+       for (i = 0; i < NV_FPU_REGS; i++) {
+               /* Check first context. Print all mismatches. */
+               fail = (ucp->uc_mcontext.fp_regs[FPR14 + i] != fps[i]);
+               if (fail) {
+                       broken = 1;
+                       printf("FPR%d (1st context) == %g instead of %g (expected)\n",
+                               FPR14 + i, ucp->uc_mcontext.fp_regs[FPR14 + i], fps[i]);
+               }
+       }
+
+       for (i = 0; i < NV_FPU_REGS; i++) {
+               /* Check second context. Print all mismatches. */
+               fail = (tm_ucp->uc_mcontext.fp_regs[FPR14 + i] != fps[NV_FPU_REGS + i]);
+               if (fail) {
+                       broken = 1;
+                       printf("FPR%d (2nd context) == %g instead of %g (expected)\n",
+                               FPR14 + i, tm_ucp->uc_mcontext.fp_regs[FPR14 + i], fps[NV_FPU_REGS + i]);
+               }
        }
 }
 
        }
 
        i = 0;
-       while (i < MAX_ATTEMPT && !fail) {
+       while (i < MAX_ATTEMPT && !broken) {
+               /*
+                * tm_signal_self_context_load will set both first and second
+                * contexts accordingly to the values passed through non-NULL
+                * array pointers to it, in that case 'fps', and invoke the
+                * signal handler installed for SIGUSR1.
+                */
                rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL);
                FAIL_IF(rc != pid);
                i++;
        }
 
-       return fail;
+       return (broken);
 }
 
 int main(void)
 
  * 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.
+ * delivered while the thread was in a transaction (referred too as
+ * first and second contexts).
  * 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.
+ * context passed to the signal handler (first context). The speculated
+ * state can be accessed with the uc_link pointer (second context).
  *
  * 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
 
 #define MAX_ATTEMPT 500000
 
-#define NV_GPR_REGS 18
+#define NV_GPR_REGS 18 /* Number of non-volatile GPR registers */
+#define R14 14 /* First non-volatile register to check in r14-r31 subset */
 
 long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
 
-static sig_atomic_t fail;
+static sig_atomic_t fail, broken;
 
-static long gps[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
-                                        -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18};
+/* Test only non-volatile general purpose registers, i.e. r14-r31 */
+static long gprs[] = {
+       /* First context will be set with these values, i.e. non-speculative */
+       /* R14, R15, ... */
+        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+       /* Second context will be set with these values, i.e. speculative */
+       /* R14, R15, ... */
+       -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
+};
 
 static void signal_usr1(int signum, siginfo_t *info, void *uc)
 {
        ucontext_t *ucp = uc;
        ucontext_t *tm_ucp = ucp->uc_link;
 
-       for (i = 0; i < NV_GPR_REGS && !fail; i++) {
-               fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]);
-               fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]);
-               if (fail)
-                       printf("Failed on %d GPR %lu or %lu\n", i,
-                                       ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]);
+       /* Check first context. Print all mismatches. */
+       for (i = 0; i < NV_GPR_REGS; i++) {
+               fail = (ucp->uc_mcontext.gp_regs[R14 + i] != gprs[i]);
+               if (fail) {
+                       broken = 1;
+                       printf("GPR%d (1st context) == %lu instead of %lu (expected)\n",
+                               R14 + i, ucp->uc_mcontext.gp_regs[R14 + i], gprs[i]);
+               }
+       }
+
+       /* Check second context. Print all mismatches. */
+       for (i = 0; i < NV_GPR_REGS; i++) {
+               fail = (tm_ucp->uc_mcontext.gp_regs[R14 + i] != gprs[NV_GPR_REGS + i]);
+               if (fail) {
+                       broken = 1;
+                       printf("GPR%d (2nd context) == %lu instead of %lu (expected)\n",
+                               R14 + i, tm_ucp->uc_mcontext.gp_regs[R14 + i], gprs[NV_GPR_REGS + i]);
+               }
        }
 }
 
        }
 
        i = 0;
-       while (i < MAX_ATTEMPT && !fail) {
-               rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL);
+       while (i < MAX_ATTEMPT && !broken) {
+                /*
+                 * tm_signal_self_context_load will set both first and second
+                 * contexts accordingly to the values passed through non-NULL
+                 * array pointers to it, in that case 'gprs', and invoke the
+                 * signal handler installed for SIGUSR1.
+                 */
+               rc = tm_signal_self_context_load(pid, gprs, NULL, NULL, NULL);
                FAIL_IF(rc != pid);
                i++;
        }
 
-       return fail;
+       return broken;
 }
 
 int main(void)
 
  * 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.
+ * delivered while the thread was in a transaction (referred too as
+ * first and second contexts).
  * 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.
+ * context passed to the signal handler (first context). The speculated
+ * state can be accessed with the uc_link pointer (second context).
  *
  * 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
 
 #define MAX_ATTEMPT 500000
 
-#define NV_VMX_REGS 12
+#define NV_VMX_REGS 12 /* Number of non-volatile VMX registers */
+#define VMX20 20 /* First non-volatile register to check in vr20-31 subset */
 
 long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
 
-static sig_atomic_t fail;
+static sig_atomic_t fail, broken;
 
+/* Test only non-volatile registers, i.e. 12 vmx registers from vr20 to vr31 */
 vector int vms[] = {
-       {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
+       /* First context will be set with these values, i.e. non-speculative */
+       /* VMX20     ,  VMX21      , ... */
+       { 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},
+       /* Second context will be set with these values, i.e. speculative */
+       /* VMX20        , VMX21            , ... */
+       { -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;
+       int i, j;
        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],
+       for (i = 0; i < NV_VMX_REGS; i++) {
+               /* Check first context. Print all mismatches. */
+               fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[VMX20 + i],
                                &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;
+                       broken = 1;
+                       printf("VMX%d (1st context) == 0x", VMX20 + i);
+                       /* Print actual value in first context. */
+                       for (j = 0; j < 4; j++)
+                               printf("%08x", ucp->uc_mcontext.v_regs->vrregs[VMX20 + i][j]);
+                       printf(" instead of 0x");
+                       /* Print expected value. */
+                       for (j = 0; j < 4; j++)
+                               printf("%08x", vms[i][j]);
+                       printf(" (expected)\n");
+               }
+       }
 
-                       fprintf(stderr, "Failed on %d vmx 0x", i);
+       for (i = 0; i < NV_VMX_REGS; i++)  {
+               /* Check second context. Print all mismatches. */
+               fail = memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[VMX20 + i],
+                               &vms[NV_VMX_REGS + i], sizeof (vector int));
+               if (fail) {
+                       broken = 1;
+                       printf("VMX%d (2nd context) == 0x", NV_VMX_REGS + i);
+                       /* Print actual value in second context. */
+                       for (j = 0; j < 4; j++)
+                               printf("%08x", tm_ucp->uc_mcontext.v_regs->vrregs[VMX20 + i][j]);
+                       printf(" instead of 0x");
+                       /* Print expected value. */
                        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");
+                               printf("%08x", vms[NV_VMX_REGS + i][j]);
+                       printf(" (expected)\n");
                }
        }
 }
        }
 
        i = 0;
-       while (i < MAX_ATTEMPT && !fail) {
+       while (i < MAX_ATTEMPT && !broken) {
+               /*
+                * tm_signal_self_context_load will set both first and second
+                * contexts accordingly to the values passed through non-NULL
+                * array pointers to it, in that case 'vms', and invoke the
+                * signal handler installed for SIGUSR1.
+                */
                rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL);
                FAIL_IF(rc != pid);
                i++;
        }
 
-       return fail;
+       return (broken);
 }
 
 int main(void)
 
  * 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.
+ * delivered while the thread was in a transaction (referred too as
+ * first and second contexts).
  * 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.
+ * context passed to the signal handler (first context). The speculated
+ * state can be accessed with the uc_link pointer (second context).
  *
  * 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
 
 #define MAX_ATTEMPT 500000
 
-#define NV_VSX_REGS 12
+#define NV_VSX_REGS 12 /* Number of VSX registers to check. */
+#define VSX20 20 /* First VSX register to check in vsr20-vsr31 subset */
+#define FPR20 20 /* FPR20 overlaps VSX20 most significant doubleword */
 
 long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
 
-static sig_atomic_t fail;
+static sig_atomic_t fail, broken;
 
-vector int vss[] = {
-       {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
+/* Test only 12 vsx registers from vsr20 to vsr31 */
+vector int vsxs[] = {
+       /* First context will be set with these values, i.e. non-speculative */
+       /* VSX20     ,  VSX21      , ... */
+       { 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},
+       /* Second context will be set with these values, i.e. speculative */
+       /* VSX20         ,  VSX21          , ... */
        {-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},
 
 static void signal_usr1(int signum, siginfo_t *info, void *uc)
 {
-       int i;
-       uint8_t vsc[sizeof(vector int)];
-       uint8_t vst[sizeof(vector int)];
+       int i, j;
+       uint8_t vsx[sizeof(vector int)];
+       uint8_t vsx_tm[sizeof(vector int)];
        ucontext_t *ucp = uc;
        ucontext_t *tm_ucp = ucp->uc_link;
 
        /*
-        * The other half of the VSX regs will be after v_regs.
+        * FP registers and VMX registers overlap the VSX registers.
+        *
+        * FP registers (f0-31) overlap the most significant 64 bits of VSX
+        * registers vsr0-31, whilst VMX registers vr0-31, being 128-bit like
+        * the VSX registers, overlap fully the other half of VSX registers,
+        * i.e. vr0-31 overlaps fully vsr32-63.
+        *
+        * Due to compatibility and historical reasons (VMX/Altivec support
+        * appeared first on the architecture), VMX registers vr0-31 (so VSX
+        * half vsr32-63 too) are stored right after the v_regs pointer, in an
+        * area allocated for 'vmx_reverse' array (please see
+        * arch/powerpc/include/uapi/asm/sigcontext.h for details about the
+        * mcontext_t structure on Power).
+        *
+        * The other VSX half (vsr0-31) is hence stored below vr0-31/vsr32-63
+        * registers, but only the least significant 64 bits of vsr0-31. The
+        * most significant 64 bits of vsr0-31 (f0-31), as it overlaps the FP
+        * registers, is kept in fp_regs.
+        *
+        * v_regs is a 16 byte aligned pointer at the start of vmx_reserve
+        * (vmx_reserve may or may not be 16 aligned) where the v_regs structure
+        * exists, so v_regs points to where vr0-31 / vsr32-63 registers are
+        * fully stored. Since v_regs type is elf_vrregset_t, v_regs + 1
+        * skips all the slots used to store vr0-31 / vsr32-64 and points to
+        * part of one VSX half, i.e. v_regs + 1 points to the least significant
+        * 64 bits of vsr0-31. The other part of this half (the most significant
+        * part of vsr0-31) is stored in fp_regs.
         *
-        * In short, vmx_reserve array holds everything. v_regs is a 16
-        * byte aligned pointer at the start of vmx_reserve (vmx_reserve
-        * may or may not be 16 aligned) where the v_regs structure exists.
-        * (half of) The VSX regsters are directly after v_regs so the
-        * easiest way to find them below.
         */
+       /* Get pointer to least significant doubleword of vsr0-31 */
        long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1);
        long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1);
-       for (i = 0; i < NV_VSX_REGS && !fail; i++) {
-               memcpy(vsc, &ucp->uc_mcontext.fp_regs[i + 20], 8);
-               memcpy(vsc + 8, &vsx_ptr[20 + i], 8);
-               fail = memcmp(vsc, &vss[i], sizeof(vector int));
-               memcpy(vst, &tm_ucp->uc_mcontext.fp_regs[i + 20], 8);
-               memcpy(vst + 8, &tm_vsx_ptr[20 + i], 8);
-               fail |= memcmp(vst, &vss[i + NV_VSX_REGS], sizeof(vector int));
 
-               if (fail) {
-                       int j;
+       /* Check first context. Print all mismatches. */
+       for (i = 0; i < NV_VSX_REGS; i++) {
+               /*
+                * Copy VSX most significant doubleword from fp_regs and
+                * copy VSX least significant one from 64-bit slots below
+                * saved VMX registers.
+                */
+               memcpy(vsx, &ucp->uc_mcontext.fp_regs[FPR20 + i], 8);
+               memcpy(vsx + 8, &vsx_ptr[VSX20 + i], 8);
+
+               fail = memcmp(vsx, &vsxs[i], sizeof(vector int));
 
-                       fprintf(stderr, "Failed on %d vsx 0x", i);
+               if (fail) {
+                       broken = 1;
+                       printf("VSX%d (1st context) == 0x", VSX20 + i);
                        for (j = 0; j < 16; j++)
-                               fprintf(stderr, "%02x", vsc[j]);
-                       fprintf(stderr, " vs 0x");
+                               printf("%02x", vsx[j]);
+                       printf(" instead of 0x");
+                       for (j = 0; j < 4; j++)
+                               printf("%08x", vsxs[i][j]);
+                       printf(" (expected)\n");
+               }
+       }
+
+       /* Check second context. Print all mismatches. */
+       for (i = 0; i < NV_VSX_REGS; i++) {
+               /*
+                * Copy VSX most significant doubleword from fp_regs and
+                * copy VSX least significant one from 64-bit slots below
+                * saved VMX registers.
+                */
+               memcpy(vsx_tm, &tm_ucp->uc_mcontext.fp_regs[FPR20 + i], 8);
+               memcpy(vsx_tm + 8, &tm_vsx_ptr[VSX20 + i], 8);
+
+               fail = memcmp(vsx_tm, &vsxs[NV_VSX_REGS + i], sizeof(vector int));
+
+               if (fail) {
+                       broken = 1;
+                       printf("VSX%d (2nd context) == 0x", VSX20 + i);
                        for (j = 0; j < 16; j++)
-                               fprintf(stderr, "%02x", vst[j]);
-                       fprintf(stderr, "\n");
+                               printf("%02x", vsx_tm[j]);
+                       printf(" instead of 0x");
+                       for (j = 0; j < 4; j++)
+                               printf("%08x", vsxs[NV_VSX_REGS + i][j]);
+                       printf("(expected)\n");
                }
        }
 }
        }
 
        i = 0;
-       while (i < MAX_ATTEMPT && !fail) {
-               rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vss);
+       while (i < MAX_ATTEMPT && !broken) {
+               /*
+                * tm_signal_self_context_load will set both first and second
+                * contexts accordingly to the values passed through non-NULL
+                * array pointers to it, in that case 'vsxs', and invoke the
+                * signal handler installed for SIGUSR1.
+                */
+               rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vsxs);
                FAIL_IF(rc != pid);
                i++;
        }
 
-       return fail;
+       return (broken);
 }
 
 int main(void)