12c2ec6bbSKonstantin Belousov /*
22c2ec6bbSKonstantin Belousov * SPDX-License-Identifier: BSD-2-Clause
32c2ec6bbSKonstantin Belousov *
42c2ec6bbSKonstantin Belousov * Copyright 2026 The FreeBSD Foundation
52c2ec6bbSKonstantin Belousov *
62c2ec6bbSKonstantin Belousov * This software were developed by
72c2ec6bbSKonstantin Belousov * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
82c2ec6bbSKonstantin Belousov * the FreeBSD Foundation.
92c2ec6bbSKonstantin Belousov */
102c2ec6bbSKonstantin Belousov
112c2ec6bbSKonstantin Belousov #include <sys/syscall.h>
122c2ec6bbSKonstantin Belousov #include <err.h>
132c2ec6bbSKonstantin Belousov #include <signal.h>
142c2ec6bbSKonstantin Belousov #include <stdatomic.h>
152c2ec6bbSKonstantin Belousov #include <stdio.h>
162c2ec6bbSKonstantin Belousov #include <stdlib.h>
172c2ec6bbSKonstantin Belousov #include <string.h>
182c2ec6bbSKonstantin Belousov #include <unistd.h>
192c2ec6bbSKonstantin Belousov
202c2ec6bbSKonstantin Belousov #ifndef __amd64__
212c2ec6bbSKonstantin Belousov #error "amd64 only"
222c2ec6bbSKonstantin Belousov #endif
232c2ec6bbSKonstantin Belousov
242c2ec6bbSKonstantin Belousov /*
252c2ec6bbSKonstantin Belousov * The check to see how "INT $0x80" behaves for amd64 native ABI
262c2ec6bbSKonstantin Belousov * processes. Before bd8edba0792b71be3f8ed5dea9c22287e95c986a it
272c2ec6bbSKonstantin Belousov * executed syscalls with amd64 calling conventions. After that
282c2ec6bbSKonstantin Belousov * revision, it should raise SIGBUS.
292c2ec6bbSKonstantin Belousov */
302c2ec6bbSKonstantin Belousov
312c2ec6bbSKonstantin Belousov static uintptr_t int0x80_loc;
322c2ec6bbSKonstantin Belousov static int signo;
332c2ec6bbSKonstantin Belousov extern char after_int0x80[];
342c2ec6bbSKonstantin Belousov
352c2ec6bbSKonstantin Belousov static void
sigill_action(int signo1,siginfo_t * si __unused,void * uctxv)362c2ec6bbSKonstantin Belousov sigill_action(int signo1, siginfo_t *si __unused, void *uctxv)
372c2ec6bbSKonstantin Belousov {
382c2ec6bbSKonstantin Belousov ucontext_t *uctx = uctxv;
392c2ec6bbSKonstantin Belousov
402c2ec6bbSKonstantin Belousov signo = signo1;
412c2ec6bbSKonstantin Belousov int0x80_loc = uctx->uc_mcontext.mc_rip;
422c2ec6bbSKonstantin Belousov }
432c2ec6bbSKonstantin Belousov
442c2ec6bbSKonstantin Belousov static int
fire(void)452c2ec6bbSKonstantin Belousov fire(void)
462c2ec6bbSKonstantin Belousov {
472c2ec6bbSKonstantin Belousov int res;
482c2ec6bbSKonstantin Belousov
49*d5728351SRyan Libby res = SYS_getpid;
502c2ec6bbSKonstantin Belousov asm volatile(
512c2ec6bbSKonstantin Belousov ".globl\tafter_int0x80\n"
522c2ec6bbSKonstantin Belousov "\tint\t$0x80\n"
532c2ec6bbSKonstantin Belousov "after_int0x80:"
54*d5728351SRyan Libby : "+a" (res)
55*d5728351SRyan Libby :
562c2ec6bbSKonstantin Belousov : "rdx", "memory", "cc");
572c2ec6bbSKonstantin Belousov return (res);
582c2ec6bbSKonstantin Belousov }
592c2ec6bbSKonstantin Belousov
602c2ec6bbSKonstantin Belousov int
main(void)612c2ec6bbSKonstantin Belousov main(void)
622c2ec6bbSKonstantin Belousov {
632c2ec6bbSKonstantin Belousov struct sigaction sa;
642c2ec6bbSKonstantin Belousov char signame[SIG2STR_MAX];
652c2ec6bbSKonstantin Belousov int pid, res;
662c2ec6bbSKonstantin Belousov
672c2ec6bbSKonstantin Belousov res = 0;
682c2ec6bbSKonstantin Belousov
692c2ec6bbSKonstantin Belousov memset(&sa, 0, sizeof(sa));
702c2ec6bbSKonstantin Belousov sa.sa_sigaction = sigill_action;
712c2ec6bbSKonstantin Belousov sa.sa_flags = SA_SIGINFO;
722c2ec6bbSKonstantin Belousov if (sigaction(SIGBUS, &sa, NULL) == -1)
732c2ec6bbSKonstantin Belousov err(1, "catching SIGBUS");
742c2ec6bbSKonstantin Belousov
752c2ec6bbSKonstantin Belousov pid = fire();
762c2ec6bbSKonstantin Belousov atomic_signal_fence(memory_order_seq_cst);
772c2ec6bbSKonstantin Belousov if (int0x80_loc == 0) {
782c2ec6bbSKonstantin Belousov printf("int $0x80 does not raise SIGBUS\n");
792c2ec6bbSKonstantin Belousov if (pid == getpid())
802c2ec6bbSKonstantin Belousov printf("and syscall worked\n");
812c2ec6bbSKonstantin Belousov else
822c2ec6bbSKonstantin Belousov printf("but syscall did not worked\n");
832c2ec6bbSKonstantin Belousov res = 1;
842c2ec6bbSKonstantin Belousov } else {
852c2ec6bbSKonstantin Belousov sig2str(signo, signame);
862c2ec6bbSKonstantin Belousov printf("int $0x80 raises SIG%s\n", signame);
872c2ec6bbSKonstantin Belousov if (int0x80_loc == (uintptr_t)after_int0x80) {
882c2ec6bbSKonstantin Belousov printf("at expected location\n");
892c2ec6bbSKonstantin Belousov } else {
902c2ec6bbSKonstantin Belousov printf("not at expected location\n");
912c2ec6bbSKonstantin Belousov res = 1;
922c2ec6bbSKonstantin Belousov }
932c2ec6bbSKonstantin Belousov }
942c2ec6bbSKonstantin Belousov exit(res);
952c2ec6bbSKonstantin Belousov }
96