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 #ifndef PPC_FEATURE2_SCV 23 #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */ 24 #endif 25 26 extern int getppid_tm_active(void); 27 extern int getppid_tm_suspended(void); 28 extern int getppid_scv_tm_active(void); 29 extern int getppid_scv_tm_suspended(void); 30 31 unsigned retries = 0; 32 33 #define TEST_DURATION 10 /* seconds */ 34 35 pid_t getppid_tm(bool scv, bool suspend) 36 { 37 int i; 38 pid_t pid; 39 40 for (i = 0; i < TM_RETRIES; i++) { 41 if (suspend) { 42 if (scv) 43 pid = getppid_scv_tm_suspended(); 44 else 45 pid = getppid_tm_suspended(); 46 } else { 47 if (scv) 48 pid = getppid_scv_tm_active(); 49 else 50 pid = getppid_tm_active(); 51 } 52 53 if (pid >= 0) 54 return pid; 55 56 if (failure_is_persistent()) { 57 if (failure_is_syscall()) 58 return -1; 59 60 printf("Unexpected persistent transaction failure.\n"); 61 printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", 62 __builtin_get_texasr(), __builtin_get_tfiar()); 63 exit(-1); 64 } 65 66 retries++; 67 } 68 69 printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES); 70 printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", 71 __builtin_get_texasr(), __builtin_get_tfiar()); 72 73 exit(-1); 74 } 75 76 int tm_syscall(void) 77 { 78 unsigned count = 0; 79 struct timeval end, now; 80 81 SKIP_IF(!have_htm_nosc()); 82 SKIP_IF(htm_is_synthetic()); 83 84 setbuf(stdout, NULL); 85 86 printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION); 87 88 gettimeofday(&end, NULL); 89 now.tv_sec = TEST_DURATION; 90 now.tv_usec = 0; 91 timeradd(&end, &now, &end); 92 93 for (count = 0; timercmp(&now, &end, <); count++) { 94 /* 95 * Test a syscall within a suspended transaction and verify 96 * that it succeeds. 97 */ 98 FAIL_IF(getppid_tm(false, true) == -1); /* Should succeed. */ 99 100 /* 101 * Test a syscall within an active transaction and verify that 102 * it fails with the correct failure code. 103 */ 104 FAIL_IF(getppid_tm(false, false) != -1); /* Should fail... */ 105 FAIL_IF(!failure_is_persistent()); /* ...persistently... */ 106 FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ 107 108 /* Now do it all again with scv if it is available. */ 109 if (have_hwcap2(PPC_FEATURE2_SCV)) { 110 FAIL_IF(getppid_tm(true, true) == -1); /* Should succeed. */ 111 FAIL_IF(getppid_tm(true, false) != -1); /* Should fail... */ 112 FAIL_IF(!failure_is_persistent()); /* ...persistently... */ 113 FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ 114 } 115 116 gettimeofday(&now, 0); 117 } 118 119 printf("%d active and suspended transactions behaved correctly.\n", count); 120 printf("(There were %d transaction retries.)\n", retries); 121 122 return 0; 123 } 124 125 int main(void) 126 { 127 return test_harness(tm_syscall, "tm_syscall"); 128 } 129