12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
25ca4ffcdSCyril Bur /*
35ca4ffcdSCyril Bur * Copyright 2016, Cyril Bur, IBM Corp.
45ca4ffcdSCyril Bur *
55ca4ffcdSCyril Bur * Test the kernel's signal frame code.
65ca4ffcdSCyril Bur *
75ca4ffcdSCyril Bur * The kernel sets up two sets of ucontexts if the signal was to be
89d535e20SGustavo Romero * delivered while the thread was in a transaction (referred too as
99d535e20SGustavo Romero * first and second contexts).
105ca4ffcdSCyril Bur * Expected behaviour is that the checkpointed state is in the user
119d535e20SGustavo Romero * context passed to the signal handler (first context). The speculated
129d535e20SGustavo Romero * state can be accessed with the uc_link pointer (second context).
135ca4ffcdSCyril Bur *
145ca4ffcdSCyril Bur * The rationale for this is that if TM unaware code (which linked
155ca4ffcdSCyril Bur * against TM libs) installs a signal handler it will not know of the
165ca4ffcdSCyril Bur * speculative nature of the 'live' registers and may infer the wrong
175ca4ffcdSCyril Bur * thing.
185ca4ffcdSCyril Bur */
195ca4ffcdSCyril Bur
205ca4ffcdSCyril Bur #include <stdlib.h>
215ca4ffcdSCyril Bur #include <stdio.h>
225ca4ffcdSCyril Bur #include <signal.h>
235ca4ffcdSCyril Bur #include <unistd.h>
245ca4ffcdSCyril Bur
255ca4ffcdSCyril Bur #include <altivec.h>
265ca4ffcdSCyril Bur
275ca4ffcdSCyril Bur #include "utils.h"
285ca4ffcdSCyril Bur #include "tm.h"
295ca4ffcdSCyril Bur
305ca4ffcdSCyril Bur #define MAX_ATTEMPT 500000
315ca4ffcdSCyril Bur
329d535e20SGustavo Romero #define NV_FPU_REGS 18 /* Number of non-volatile FP registers */
339d535e20SGustavo Romero #define FPR14 14 /* First non-volatile FP register to check in f14-31 subset */
345ca4ffcdSCyril Bur
355ca4ffcdSCyril Bur long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
365ca4ffcdSCyril Bur
379d535e20SGustavo Romero /* Test only non-volatile registers, i.e. 18 fpr registers from f14 to f31 */
385ca4ffcdSCyril Bur static double fps[] = {
399d535e20SGustavo Romero /* First context will be set with these values, i.e. non-speculative */
405ca4ffcdSCyril Bur 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
419d535e20SGustavo Romero /* Second context will be set with these values, i.e. speculative */
425ca4ffcdSCyril Bur -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
435ca4ffcdSCyril Bur };
445ca4ffcdSCyril Bur
459d535e20SGustavo Romero static sig_atomic_t fail, broken;
465ca4ffcdSCyril Bur
signal_usr1(int signum,siginfo_t * info,void * uc)475ca4ffcdSCyril Bur static void signal_usr1(int signum, siginfo_t *info, void *uc)
485ca4ffcdSCyril Bur {
495ca4ffcdSCyril Bur int i;
505ca4ffcdSCyril Bur ucontext_t *ucp = uc;
515ca4ffcdSCyril Bur ucontext_t *tm_ucp = ucp->uc_link;
525ca4ffcdSCyril Bur
539d535e20SGustavo Romero for (i = 0; i < NV_FPU_REGS; i++) {
549d535e20SGustavo Romero /* Check first context. Print all mismatches. */
559d535e20SGustavo Romero fail = (ucp->uc_mcontext.fp_regs[FPR14 + i] != fps[i]);
569d535e20SGustavo Romero if (fail) {
579d535e20SGustavo Romero broken = 1;
589d535e20SGustavo Romero printf("FPR%d (1st context) == %g instead of %g (expected)\n",
599d535e20SGustavo Romero FPR14 + i, ucp->uc_mcontext.fp_regs[FPR14 + i], fps[i]);
609d535e20SGustavo Romero }
619d535e20SGustavo Romero }
629d535e20SGustavo Romero
639d535e20SGustavo Romero for (i = 0; i < NV_FPU_REGS; i++) {
649d535e20SGustavo Romero /* Check second context. Print all mismatches. */
659d535e20SGustavo Romero fail = (tm_ucp->uc_mcontext.fp_regs[FPR14 + i] != fps[NV_FPU_REGS + i]);
669d535e20SGustavo Romero if (fail) {
679d535e20SGustavo Romero broken = 1;
689d535e20SGustavo Romero printf("FPR%d (2nd context) == %g instead of %g (expected)\n",
699d535e20SGustavo Romero FPR14 + i, tm_ucp->uc_mcontext.fp_regs[FPR14 + i], fps[NV_FPU_REGS + i]);
709d535e20SGustavo Romero }
715ca4ffcdSCyril Bur }
725ca4ffcdSCyril Bur }
735ca4ffcdSCyril Bur
tm_signal_context_chk_fpu()745ca4ffcdSCyril Bur static int tm_signal_context_chk_fpu()
755ca4ffcdSCyril Bur {
765ca4ffcdSCyril Bur struct sigaction act;
775ca4ffcdSCyril Bur int i;
785ca4ffcdSCyril Bur long rc;
795ca4ffcdSCyril Bur pid_t pid = getpid();
805ca4ffcdSCyril Bur
815ca4ffcdSCyril Bur SKIP_IF(!have_htm());
82*e42edf9bSJordan Niethe SKIP_IF(htm_is_synthetic());
835ca4ffcdSCyril Bur
845ca4ffcdSCyril Bur act.sa_sigaction = signal_usr1;
855ca4ffcdSCyril Bur sigemptyset(&act.sa_mask);
865ca4ffcdSCyril Bur act.sa_flags = SA_SIGINFO;
875ca4ffcdSCyril Bur if (sigaction(SIGUSR1, &act, NULL) < 0) {
885ca4ffcdSCyril Bur perror("sigaction sigusr1");
895ca4ffcdSCyril Bur exit(1);
905ca4ffcdSCyril Bur }
915ca4ffcdSCyril Bur
925ca4ffcdSCyril Bur i = 0;
939d535e20SGustavo Romero while (i < MAX_ATTEMPT && !broken) {
949d535e20SGustavo Romero /*
959d535e20SGustavo Romero * tm_signal_self_context_load will set both first and second
969d535e20SGustavo Romero * contexts accordingly to the values passed through non-NULL
979d535e20SGustavo Romero * array pointers to it, in that case 'fps', and invoke the
989d535e20SGustavo Romero * signal handler installed for SIGUSR1.
999d535e20SGustavo Romero */
1005ca4ffcdSCyril Bur rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL);
1015ca4ffcdSCyril Bur FAIL_IF(rc != pid);
1025ca4ffcdSCyril Bur i++;
1035ca4ffcdSCyril Bur }
1045ca4ffcdSCyril Bur
1059d535e20SGustavo Romero return (broken);
1065ca4ffcdSCyril Bur }
1075ca4ffcdSCyril Bur
main(void)1085ca4ffcdSCyril Bur int main(void)
1095ca4ffcdSCyril Bur {
1105ca4ffcdSCyril Bur return test_harness(tm_signal_context_chk_fpu, "tm_signal_context_chk_fpu");
1115ca4ffcdSCyril Bur }
112