1 /* Public domain */ 2 3 #include <signal.h> 4 #include <stdint.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 8 extern void foo(void); 9 void (*foobar)(void) = foo; 10 11 void 12 bar(void) 13 { 14 foobar(); 15 } 16 17 void 18 handler(int sig, siginfo_t *si, void *context) 19 { 20 if (si->si_signo == SIGILL && si->si_code == ILL_BTCFI) 21 exit(0); 22 } 23 24 #if defined(__amd64__) 25 26 static int 27 has_btcfi(void) 28 { 29 uint32_t d; 30 31 asm("cpuid" : "=d" (d) : "a" (7), "c" (0)); 32 return (d & (1U << 20)) ? 1 : 0; 33 } 34 35 #elif defined(__aarch64__) 36 37 #include <sys/types.h> 38 #include <sys/sysctl.h> 39 40 #include <machine/armreg.h> 41 #include <machine/cpu.h> 42 43 static int 44 has_btcfi(void) 45 { 46 int mib[] = { CTL_MACHDEP, CPU_ID_AA64PFR1 }; 47 uint64_t id_aa64pfr1 = 0; 48 size_t size = sizeof(id_aa64pfr1); 49 50 sysctl(mib, 2, &id_aa64pfr1, &size, NULL, 0); 51 return ID_AA64PFR1_BT(id_aa64pfr1) >= ID_AA64PFR1_BT_IMPL; 52 } 53 54 #else 55 56 static int 57 has_btcfi(void) 58 { 59 return 0; 60 } 61 62 #endif 63 64 int 65 main(void) 66 { 67 struct sigaction sa; 68 69 if (!has_btcfi()) { 70 printf("Unsupported CPU\n"); 71 printf("SKIPPED\n"); 72 exit(0); 73 } 74 75 sa.sa_sigaction = handler; 76 sa.sa_mask = 0; 77 sa.sa_flags = SA_SIGINFO; 78 sigaction(SIGILL, &sa, NULL); 79 80 bar(); 81 exit(1); 82 } 83