brintos

brintos / linux-shallow public Read only

0
0
Text · 4.9 KiB · 28a8e8a Raw
230 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2019,2021  Arm Limited4 * Original author: Dave Martin <Dave.Martin@arm.com>5 */6 7#include "system.h"8 9#include <stdbool.h>10#include <stddef.h>11#include <linux/errno.h>12#include <linux/auxvec.h>13#include <linux/signal.h>14#include <asm/sigcontext.h>15#include <asm/ucontext.h>16 17typedef struct ucontext ucontext_t;18 19#include "btitest.h"20#include "signal.h"21 22#define EXPECTED_TESTS 1823 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 104/* Does the system have BTI? */105static bool have_bti;106 107static void __do_test(void (*trampoline)(void (*)(void)),108		      void (*fn)(void),109		      const char *trampoline_name,110		      const char *name,111		      int expect_sigill)112{113	/*114	 * Branch Target exceptions should only happen for BTI115	 * binaries running on a system with BTI:116	 */117	if (!BTI || !have_bti)118		expect_sigill = 0;119 120	sigill_expected = expect_sigill;121	sigill_received = 0;122	current_test_name = name;123	current_trampoline_name = trampoline_name;124 125	trampoline(fn);126 127	if (expect_sigill && !sigill_received) {128		putstr("not ok ");129		test_failed++;130	} else {131		putstr("ok ");132		test_passed++;133	}134	putnum(test_num++);135	putstr(" ");136	puttestname(name, trampoline_name);137	putstr("\n");138}139 140#define do_test(expect_sigill_br_x0,					\141		expect_sigill_br_x16,					\142		expect_sigill_blr,					\143		name)							\144do {									\145	__do_test(call_using_br_x0, name, "call_using_br_x0", #name,	\146		  expect_sigill_br_x0);					\147	__do_test(call_using_br_x16, name, "call_using_br_x16", #name,	\148		  expect_sigill_br_x16);				\149	__do_test(call_using_blr, name, "call_using_blr", #name,	\150		  expect_sigill_blr);					\151} while (0)152 153void start(int *argcp)154{155	struct sigaction sa;156	void *const *p;157	const struct auxv_entry {158		unsigned long type;159		unsigned long val;160	} *auxv;161	unsigned long hwcap = 0, hwcap2 = 0;162 163	putstr("TAP version 13\n");164	putstr("1..");165	putnum(EXPECTED_TESTS);166	putstr("\n");167 168	/* Gross hack for finding AT_HWCAP2 from the initial process stack: */169	p = (void *const *)argcp + 1 + *argcp + 1; /* start of environment */170	/* step over environment */171	while (*p++)172		;173	for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) {174		switch (auxv->type) {175		case AT_HWCAP:176			hwcap = auxv->val;177			break;178		case AT_HWCAP2:179			hwcap2 = auxv->val;180			break;181		default:182			break;183		}184	}185 186	if (hwcap & HWCAP_PACA)187		putstr("# HWCAP_PACA present\n");188	else189		putstr("# HWCAP_PACA not present\n");190 191	if (hwcap2 & HWCAP2_BTI) {192		putstr("# HWCAP2_BTI present\n");193		if (!(hwcap & HWCAP_PACA))194			putstr("# Bad hardware?  Expect problems.\n");195		have_bti = true;196	} else {197		putstr("# HWCAP2_BTI not present\n");198		have_bti = false;199	}200 201	putstr("# Test binary");202	if (!BTI)203		putstr(" not");204	putstr(" built for BTI\n");205 206	sa.sa_handler = (sighandler_t)(void *)handler;207	sa.sa_flags = SA_SIGINFO;208	sigemptyset(&sa.sa_mask);209	sigaction(SIGILL, &sa, NULL);210	sigaddset(&sa.sa_mask, SIGILL);211	sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);212 213	do_test(1, 1, 1, nohint_func);214	do_test(1, 1, 1, bti_none_func);215	do_test(1, 0, 0, bti_c_func);216	do_test(0, 0, 1, bti_j_func);217	do_test(0, 0, 0, bti_jc_func);218	do_test(1, 0, 0, paciasp_func);219 220	print_summary();221 222	if (test_num - 1 != EXPECTED_TESTS)223		putstr("# WARNING - EXPECTED TEST COUNT WRONG\n");224 225	if (test_failed)226		exit(1);227	else228		exit(0);229}230