0001
0002
0003
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 }