Path: blob/master/tools/testing/selftests/arm64/bti/test.c
26299 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (C) 2019,2021 Arm Limited3* Original author: Dave Martin <[email protected]>4*/56#include "system.h"78#include <stdbool.h>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>1516typedef struct ucontext ucontext_t;1718#include "btitest.h"19#include "signal.h"2021#define EXPECTED_TESTS 182223static volatile unsigned int test_num = 1;24static unsigned int test_passed;25static unsigned int test_failed;26static unsigned int test_skipped;2728static void fdputs(int fd, const char *str)29{30size_t len = 0;31const char *p = str;3233while (*p++)34++len;3536write(fd, str, len);37}3839static void putstr(const char *str)40{41fdputs(1, str);42}4344static void putnum(unsigned int num)45{46char c;4748if (num / 10)49putnum(num / 10);5051c = '0' + (num % 10);52write(1, &c, 1);53}5455#define puttestname(test_name, trampoline_name) do { \56putstr(test_name); \57putstr("/"); \58putstr(trampoline_name); \59} while (0)6061void print_summary(void)62{63putstr("# Totals: pass:");64putnum(test_passed);65putstr(" fail:");66putnum(test_failed);67putstr(" xfail:0 xpass:0 skip:");68putnum(test_skipped);69putstr(" error:0\n");70}7172static const char *volatile current_test_name;73static const char *volatile current_trampoline_name;74static volatile int sigill_expected, sigill_received;7576static void handler(int n, siginfo_t *si __always_unused,77void *uc_ __always_unused)78{79ucontext_t *uc = uc_;8081putstr("# \t[SIGILL in ");82puttestname(current_test_name, current_trampoline_name);83putstr(", BTYPE=");84write(1, &"00011011"[((uc->uc_mcontext.pstate & PSR_BTYPE_MASK)85>> PSR_BTYPE_SHIFT) * 2], 2);86if (!sigill_expected) {87putstr("]\n");88putstr("not ok ");89putnum(test_num);90putstr(" ");91puttestname(current_test_name, current_trampoline_name);92putstr("(unexpected SIGILL)\n");93print_summary();94exit(128 + n);95}9697putstr(" (expected)]\n");98sigill_received = 1;99/* zap BTYPE so that resuming the faulting code will work */100uc->uc_mcontext.pstate &= ~PSR_BTYPE_MASK;101}102103/* Does the system have BTI? */104static bool have_bti;105106static void __do_test(void (*trampoline)(void (*)(void)),107void (*fn)(void),108const char *trampoline_name,109const char *name,110int expect_sigill)111{112/*113* Branch Target exceptions should only happen for BTI114* binaries running on a system with BTI:115*/116if (!BTI || !have_bti)117expect_sigill = 0;118119sigill_expected = expect_sigill;120sigill_received = 0;121current_test_name = name;122current_trampoline_name = trampoline_name;123124trampoline(fn);125126if (expect_sigill && !sigill_received) {127putstr("not ok ");128test_failed++;129} else {130putstr("ok ");131test_passed++;132}133putnum(test_num++);134putstr(" ");135puttestname(name, trampoline_name);136putstr("\n");137}138139#define do_test(expect_sigill_br_x0, \140expect_sigill_br_x16, \141expect_sigill_blr, \142name) \143do { \144__do_test(call_using_br_x0, name, "call_using_br_x0", #name, \145expect_sigill_br_x0); \146__do_test(call_using_br_x16, name, "call_using_br_x16", #name, \147expect_sigill_br_x16); \148__do_test(call_using_blr, name, "call_using_blr", #name, \149expect_sigill_blr); \150} while (0)151152void start(int *argcp)153{154struct sigaction sa;155void *const *p;156const struct auxv_entry {157unsigned long type;158unsigned long val;159} *auxv;160unsigned long hwcap = 0, hwcap2 = 0;161162putstr("TAP version 13\n");163putstr("1..");164putnum(EXPECTED_TESTS);165putstr("\n");166167/* Gross hack for finding AT_HWCAP2 from the initial process stack: */168p = (void *const *)argcp + 1 + *argcp + 1; /* start of environment */169/* step over environment */170while (*p++)171;172for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) {173switch (auxv->type) {174case AT_HWCAP:175hwcap = auxv->val;176break;177case AT_HWCAP2:178hwcap2 = auxv->val;179break;180default:181break;182}183}184185if (hwcap & HWCAP_PACA)186putstr("# HWCAP_PACA present\n");187else188putstr("# HWCAP_PACA not present\n");189190if (hwcap2 & HWCAP2_BTI) {191putstr("# HWCAP2_BTI present\n");192if (!(hwcap & HWCAP_PACA))193putstr("# Bad hardware? Expect problems.\n");194have_bti = true;195} else {196putstr("# HWCAP2_BTI not present\n");197have_bti = false;198}199200putstr("# Test binary");201if (!BTI)202putstr(" not");203putstr(" built for BTI\n");204205sa.sa_handler = (sighandler_t)(void *)handler;206sa.sa_flags = SA_SIGINFO;207sigemptyset(&sa.sa_mask);208sigaction(SIGILL, &sa, NULL);209sigaddset(&sa.sa_mask, SIGILL);210sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);211212do_test(1, 1, 1, nohint_func);213do_test(1, 1, 1, bti_none_func);214do_test(1, 0, 0, bti_c_func);215do_test(0, 0, 1, bti_j_func);216do_test(0, 0, 0, bti_jc_func);217do_test(1, 0, 0, paciasp_func);218219print_summary();220221if (test_num - 1 != EXPECTED_TESTS)222putstr("# WARNING - EXPECTED TEST COUNT WRONG\n");223224if (test_failed)225exit(1);226else227exit(0);228}229230231