root/tools/testing/selftests/breakpoints/step_after_suspend_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. child
  2. run_test
  3. suspend
  4. main

   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 
  22 #include "../kselftest.h"
  23 
  24 void child(int cpu)
  25 {
  26         cpu_set_t set;
  27 
  28         CPU_ZERO(&set);
  29         CPU_SET(cpu, &set);
  30         if (sched_setaffinity(0, sizeof(set), &set) != 0) {
  31                 ksft_print_msg("sched_setaffinity() failed: %s\n",
  32                         strerror(errno));
  33                 _exit(1);
  34         }
  35 
  36         if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) {
  37                 ksft_print_msg("ptrace(PTRACE_TRACEME) failed: %s\n",
  38                         strerror(errno));
  39                 _exit(1);
  40         }
  41 
  42         if (raise(SIGSTOP) != 0) {
  43                 ksft_print_msg("raise(SIGSTOP) failed: %s\n", strerror(errno));
  44                 _exit(1);
  45         }
  46 
  47         _exit(0);
  48 }
  49 
  50 bool run_test(int cpu)
  51 {
  52         int status;
  53         pid_t pid = fork();
  54         pid_t wpid;
  55 
  56         if (pid < 0) {
  57                 ksft_print_msg("fork() failed: %s\n", strerror(errno));
  58                 return false;
  59         }
  60         if (pid == 0)
  61                 child(cpu);
  62 
  63         wpid = waitpid(pid, &status, __WALL);
  64         if (wpid != pid) {
  65                 ksft_print_msg("waitpid() failed: %s\n", strerror(errno));
  66                 return false;
  67         }
  68         if (!WIFSTOPPED(status)) {
  69                 ksft_print_msg("child did not stop: %s\n", strerror(errno));
  70                 return false;
  71         }
  72         if (WSTOPSIG(status) != SIGSTOP) {
  73                 ksft_print_msg("child did not stop with SIGSTOP: %s\n",
  74                         strerror(errno));
  75                 return false;
  76         }
  77 
  78         if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) {
  79                 if (errno == EIO) {
  80                         ksft_exit_skip(
  81                                 "ptrace(PTRACE_SINGLESTEP) not supported on this architecture: %s\n",
  82                                 strerror(errno));
  83                 }
  84                 ksft_print_msg("ptrace(PTRACE_SINGLESTEP) failed: %s\n",
  85                         strerror(errno));
  86                 return false;
  87         }
  88 
  89         wpid = waitpid(pid, &status, __WALL);
  90         if (wpid != pid) {
  91                 ksft_print_msg("waitpid() failed: $s\n", strerror(errno));
  92                 return false;
  93         }
  94         if (WIFEXITED(status)) {
  95                 ksft_print_msg("child did not single-step: %s\n",
  96                         strerror(errno));
  97                 return false;
  98         }
  99         if (!WIFSTOPPED(status)) {
 100                 ksft_print_msg("child did not stop: %s\n", strerror(errno));
 101                 return false;
 102         }
 103         if (WSTOPSIG(status) != SIGTRAP) {
 104                 ksft_print_msg("child did not stop with SIGTRAP: %s\n",
 105                         strerror(errno));
 106                 return false;
 107         }
 108 
 109         if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) {
 110                 ksft_print_msg("ptrace(PTRACE_CONT) failed: %s\n",
 111                         strerror(errno));
 112                 return false;
 113         }
 114 
 115         wpid = waitpid(pid, &status, __WALL);
 116         if (wpid != pid) {
 117                 ksft_print_msg("waitpid() failed: %s\n", strerror(errno));
 118                 return false;
 119         }
 120         if (!WIFEXITED(status)) {
 121                 ksft_print_msg("child did not exit after PTRACE_CONT: %s\n",
 122                         strerror(errno));
 123                 return false;
 124         }
 125 
 126         return true;
 127 }
 128 
 129 void suspend(void)
 130 {
 131         int power_state_fd;
 132         struct sigevent event = {};
 133         int timerfd;
 134         int err;
 135         struct itimerspec spec = {};
 136 
 137         if (getuid() != 0)
 138                 ksft_exit_skip("Please run the test as root - Exiting.\n");
 139 
 140         power_state_fd = open("/sys/power/state", O_RDWR);
 141         if (power_state_fd < 0)
 142                 ksft_exit_fail_msg(
 143                         "open(\"/sys/power/state\") failed %s)\n",
 144                         strerror(errno));
 145 
 146         timerfd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0);
 147         if (timerfd < 0)
 148                 ksft_exit_fail_msg("timerfd_create() failed\n");
 149 
 150         spec.it_value.tv_sec = 5;
 151         err = timerfd_settime(timerfd, 0, &spec, NULL);
 152         if (err < 0)
 153                 ksft_exit_fail_msg("timerfd_settime() failed\n");
 154 
 155         if (write(power_state_fd, "mem", strlen("mem")) != strlen("mem"))
 156                 ksft_exit_fail_msg("Failed to enter Suspend state\n");
 157 
 158         close(timerfd);
 159         close(power_state_fd);
 160 }
 161 
 162 int main(int argc, char **argv)
 163 {
 164         int opt;
 165         bool do_suspend = true;
 166         bool succeeded = true;
 167         unsigned int tests = 0;
 168         cpu_set_t available_cpus;
 169         int err;
 170         int cpu;
 171 
 172         ksft_print_header();
 173 
 174         while ((opt = getopt(argc, argv, "n")) != -1) {
 175                 switch (opt) {
 176                 case 'n':
 177                         do_suspend = false;
 178                         break;
 179                 default:
 180                         printf("Usage: %s [-n]\n", argv[0]);
 181                         printf("        -n: do not trigger a suspend/resume cycle before the test\n");
 182                         return -1;
 183                 }
 184         }
 185 
 186         for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
 187                 if (!CPU_ISSET(cpu, &available_cpus))
 188                         continue;
 189                 tests++;
 190         }
 191         ksft_set_plan(tests);
 192 
 193         if (do_suspend)
 194                 suspend();
 195 
 196         err = sched_getaffinity(0, sizeof(available_cpus), &available_cpus);
 197         if (err < 0)
 198                 ksft_exit_fail_msg("sched_getaffinity() failed\n");
 199 
 200         for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
 201                 bool test_success;
 202 
 203                 if (!CPU_ISSET(cpu, &available_cpus))
 204                         continue;
 205 
 206                 test_success = run_test(cpu);
 207                 if (test_success) {
 208                         ksft_test_result_pass("CPU %d\n", cpu);
 209                 } else {
 210                         ksft_test_result_fail("CPU %d\n", cpu);
 211                         succeeded = false;
 212                 }
 213         }
 214 
 215         if (succeeded)
 216                 ksft_exit_pass();
 217         else
 218                 ksft_exit_fail();
 219 }

/* [<][>][^][v][top][bottom][index][help] */