tests/sys/arch/amd64: add a program to check INT $0x80 behavior on amd64
Requested and reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D56654
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
TESTSDIR= ${TESTSBASE}/sys/arch/amd64
|
||||
|
||||
PLAIN_TESTS_C+= int0x80
|
||||
|
||||
BINDIR= ${TESTSDIR}
|
||||
|
||||
.include <bsd.test.mk>
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright 2026 The FreeBSD Foundation
|
||||
*
|
||||
* This software were developed by
|
||||
* Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
*/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <err.h>
|
||||
#include <signal.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef __amd64__
|
||||
#error "amd64 only"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The check to see how "INT $0x80" behaves for amd64 native ABI
|
||||
* processes. Before bd8edba0792b71be3f8ed5dea9c22287e95c986a it
|
||||
* executed syscalls with amd64 calling conventions. After that
|
||||
* revision, it should raise SIGBUS.
|
||||
*/
|
||||
|
||||
static uintptr_t int0x80_loc;
|
||||
static int signo;
|
||||
extern char after_int0x80[];
|
||||
|
||||
static void
|
||||
sigill_action(int signo1, siginfo_t *si __unused, void *uctxv)
|
||||
{
|
||||
ucontext_t *uctx = uctxv;
|
||||
|
||||
signo = signo1;
|
||||
int0x80_loc = uctx->uc_mcontext.mc_rip;
|
||||
}
|
||||
|
||||
static int
|
||||
fire(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
asm volatile(
|
||||
".globl\tafter_int0x80\n"
|
||||
"\tint\t$0x80\n"
|
||||
"after_int0x80:"
|
||||
: "=a" (res)
|
||||
: "%0" (SYS_getpid)
|
||||
: "rdx", "memory", "cc");
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
char signame[SIG2STR_MAX];
|
||||
int pid, res;
|
||||
|
||||
res = 0;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_sigaction = sigill_action;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGBUS, &sa, NULL) == -1)
|
||||
err(1, "catching SIGBUS");
|
||||
|
||||
pid = fire();
|
||||
atomic_signal_fence(memory_order_seq_cst);
|
||||
if (int0x80_loc == 0) {
|
||||
printf("int $0x80 does not raise SIGBUS\n");
|
||||
if (pid == getpid())
|
||||
printf("and syscall worked\n");
|
||||
else
|
||||
printf("but syscall did not worked\n");
|
||||
res = 1;
|
||||
} else {
|
||||
sig2str(signo, signame);
|
||||
printf("int $0x80 raises SIG%s\n", signame);
|
||||
if (int0x80_loc == (uintptr_t)after_int0x80) {
|
||||
printf("at expected location\n");
|
||||
} else {
|
||||
printf("not at expected location\n");
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
exit(res);
|
||||
}
|
||||
Reference in New Issue
Block a user