cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

step_after_suspend_test.c (4827B)


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