xref: /freebsd/tests/sys/arch/amd64/int0x80.c (revision d5728351a58b87764f3302eb8c4ca9f35e99e8b6)
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