18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2015, Sam Bobroff, IBM Corp. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Test the kernel's system call code to ensure that a system call 68c2ecf20Sopenharmony_ci * made from within an active HTM transaction is aborted with the 78c2ecf20Sopenharmony_ci * correct failure code. 88c2ecf20Sopenharmony_ci * Conversely, ensure that a system call made from within a 98c2ecf20Sopenharmony_ci * suspended transaction can succeed. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <stdio.h> 138c2ecf20Sopenharmony_ci#include <unistd.h> 148c2ecf20Sopenharmony_ci#include <sys/syscall.h> 158c2ecf20Sopenharmony_ci#include <asm/tm.h> 168c2ecf20Sopenharmony_ci#include <sys/time.h> 178c2ecf20Sopenharmony_ci#include <stdlib.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "utils.h" 208c2ecf20Sopenharmony_ci#include "tm.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ciextern int getppid_tm_active(void); 238c2ecf20Sopenharmony_ciextern int getppid_tm_suspended(void); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ciunsigned retries = 0; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define TEST_DURATION 10 /* seconds */ 288c2ecf20Sopenharmony_ci#define TM_RETRIES 100 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cipid_t getppid_tm(bool suspend) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci int i; 338c2ecf20Sopenharmony_ci pid_t pid; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci for (i = 0; i < TM_RETRIES; i++) { 368c2ecf20Sopenharmony_ci if (suspend) 378c2ecf20Sopenharmony_ci pid = getppid_tm_suspended(); 388c2ecf20Sopenharmony_ci else 398c2ecf20Sopenharmony_ci pid = getppid_tm_active(); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (pid >= 0) 428c2ecf20Sopenharmony_ci return pid; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci if (failure_is_persistent()) { 458c2ecf20Sopenharmony_ci if (failure_is_syscall()) 468c2ecf20Sopenharmony_ci return -1; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci printf("Unexpected persistent transaction failure.\n"); 498c2ecf20Sopenharmony_ci printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", 508c2ecf20Sopenharmony_ci __builtin_get_texasr(), __builtin_get_tfiar()); 518c2ecf20Sopenharmony_ci exit(-1); 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci retries++; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES); 588c2ecf20Sopenharmony_ci printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", 598c2ecf20Sopenharmony_ci __builtin_get_texasr(), __builtin_get_tfiar()); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci exit(-1); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciint tm_syscall(void) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci unsigned count = 0; 678c2ecf20Sopenharmony_ci struct timeval end, now; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci SKIP_IF(!have_htm_nosc()); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci setbuf(stdout, NULL); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci gettimeofday(&end, NULL); 768c2ecf20Sopenharmony_ci now.tv_sec = TEST_DURATION; 778c2ecf20Sopenharmony_ci now.tv_usec = 0; 788c2ecf20Sopenharmony_ci timeradd(&end, &now, &end); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci for (count = 0; timercmp(&now, &end, <); count++) { 818c2ecf20Sopenharmony_ci /* 828c2ecf20Sopenharmony_ci * Test a syscall within a suspended transaction and verify 838c2ecf20Sopenharmony_ci * that it succeeds. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */ 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci /* 888c2ecf20Sopenharmony_ci * Test a syscall within an active transaction and verify that 898c2ecf20Sopenharmony_ci * it fails with the correct failure code. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ci FAIL_IF(getppid_tm(false) != -1); /* Should fail... */ 928c2ecf20Sopenharmony_ci FAIL_IF(!failure_is_persistent()); /* ...persistently... */ 938c2ecf20Sopenharmony_ci FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ 948c2ecf20Sopenharmony_ci gettimeofday(&now, 0); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci printf("%d active and suspended transactions behaved correctly.\n", count); 988c2ecf20Sopenharmony_ci printf("(There were %d transaction retries.)\n", retries); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci return 0; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ciint main(void) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci return test_harness(tm_syscall, "tm_syscall"); 1068c2ecf20Sopenharmony_ci} 107