Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2016 Google, Inc.
0004  */
0005 
0006 #define _GNU_SOURCE
0007 
0008 #include <errno.h>
0009 #include <fcntl.h>
0010 #include <sched.h>
0011 #include <signal.h>
0012 #include <stdbool.h>
0013 #include <stdio.h>
0014 #include <string.h>
0015 #include <unistd.h>
0016 #include <sys/ptrace.h>
0017 #include <sys/stat.h>
0018 #include <sys/timerfd.h>
0019 #include <sys/types.h>
0020 #include <sys/wait.h>
0021 
0022 #include "../kselftest.h"
0023 
0024 void child(int cpu)
0025 {
0026     cpu_set_t set;
0027 
0028     CPU_ZERO(&set);
0029     CPU_SET(cpu, &set);
0030     if (sched_setaffinity(0, sizeof(set), &set) != 0) {
0031         ksft_print_msg("sched_setaffinity() failed: %s\n",
0032             strerror(errno));
0033         _exit(1);
0034     }
0035 
0036     if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) {
0037         ksft_print_msg("ptrace(PTRACE_TRACEME) failed: %s\n",
0038             strerror(errno));
0039         _exit(1);
0040     }
0041 
0042     if (raise(SIGSTOP) != 0) {
0043         ksft_print_msg("raise(SIGSTOP) failed: %s\n", strerror(errno));
0044         _exit(1);
0045     }
0046 
0047     _exit(0);
0048 }
0049 
0050 int run_test(int cpu)
0051 {
0052     int status;
0053     pid_t pid = fork();
0054     pid_t wpid;
0055 
0056     if (pid < 0) {
0057         ksft_print_msg("fork() failed: %s\n", strerror(errno));
0058         return KSFT_FAIL;
0059     }
0060     if (pid == 0)
0061         child(cpu);
0062 
0063     wpid = waitpid(pid, &status, __WALL);
0064     if (wpid != pid) {
0065         ksft_print_msg("waitpid() failed: %s\n", strerror(errno));
0066         return KSFT_FAIL;
0067     }
0068     if (!WIFSTOPPED(status)) {
0069         ksft_print_msg("child did not stop: %s\n", strerror(errno));
0070         return KSFT_FAIL;
0071     }
0072     if (WSTOPSIG(status) != SIGSTOP) {
0073         ksft_print_msg("child did not stop with SIGSTOP: %s\n",
0074             strerror(errno));
0075         return KSFT_FAIL;
0076     }
0077 
0078     if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) {
0079         if (errno == EIO) {
0080             ksft_print_msg(
0081                 "ptrace(PTRACE_SINGLESTEP) not supported on this architecture: %s\n",
0082                 strerror(errno));
0083             return KSFT_SKIP;
0084         }
0085         ksft_print_msg("ptrace(PTRACE_SINGLESTEP) failed: %s\n",
0086             strerror(errno));
0087         return KSFT_FAIL;
0088     }
0089 
0090     wpid = waitpid(pid, &status, __WALL);
0091     if (wpid != pid) {
0092         ksft_print_msg("waitpid() failed: $s\n", strerror(errno));
0093         return KSFT_FAIL;
0094     }
0095     if (WIFEXITED(status)) {
0096         ksft_print_msg("child did not single-step: %s\n",
0097             strerror(errno));
0098         return KSFT_FAIL;
0099     }
0100     if (!WIFSTOPPED(status)) {
0101         ksft_print_msg("child did not stop: %s\n", strerror(errno));
0102         return KSFT_FAIL;
0103     }
0104     if (WSTOPSIG(status) != SIGTRAP) {
0105         ksft_print_msg("child did not stop with SIGTRAP: %s\n",
0106             strerror(errno));
0107         return KSFT_FAIL;
0108     }
0109 
0110     if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) {
0111         ksft_print_msg("ptrace(PTRACE_CONT) failed: %s\n",
0112             strerror(errno));
0113         return KSFT_FAIL;
0114     }
0115 
0116     wpid = waitpid(pid, &status, __WALL);
0117     if (wpid != pid) {
0118         ksft_print_msg("waitpid() failed: %s\n", strerror(errno));
0119         return KSFT_FAIL;
0120     }
0121     if (!WIFEXITED(status)) {
0122         ksft_print_msg("child did not exit after PTRACE_CONT: %s\n",
0123             strerror(errno));
0124         return KSFT_FAIL;
0125     }
0126 
0127     return KSFT_PASS;
0128 }
0129 
0130 void suspend(void)
0131 {
0132     int power_state_fd;
0133     struct sigevent event = {};
0134     int timerfd;
0135     int err;
0136     struct itimerspec spec = {};
0137 
0138     if (getuid() != 0)
0139         ksft_exit_skip("Please run the test as root - Exiting.\n");
0140 
0141     power_state_fd = open("/sys/power/state", O_RDWR);
0142     if (power_state_fd < 0)
0143         ksft_exit_fail_msg(
0144             "open(\"/sys/power/state\") failed %s)\n",
0145             strerror(errno));
0146 
0147     timerfd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
0148     if (timerfd < 0)
0149         ksft_exit_fail_msg("timerfd_create() failed\n");
0150 
0151     spec.it_value.tv_sec = 5;
0152     err = timerfd_settime(timerfd, 0, &spec, NULL);
0153     if (err < 0)
0154         ksft_exit_fail_msg("timerfd_settime() failed\n");
0155 
0156     if (write(power_state_fd, "mem", strlen("mem")) != strlen("mem"))
0157         ksft_exit_fail_msg("Failed to enter Suspend state\n");
0158 
0159     close(timerfd);
0160     close(power_state_fd);
0161 }
0162 
0163 int main(int argc, char **argv)
0164 {
0165     int opt;
0166     bool do_suspend = true;
0167     bool succeeded = true;
0168     unsigned int tests = 0;
0169     cpu_set_t available_cpus;
0170     int err;
0171     int cpu;
0172 
0173     ksft_print_header();
0174 
0175     while ((opt = getopt(argc, argv, "n")) != -1) {
0176         switch (opt) {
0177         case 'n':
0178             do_suspend = false;
0179             break;
0180         default:
0181             printf("Usage: %s [-n]\n", argv[0]);
0182             printf("        -n: do not trigger a suspend/resume cycle before the test\n");
0183             return -1;
0184         }
0185     }
0186 
0187     err = sched_getaffinity(0, sizeof(available_cpus), &available_cpus);
0188     if (err < 0)
0189         ksft_exit_fail_msg("sched_getaffinity() failed\n");
0190 
0191     for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
0192         if (!CPU_ISSET(cpu, &available_cpus))
0193             continue;
0194         tests++;
0195     }
0196 
0197     if (do_suspend)
0198         suspend();
0199 
0200     ksft_set_plan(tests);
0201     for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
0202         int test_success;
0203 
0204         if (!CPU_ISSET(cpu, &available_cpus))
0205             continue;
0206 
0207         test_success = run_test(cpu);
0208         switch (test_success) {
0209         case KSFT_PASS:
0210             ksft_test_result_pass("CPU %d\n", cpu);
0211             break;
0212         case KSFT_SKIP:
0213             ksft_test_result_skip("CPU %d\n", cpu);
0214             break;
0215         case KSFT_FAIL:
0216             ksft_test_result_fail("CPU %d\n", cpu);
0217             succeeded = false;
0218             break;
0219         }
0220     }
0221 
0222     if (succeeded)
0223         ksft_exit_pass();
0224     else
0225         ksft_exit_fail();
0226 }