1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2015, Sam Bobroff, IBM Corp. 4 * 5 * Test the kernel's system call code to ensure that a system call 6 * made from within an active HTM transaction is aborted with the 7 * correct failure code. 8 * Conversely, ensure that a system call made from within a 9 * suspended transaction can succeed. 10 */ 11 12 #include <stdio.h> 13 #include <unistd.h> 14 #include <sys/syscall.h> 15 #include <asm/tm.h> 16 #include <sys/time.h> 17 #include <stdlib.h> 18 19 #include "utils.h" 20 #include "tm.h" 21 22 extern int getppid_tm_active(void); 23 extern int getppid_tm_suspended(void); 24 25 unsigned retries = 0; 26 27 #define TEST_DURATION 10 /* seconds */ 28 29 pid_t getppid_tm(bool suspend) 30 { 31 int i; 32 pid_t pid; 33 34 for (i = 0; i < TM_RETRIES; i++) { 35 if (suspend) 36 pid = getppid_tm_suspended(); 37 else 38 pid = getppid_tm_active(); 39 40 if (pid >= 0) 41 return pid; 42 43 if (failure_is_persistent()) { 44 if (failure_is_syscall()) 45 return -1; 46 47 printf("Unexpected persistent transaction failure.\n"); 48 printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", 49 __builtin_get_texasr(), __builtin_get_tfiar()); 50 exit(-1); 51 } 52 53 retries++; 54 } 55 56 printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES); 57 printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", 58 __builtin_get_texasr(), __builtin_get_tfiar()); 59 60 exit(-1); 61 } 62 63 int tm_syscall(void) 64 { 65 unsigned count = 0; 66 struct timeval end, now; 67 68 SKIP_IF(!have_htm_nosc()); 69 SKIP_IF(htm_is_synthetic()); 70 71 setbuf(stdout, NULL); 72 73 printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION); 74 75 gettimeofday(&end, NULL); 76 now.tv_sec = TEST_DURATION; 77 now.tv_usec = 0; 78 timeradd(&end, &now, &end); 79 80 for (count = 0; timercmp(&now, &end, <); count++) { 81 /* 82 * Test a syscall within a suspended transaction and verify 83 * that it succeeds. 84 */ 85 FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */ 86 87 /* 88 * Test a syscall within an active transaction and verify that 89 * it fails with the correct failure code. 90 */ 91 FAIL_IF(getppid_tm(false) != -1); /* Should fail... */ 92 FAIL_IF(!failure_is_persistent()); /* ...persistently... */ 93 FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ 94 gettimeofday(&now, 0); 95 } 96 97 printf("%d active and suspended transactions behaved correctly.\n", count); 98 printf("(There were %d transaction retries.)\n", retries); 99 100 return 0; 101 } 102 103 int main(void) 104 { 105 return test_harness(tm_syscall, "tm_syscall"); 106 } 107