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

test.c (5035B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2019,2021  Arm Limited
      4 * Original author: Dave Martin <Dave.Martin@arm.com>
      5 */
      6
      7#include "system.h"
      8
      9#include <stddef.h>
     10#include <linux/errno.h>
     11#include <linux/auxvec.h>
     12#include <linux/signal.h>
     13#include <asm/sigcontext.h>
     14#include <asm/ucontext.h>
     15
     16typedef struct ucontext ucontext_t;
     17
     18#include "btitest.h"
     19#include "compiler.h"
     20#include "signal.h"
     21
     22#define EXPECTED_TESTS 18
     23
     24static volatile unsigned int test_num = 1;
     25static unsigned int test_passed;
     26static unsigned int test_failed;
     27static unsigned int test_skipped;
     28
     29static void fdputs(int fd, const char *str)
     30{
     31	size_t len = 0;
     32	const char *p = str;
     33
     34	while (*p++)
     35		++len;
     36
     37	write(fd, str, len);
     38}
     39
     40static void putstr(const char *str)
     41{
     42	fdputs(1, str);
     43}
     44
     45static void putnum(unsigned int num)
     46{
     47	char c;
     48
     49	if (num / 10)
     50		putnum(num / 10);
     51
     52	c = '0' + (num % 10);
     53	write(1, &c, 1);
     54}
     55
     56#define puttestname(test_name, trampoline_name) do {	\
     57	putstr(test_name);				\
     58	putstr("/");					\
     59	putstr(trampoline_name);			\
     60} while (0)
     61
     62void print_summary(void)
     63{
     64	putstr("# Totals: pass:");
     65	putnum(test_passed);
     66	putstr(" fail:");
     67	putnum(test_failed);
     68	putstr(" xfail:0 xpass:0 skip:");
     69	putnum(test_skipped);
     70	putstr(" error:0\n");
     71}
     72
     73static const char *volatile current_test_name;
     74static const char *volatile current_trampoline_name;
     75static volatile int sigill_expected, sigill_received;
     76
     77static void handler(int n, siginfo_t *si __always_unused,
     78		    void *uc_ __always_unused)
     79{
     80	ucontext_t *uc = uc_;
     81
     82	putstr("# \t[SIGILL in ");
     83	puttestname(current_test_name, current_trampoline_name);
     84	putstr(", BTYPE=");
     85	write(1, &"00011011"[((uc->uc_mcontext.pstate & PSR_BTYPE_MASK)
     86			      >> PSR_BTYPE_SHIFT) * 2], 2);
     87	if (!sigill_expected) {
     88		putstr("]\n");
     89		putstr("not ok ");
     90		putnum(test_num);
     91		putstr(" ");
     92		puttestname(current_test_name, current_trampoline_name);
     93		putstr("(unexpected SIGILL)\n");
     94		print_summary();
     95		exit(128 + n);
     96	}
     97
     98	putstr(" (expected)]\n");
     99	sigill_received = 1;
    100	/* zap BTYPE so that resuming the faulting code will work */
    101	uc->uc_mcontext.pstate &= ~PSR_BTYPE_MASK;
    102}
    103
    104static int skip_all;
    105
    106static void __do_test(void (*trampoline)(void (*)(void)),
    107		      void (*fn)(void),
    108		      const char *trampoline_name,
    109		      const char *name,
    110		      int expect_sigill)
    111{
    112	if (skip_all) {
    113		test_skipped++;
    114		putstr("ok ");
    115		putnum(test_num);
    116		putstr(" ");
    117		puttestname(name, trampoline_name);
    118		putstr(" # SKIP\n");
    119
    120		return;
    121	}
    122
    123	/* Branch Target exceptions should only happen in BTI binaries: */
    124	if (!BTI)
    125		expect_sigill = 0;
    126
    127	sigill_expected = expect_sigill;
    128	sigill_received = 0;
    129	current_test_name = name;
    130	current_trampoline_name = trampoline_name;
    131
    132	trampoline(fn);
    133
    134	if (expect_sigill && !sigill_received) {
    135		putstr("not ok ");
    136		test_failed++;
    137	} else {
    138		putstr("ok ");
    139		test_passed++;
    140	}
    141	putnum(test_num++);
    142	putstr(" ");
    143	puttestname(name, trampoline_name);
    144	putstr("\n");
    145}
    146
    147#define do_test(expect_sigill_br_x0,					\
    148		expect_sigill_br_x16,					\
    149		expect_sigill_blr,					\
    150		name)							\
    151do {									\
    152	__do_test(call_using_br_x0, name, "call_using_br_x0", #name,	\
    153		  expect_sigill_br_x0);					\
    154	__do_test(call_using_br_x16, name, "call_using_br_x16", #name,	\
    155		  expect_sigill_br_x16);				\
    156	__do_test(call_using_blr, name, "call_using_blr", #name,	\
    157		  expect_sigill_blr);					\
    158} while (0)
    159
    160void start(int *argcp)
    161{
    162	struct sigaction sa;
    163	void *const *p;
    164	const struct auxv_entry {
    165		unsigned long type;
    166		unsigned long val;
    167	} *auxv;
    168	unsigned long hwcap = 0, hwcap2 = 0;
    169
    170	putstr("TAP version 13\n");
    171	putstr("1..");
    172	putnum(EXPECTED_TESTS);
    173	putstr("\n");
    174
    175	/* Gross hack for finding AT_HWCAP2 from the initial process stack: */
    176	p = (void *const *)argcp + 1 + *argcp + 1; /* start of environment */
    177	/* step over environment */
    178	while (*p++)
    179		;
    180	for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) {
    181		switch (auxv->type) {
    182		case AT_HWCAP:
    183			hwcap = auxv->val;
    184			break;
    185		case AT_HWCAP2:
    186			hwcap2 = auxv->val;
    187			break;
    188		default:
    189			break;
    190		}
    191	}
    192
    193	if (hwcap & HWCAP_PACA)
    194		putstr("# HWCAP_PACA present\n");
    195	else
    196		putstr("# HWCAP_PACA not present\n");
    197
    198	if (hwcap2 & HWCAP2_BTI) {
    199		putstr("# HWCAP2_BTI present\n");
    200		if (!(hwcap & HWCAP_PACA))
    201			putstr("# Bad hardware?  Expect problems.\n");
    202	} else {
    203		putstr("# HWCAP2_BTI not present\n");
    204		skip_all = 1;
    205	}
    206
    207	putstr("# Test binary");
    208	if (!BTI)
    209		putstr(" not");
    210	putstr(" built for BTI\n");
    211
    212	sa.sa_handler = (sighandler_t)(void *)handler;
    213	sa.sa_flags = SA_SIGINFO;
    214	sigemptyset(&sa.sa_mask);
    215	sigaction(SIGILL, &sa, NULL);
    216	sigaddset(&sa.sa_mask, SIGILL);
    217	sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
    218
    219	do_test(1, 1, 1, nohint_func);
    220	do_test(1, 1, 1, bti_none_func);
    221	do_test(1, 0, 0, bti_c_func);
    222	do_test(0, 0, 1, bti_j_func);
    223	do_test(0, 0, 0, bti_jc_func);
    224	do_test(1, 0, 0, paciasp_func);
    225
    226	print_summary();
    227
    228	if (test_num - 1 != EXPECTED_TESTS)
    229		putstr("# WARNING - EXPECTED TEST COUNT WRONG\n");
    230
    231	if (test_failed)
    232		exit(1);
    233	else
    234		exit(0);
    235}