// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019,2021 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "system.h"
#include <stdbool.h>
#include <stddef.h>
#include <linux/errno.h>
#include <linux/auxvec.h>
#include <linux/signal.h>
#include <asm /sigcontext.h>
#include <asm /ucontext.h>
typedef struct ucontext ucontext_t;
#include "btitest.h"
#include "signal.h"
#define EXPECTED_TESTS 18
static volatile unsigned int test_num = 1;
static unsigned int test_passed;
static unsigned int test_failed;
static unsigned int test_skipped;
static void fdputs(int fd, const char *str)
{
size_t len = 0;
const char *p = str;
while (*p++)
++len;
write(fd, str, len);
}
static void putstr(const char *str)
{
fdputs(1, str);
}
static void putnum(unsigned int num)
{
char c;
if (num / 10)
putnum(num / 10);
c = '0' + (num % 10);
write(1, &c, 1);
}
#define puttestname(test_name, trampoline_name) do { \
putstr(test_name); \
putstr("/" ); \
putstr(trampoline_name); \
} while (0)
void print_summary(void )
{
putstr("# Totals: pass:" );
putnum(test_passed);
putstr(" fail:" );
putnum(test_failed);
putstr(" xfail:0 xpass:0 skip:" );
putnum(test_skipped);
putstr(" error:0\n" );
}
static const char *volatile current_test_name;
static const char *volatile current_trampoline_name;
static volatile int sigill_expected, sigill_received;
static void handler(int n, siginfo_t *si __always_unused,
void *uc_ __always_unused)
{
ucontext_t *uc = uc_;
putstr("# \t[SIGILL in " );
puttestname(current_test_name, current_trampoline_name);
putstr(", BTYPE=" );
write(1, &"00011011" [((uc->uc_mcontext.pstate & PSR_BTYPE_MASK)
>> PSR_BTYPE_SHIFT) * 2], 2);
if (!sigill_expected) {
putstr("]\n" );
putstr("not ok " );
putnum(test_num);
putstr(" " );
puttestname(current_test_name, current_trampoline_name);
putstr("(unexpected SIGILL)\n" );
print_summary();
exit (128 + n);
}
putstr(" (expected)]\n" );
sigill_received = 1;
/* zap BTYPE so that resuming the faulting code will work */
uc->uc_mcontext.pstate &= ~PSR_BTYPE_MASK;
}
/* Does the system have BTI? */
static bool have_bti;
static void __do_test(void (*trampoline)(void (*)(void )),
void (*fn)(void ),
const char *trampoline_name,
const char *name,
int expect_sigill)
{
/*
* Branch Target exceptions should only happen for BTI
* binaries running on a system with BTI:
*/
if (!BTI || !have_bti)
expect_sigill = 0;
sigill_expected = expect_sigill;
sigill_received = 0;
current_test_name = name;
current_trampoline_name = trampoline_name;
trampoline(fn);
if (expect_sigill && !sigill_received) {
putstr("not ok " );
test_failed++;
} else {
putstr("ok " );
test_passed++;
}
putnum(test_num++);
putstr(" " );
puttestname(name, trampoline_name);
putstr("\n" );
}
#define do_test(expect_sigill_br_x0, \
expect_sigill_br_x16, \
expect_sigill_blr, \
name) \
do { \
__do_test(call_using_br_x0, name, "call_using_br_x0" , #name , \
expect_sigill_br_x0); \
__do_test(call_using_br_x16, name, "call_using_br_x16" , #name , \
expect_sigill_br_x16); \
__do_test(call_using_blr, name, "call_using_blr" , #name , \
expect_sigill_blr); \
} while (0)
void start(int *argcp)
{
struct sigaction sa;
void *const *p;
const struct auxv_entry {
unsigned long type;
unsigned long val;
} *auxv;
unsigned long hwcap = 0, hwcap2 = 0;
putstr("TAP version 13\n" );
putstr("1.." );
putnum(EXPECTED_TESTS);
putstr("\n" );
/* Gross hack for finding AT_HWCAP2 from the initial process stack: */
p = (void *const *)argcp + 1 + *argcp + 1; /* start of environment */
/* step over environment */
while (*p++)
;
for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) {
switch (auxv->type) {
case AT_HWCAP:
hwcap = auxv->val;
break ;
case AT_HWCAP2:
hwcap2 = auxv->val;
break ;
default :
break ;
}
}
if (hwcap & HWCAP_PACA)
putstr("# HWCAP_PACA present\n" );
else
putstr("# HWCAP_PACA not present\n" );
if (hwcap2 & HWCAP2_BTI) {
putstr("# HWCAP2_BTI present\n" );
if (!(hwcap & HWCAP_PACA))
putstr("# Bad hardware? Expect problems.\n" );
have_bti = true ;
} else {
putstr("# HWCAP2_BTI not present\n" );
have_bti = false ;
}
putstr("# Test binary" );
if (!BTI)
putstr(" not" );
putstr(" built for BTI\n" );
sa.sa_handler = (sighandler_t)(void *)handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sigaction(SIGILL, &sa, NULL);
sigaddset(&sa.sa_mask, SIGILL);
sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
do_test(1, 1, 1, nohint_func);
do_test(1, 1, 1, bti_none_func);
do_test(1, 0, 0, bti_c_func);
do_test(0, 0, 1, bti_j_func);
do_test(0, 0, 0, bti_jc_func);
do_test(1, 0, 0, paciasp_func);
print_summary();
if (test_num - 1 != EXPECTED_TESTS)
putstr("# WARNING - EXPECTED TEST COUNT WRONG\n" );
if (test_failed)
exit (1);
else
exit (0);
}
Messung V0.5 C=98 H=98 G=97
¤ Dauer der Verarbeitung: 0.3 Sekunden
¤
*© Formatika GbR, Deutschland