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

za-fork.c (2949B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2022 ARM Limited.
      4 * Original author: Mark Brown <broonie@kernel.org>
      5 */
      6
      7// SPDX-License-Identifier: GPL-2.0-only
      8
      9#include <linux/sched.h>
     10#include <linux/wait.h>
     11
     12#define EXPECTED_TESTS 1
     13
     14static void putstr(const char *str)
     15{
     16	write(1, str, strlen(str));
     17}
     18
     19static void putnum(unsigned int num)
     20{
     21	char c;
     22
     23	if (num / 10)
     24		putnum(num / 10);
     25
     26	c = '0' + (num % 10);
     27	write(1, &c, 1);
     28}
     29
     30static int tests_run;
     31static int tests_passed;
     32static int tests_failed;
     33static int tests_skipped;
     34
     35static void print_summary(void)
     36{
     37	if (tests_passed + tests_failed + tests_skipped != EXPECTED_TESTS)
     38		putstr("# UNEXPECTED TEST COUNT: ");
     39
     40	putstr("# Totals: pass:");
     41	putnum(tests_passed);
     42	putstr(" fail:");
     43	putnum(tests_failed);
     44	putstr(" xfail:0 xpass:0 skip:");
     45	putnum(tests_skipped);
     46	putstr(" error:0\n");
     47}
     48
     49int fork_test(void);
     50int verify_fork(void);
     51
     52/*
     53 * If we fork the value in the parent should be unchanged and the
     54 * child should start with the same value.  This is called from the
     55 * fork_test() asm function.
     56 */
     57int fork_test_c(void)
     58{
     59	pid_t newpid, waiting;
     60	int child_status, parent_result;
     61
     62	newpid = fork();
     63	if (newpid == 0) {
     64		/* In child */
     65		if (!verify_fork()) {
     66			putstr("# ZA state invalid in child\n");
     67			exit(0);
     68		} else {
     69			exit(1);
     70		}
     71	}
     72	if (newpid < 0) {
     73		putstr("# fork() failed: -");
     74		putnum(-newpid);
     75		putstr("\n");
     76		return 0;
     77	}
     78
     79	parent_result = verify_fork();
     80	if (!parent_result)
     81		putstr("# ZA state invalid in parent\n");
     82
     83	for (;;) {
     84		waiting = waitpid(newpid, &child_status, 0);
     85
     86		if (waiting < 0) {
     87			if (errno == EINTR)
     88				continue;
     89			putstr("# waitpid() failed: ");
     90			putnum(errno);
     91			putstr("\n");
     92			return 0;
     93		}
     94		if (waiting != newpid) {
     95			putstr("# waitpid() returned wrong PID\n");
     96			return 0;
     97		}
     98
     99		if (!WIFEXITED(child_status)) {
    100			putstr("# child did not exit\n");
    101			return 0;
    102		}
    103
    104		return WEXITSTATUS(child_status) && parent_result;
    105	}
    106}
    107
    108#define run_test(name)			     \
    109	if (name()) {			     \
    110		tests_passed++;		     \
    111	} else {			     \
    112		tests_failed++;		     \
    113		putstr("not ");		     \
    114	}				     \
    115	putstr("ok ");			     \
    116	putnum(++tests_run);		     \
    117	putstr(" " #name "\n");
    118
    119int main(int argc, char **argv)
    120{
    121	int ret, i;
    122
    123	putstr("TAP version 13\n");
    124	putstr("1..");
    125	putnum(EXPECTED_TESTS);
    126	putstr("\n");
    127
    128	putstr("# PID: ");
    129	putnum(getpid());
    130	putstr("\n");
    131
    132	/*
    133	 * This test is run with nolibc which doesn't support hwcap and
    134	 * it's probably disproportionate to implement so instead check
    135	 * for the default vector length configuration in /proc.
    136	 */
    137	ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0);
    138	if (ret >= 0) {
    139		run_test(fork_test);
    140
    141	} else {
    142		putstr("# SME support not present\n");
    143
    144		for (i = 0; i < EXPECTED_TESTS; i++) {
    145			putstr("ok ");
    146			putnum(i);
    147			putstr(" skipped\n");
    148		}
    149
    150		tests_skipped += EXPECTED_TESTS;
    151	}
    152
    153	print_summary();
    154
    155	return 0;
    156}