Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2015, Sam Bobroff, IBM Corp.
0004  *
0005  * Test the kernel's system call code to ensure that a system call
0006  * made from within an active HTM transaction is aborted with the
0007  * correct failure code.
0008  * Conversely, ensure that a system call made from within a
0009  * suspended transaction can succeed.
0010  */
0011 
0012 #include <stdio.h>
0013 #include <unistd.h>
0014 #include <sys/syscall.h>
0015 #include <asm/tm.h>
0016 #include <sys/time.h>
0017 #include <stdlib.h>
0018 
0019 #include "utils.h"
0020 #include "tm.h"
0021 
0022 #ifndef PPC_FEATURE2_SCV
0023 #define PPC_FEATURE2_SCV               0x00100000 /* scv syscall */
0024 #endif
0025 
0026 extern int getppid_tm_active(void);
0027 extern int getppid_tm_suspended(void);
0028 extern int getppid_scv_tm_active(void);
0029 extern int getppid_scv_tm_suspended(void);
0030 
0031 unsigned retries = 0;
0032 
0033 #define TEST_DURATION 10 /* seconds */
0034 
0035 pid_t getppid_tm(bool scv, bool suspend)
0036 {
0037     int i;
0038     pid_t pid;
0039 
0040     for (i = 0; i < TM_RETRIES; i++) {
0041         if (suspend) {
0042             if (scv)
0043                 pid = getppid_scv_tm_suspended();
0044             else
0045                 pid = getppid_tm_suspended();
0046         } else {
0047             if (scv)
0048                 pid = getppid_scv_tm_active();
0049             else
0050                 pid = getppid_tm_active();
0051         }
0052 
0053         if (pid >= 0)
0054             return pid;
0055 
0056         if (failure_is_persistent()) {
0057             if (failure_is_syscall())
0058                 return -1;
0059 
0060             printf("Unexpected persistent transaction failure.\n");
0061             printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
0062                    __builtin_get_texasr(), __builtin_get_tfiar());
0063             exit(-1);
0064         }
0065 
0066         retries++;
0067     }
0068 
0069     printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES);
0070     printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n",
0071            __builtin_get_texasr(), __builtin_get_tfiar());
0072 
0073     exit(-1);
0074 }
0075 
0076 int tm_syscall(void)
0077 {
0078     unsigned count = 0;
0079     struct timeval end, now;
0080 
0081     SKIP_IF(!have_htm_nosc());
0082     SKIP_IF(htm_is_synthetic());
0083 
0084     setbuf(stdout, NULL);
0085 
0086     printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION);
0087 
0088     gettimeofday(&end, NULL);
0089     now.tv_sec = TEST_DURATION;
0090     now.tv_usec = 0;
0091     timeradd(&end, &now, &end);
0092 
0093     for (count = 0; timercmp(&now, &end, <); count++) {
0094         /*
0095          * Test a syscall within a suspended transaction and verify
0096          * that it succeeds.
0097          */
0098         FAIL_IF(getppid_tm(false, true) == -1); /* Should succeed. */
0099 
0100         /*
0101          * Test a syscall within an active transaction and verify that
0102          * it fails with the correct failure code.
0103          */
0104         FAIL_IF(getppid_tm(false, false) != -1);  /* Should fail... */
0105         FAIL_IF(!failure_is_persistent()); /* ...persistently... */
0106         FAIL_IF(!failure_is_syscall());    /* ...with code syscall. */
0107 
0108         /* Now do it all again with scv if it is available. */
0109         if (have_hwcap2(PPC_FEATURE2_SCV)) {
0110             FAIL_IF(getppid_tm(true, true) == -1); /* Should succeed. */
0111             FAIL_IF(getppid_tm(true, false) != -1);  /* Should fail... */
0112             FAIL_IF(!failure_is_persistent()); /* ...persistently... */
0113             FAIL_IF(!failure_is_syscall());    /* ...with code syscall. */
0114         }
0115 
0116         gettimeofday(&now, 0);
0117     }
0118 
0119     printf("%d active and suspended transactions behaved correctly.\n", count);
0120     printf("(There were %d transaction retries.)\n", retries);
0121 
0122     return 0;
0123 }
0124 
0125 int main(void)
0126 {
0127     return test_harness(tm_syscall, "tm_syscall");
0128 }