1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2016 Google, Inc. 4 */ 5 6 #define _GNU_SOURCE 7 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <sched.h> 11 #include <signal.h> 12 #include <stdbool.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include <sys/ptrace.h> 17 #include <sys/stat.h> 18 #include <sys/timerfd.h> 19 #include <sys/types.h> 20 #include <sys/wait.h> 21 #include <time.h> 22 23 #include "kselftest.h" 24 25 void child(int cpu) 26 { 27 cpu_set_t set; 28 29 CPU_ZERO(&set); 30 CPU_SET(cpu, &set); 31 if (sched_setaffinity(0, sizeof(set), &set) != 0) { 32 ksft_print_msg("sched_setaffinity() failed: %s\n", 33 strerror(errno)); 34 _exit(1); 35 } 36 37 if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) { 38 ksft_print_msg("ptrace(PTRACE_TRACEME) failed: %s\n", 39 strerror(errno)); 40 _exit(1); 41 } 42 43 if (raise(SIGSTOP) != 0) { 44 ksft_print_msg("raise(SIGSTOP) failed: %s\n", strerror(errno)); 45 _exit(1); 46 } 47 48 _exit(0); 49 } 50 51 int run_test(int cpu) 52 { 53 int status; 54 pid_t pid = fork(); 55 pid_t wpid; 56 57 if (pid < 0) { 58 ksft_print_msg("fork() failed: %s\n", strerror(errno)); 59 return KSFT_FAIL; 60 } 61 if (pid == 0) 62 child(cpu); 63 64 wpid = waitpid(pid, &status, __WALL); 65 if (wpid != pid) { 66 ksft_print_msg("waitpid() failed: %s\n", strerror(errno)); 67 return KSFT_FAIL; 68 } 69 if (!WIFSTOPPED(status)) { 70 ksft_print_msg("child did not stop: %s\n", strerror(errno)); 71 return KSFT_FAIL; 72 } 73 if (WSTOPSIG(status) != SIGSTOP) { 74 ksft_print_msg("child did not stop with SIGSTOP: %s\n", 75 strerror(errno)); 76 return KSFT_FAIL; 77 } 78 79 if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) { 80 if (errno == EIO) { 81 ksft_print_msg( 82 "ptrace(PTRACE_SINGLESTEP) not supported on this architecture: %s\n", 83 strerror(errno)); 84 return KSFT_SKIP; 85 } 86 ksft_print_msg("ptrace(PTRACE_SINGLESTEP) failed: %s\n", 87 strerror(errno)); 88 return KSFT_FAIL; 89 } 90 91 wpid = waitpid(pid, &status, __WALL); 92 if (wpid != pid) { 93 ksft_print_msg("waitpid() failed: %s\n", strerror(errno)); 94 return KSFT_FAIL; 95 } 96 if (WIFEXITED(status)) { 97 ksft_print_msg("child did not single-step: %s\n", 98 strerror(errno)); 99 return KSFT_FAIL; 100 } 101 if (!WIFSTOPPED(status)) { 102 ksft_print_msg("child did not stop: %s\n", strerror(errno)); 103 return KSFT_FAIL; 104 } 105 if (WSTOPSIG(status) != SIGTRAP) { 106 ksft_print_msg("child did not stop with SIGTRAP: %s\n", 107 strerror(errno)); 108 return KSFT_FAIL; 109 } 110 111 if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) { 112 ksft_print_msg("ptrace(PTRACE_CONT) failed: %s\n", 113 strerror(errno)); 114 return KSFT_FAIL; 115 } 116 117 wpid = waitpid(pid, &status, __WALL); 118 if (wpid != pid) { 119 ksft_print_msg("waitpid() failed: %s\n", strerror(errno)); 120 return KSFT_FAIL; 121 } 122 if (!WIFEXITED(status)) { 123 ksft_print_msg("child did not exit after PTRACE_CONT: %s\n", 124 strerror(errno)); 125 return KSFT_FAIL; 126 } 127 128 return KSFT_PASS; 129 } 130 131 /* 132 * Reads the suspend success count from sysfs. 133 * Returns the count on success or exits on failure. 134 */ 135 static int get_suspend_success_count_or_fail(void) 136 { 137 FILE *fp; 138 int val; 139 140 fp = fopen("/sys/power/suspend_stats/success", "r"); 141 if (!fp) 142 ksft_exit_fail_msg( 143 "Failed to open suspend_stats/success: %s\n", 144 strerror(errno)); 145 146 if (fscanf(fp, "%d", &val) != 1) { 147 fclose(fp); 148 ksft_exit_fail_msg( 149 "Failed to read suspend success count\n"); 150 } 151 152 fclose(fp); 153 return val; 154 } 155 156 void suspend(void) 157 { 158 int timerfd; 159 int err; 160 int count_before; 161 int count_after; 162 struct timespec res; 163 struct itimerspec spec = {}; 164 165 if (getuid() != 0) 166 ksft_exit_skip("Please run the test as root - Exiting.\n"); 167 168 /* 169 * CLOCK_BOOTTIME_ALARM cannot wake up systems that don't have a 170 * wakeup capable RTC from suspend. Check if we have a wakeup-capable 171 * RTC to prevent this test from causing the system to hang after 172 * it suspends. 173 */ 174 if (clock_getres(CLOCK_BOOTTIME_ALARM, &res) != 0) 175 ksft_exit_skip("No wakeup-capable RTC for CLOCK_BOOTTIME_ALARM\n"); 176 177 timerfd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0); 178 if (timerfd < 0) 179 ksft_exit_fail_msg("timerfd_create() failed\n"); 180 181 spec.it_value.tv_sec = 5; 182 err = timerfd_settime(timerfd, 0, &spec, NULL); 183 if (err < 0) 184 ksft_exit_fail_msg("timerfd_settime() failed\n"); 185 186 count_before = get_suspend_success_count_or_fail(); 187 188 system("(echo mem > /sys/power/state) 2> /dev/null"); 189 190 count_after = get_suspend_success_count_or_fail(); 191 if (count_after <= count_before) 192 ksft_exit_fail_msg("Failed to enter Suspend state\n"); 193 194 close(timerfd); 195 } 196 197 int main(int argc, char **argv) 198 { 199 int opt; 200 bool do_suspend = true; 201 bool succeeded = true; 202 unsigned int tests = 0; 203 cpu_set_t available_cpus; 204 int err; 205 int cpu; 206 207 ksft_print_header(); 208 209 while ((opt = getopt(argc, argv, "n")) != -1) { 210 switch (opt) { 211 case 'n': 212 do_suspend = false; 213 break; 214 default: 215 printf("Usage: %s [-n]\n", argv[0]); 216 printf(" -n: do not trigger a suspend/resume cycle before the test\n"); 217 return -1; 218 } 219 } 220 221 err = sched_getaffinity(0, sizeof(available_cpus), &available_cpus); 222 if (err < 0) 223 ksft_exit_fail_msg("sched_getaffinity() failed\n"); 224 225 for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { 226 if (!CPU_ISSET(cpu, &available_cpus)) 227 continue; 228 tests++; 229 } 230 231 if (do_suspend) 232 suspend(); 233 234 ksft_set_plan(tests); 235 for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { 236 int test_success; 237 238 if (!CPU_ISSET(cpu, &available_cpus)) 239 continue; 240 241 test_success = run_test(cpu); 242 switch (test_success) { 243 case KSFT_PASS: 244 ksft_test_result_pass("CPU %d\n", cpu); 245 break; 246 case KSFT_SKIP: 247 ksft_test_result_skip("CPU %d\n", cpu); 248 break; 249 case KSFT_FAIL: 250 ksft_test_result_fail("CPU %d\n", cpu); 251 succeeded = false; 252 break; 253 } 254 } 255 256 if (succeeded) 257 ksft_exit_pass(); 258 else 259 ksft_exit_fail(); 260 } 261