1*e7f8a3aaSIlya Leoshkevich #include <assert.h> 2*e7f8a3aaSIlya Leoshkevich #include <signal.h> 3*e7f8a3aaSIlya Leoshkevich #include <string.h> 4*e7f8a3aaSIlya Leoshkevich #include <sys/mman.h> 5*e7f8a3aaSIlya Leoshkevich #include <ucontext.h> 6*e7f8a3aaSIlya Leoshkevich #include <unistd.h> 7*e7f8a3aaSIlya Leoshkevich 8*e7f8a3aaSIlya Leoshkevich /* 9*e7f8a3aaSIlya Leoshkevich * Various instructions that generate SIGILL and SIGSEGV. They could have been 10*e7f8a3aaSIlya Leoshkevich * defined in a separate .s file, but this would complicate the build, so the 11*e7f8a3aaSIlya Leoshkevich * inline asm is used instead. 12*e7f8a3aaSIlya Leoshkevich */ 13*e7f8a3aaSIlya Leoshkevich 14*e7f8a3aaSIlya Leoshkevich void illegal_op(void); 15*e7f8a3aaSIlya Leoshkevich void after_illegal_op(void); 16*e7f8a3aaSIlya Leoshkevich asm(".globl\tillegal_op\n" 17*e7f8a3aaSIlya Leoshkevich "illegal_op:\t.byte\t0x00,0x00\n" 18*e7f8a3aaSIlya Leoshkevich "\t.globl\tafter_illegal_op\n" 19*e7f8a3aaSIlya Leoshkevich "after_illegal_op:\tbr\t%r14"); 20*e7f8a3aaSIlya Leoshkevich 21*e7f8a3aaSIlya Leoshkevich void stg(void *dst, unsigned long src); 22*e7f8a3aaSIlya Leoshkevich asm(".globl\tstg\n" 23*e7f8a3aaSIlya Leoshkevich "stg:\tstg\t%r3,0(%r2)\n" 24*e7f8a3aaSIlya Leoshkevich "\tbr\t%r14"); 25*e7f8a3aaSIlya Leoshkevich 26*e7f8a3aaSIlya Leoshkevich void mvc_8(void *dst, void *src); 27*e7f8a3aaSIlya Leoshkevich asm(".globl\tmvc_8\n" 28*e7f8a3aaSIlya Leoshkevich "mvc_8:\tmvc\t0(8,%r2),0(%r3)\n" 29*e7f8a3aaSIlya Leoshkevich "\tbr\t%r14"); 30*e7f8a3aaSIlya Leoshkevich 31*e7f8a3aaSIlya Leoshkevich static void safe_puts(const char *s) 32*e7f8a3aaSIlya Leoshkevich { 33*e7f8a3aaSIlya Leoshkevich write(0, s, strlen(s)); 34*e7f8a3aaSIlya Leoshkevich write(0, "\n", 1); 35*e7f8a3aaSIlya Leoshkevich } 36*e7f8a3aaSIlya Leoshkevich 37*e7f8a3aaSIlya Leoshkevich enum exception { 38*e7f8a3aaSIlya Leoshkevich exception_operation, 39*e7f8a3aaSIlya Leoshkevich exception_translation, 40*e7f8a3aaSIlya Leoshkevich exception_protection, 41*e7f8a3aaSIlya Leoshkevich }; 42*e7f8a3aaSIlya Leoshkevich 43*e7f8a3aaSIlya Leoshkevich static struct { 44*e7f8a3aaSIlya Leoshkevich int sig; 45*e7f8a3aaSIlya Leoshkevich void *addr; 46*e7f8a3aaSIlya Leoshkevich unsigned long psw_addr; 47*e7f8a3aaSIlya Leoshkevich enum exception exception; 48*e7f8a3aaSIlya Leoshkevich } expected; 49*e7f8a3aaSIlya Leoshkevich 50*e7f8a3aaSIlya Leoshkevich static void handle_signal(int sig, siginfo_t *info, void *ucontext) 51*e7f8a3aaSIlya Leoshkevich { 52*e7f8a3aaSIlya Leoshkevich void *page; 53*e7f8a3aaSIlya Leoshkevich int err; 54*e7f8a3aaSIlya Leoshkevich 55*e7f8a3aaSIlya Leoshkevich if (sig != expected.sig) { 56*e7f8a3aaSIlya Leoshkevich safe_puts("[ FAILED ] wrong signal"); 57*e7f8a3aaSIlya Leoshkevich _exit(1); 58*e7f8a3aaSIlya Leoshkevich } 59*e7f8a3aaSIlya Leoshkevich 60*e7f8a3aaSIlya Leoshkevich if (info->si_addr != expected.addr) { 61*e7f8a3aaSIlya Leoshkevich safe_puts("[ FAILED ] wrong si_addr"); 62*e7f8a3aaSIlya Leoshkevich _exit(1); 63*e7f8a3aaSIlya Leoshkevich } 64*e7f8a3aaSIlya Leoshkevich 65*e7f8a3aaSIlya Leoshkevich if (((ucontext_t *)ucontext)->uc_mcontext.psw.addr != expected.psw_addr) { 66*e7f8a3aaSIlya Leoshkevich safe_puts("[ FAILED ] wrong psw.addr"); 67*e7f8a3aaSIlya Leoshkevich _exit(1); 68*e7f8a3aaSIlya Leoshkevich } 69*e7f8a3aaSIlya Leoshkevich 70*e7f8a3aaSIlya Leoshkevich switch (expected.exception) { 71*e7f8a3aaSIlya Leoshkevich case exception_translation: 72*e7f8a3aaSIlya Leoshkevich page = mmap(expected.addr, 4096, PROT_READ | PROT_WRITE, 73*e7f8a3aaSIlya Leoshkevich MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 74*e7f8a3aaSIlya Leoshkevich if (page != expected.addr) { 75*e7f8a3aaSIlya Leoshkevich safe_puts("[ FAILED ] mmap() failed"); 76*e7f8a3aaSIlya Leoshkevich _exit(1); 77*e7f8a3aaSIlya Leoshkevich } 78*e7f8a3aaSIlya Leoshkevich break; 79*e7f8a3aaSIlya Leoshkevich case exception_protection: 80*e7f8a3aaSIlya Leoshkevich err = mprotect(expected.addr, 4096, PROT_READ | PROT_WRITE); 81*e7f8a3aaSIlya Leoshkevich if (err != 0) { 82*e7f8a3aaSIlya Leoshkevich safe_puts("[ FAILED ] mprotect() failed"); 83*e7f8a3aaSIlya Leoshkevich _exit(1); 84*e7f8a3aaSIlya Leoshkevich } 85*e7f8a3aaSIlya Leoshkevich break; 86*e7f8a3aaSIlya Leoshkevich default: 87*e7f8a3aaSIlya Leoshkevich break; 88*e7f8a3aaSIlya Leoshkevich } 89*e7f8a3aaSIlya Leoshkevich } 90*e7f8a3aaSIlya Leoshkevich 91*e7f8a3aaSIlya Leoshkevich static void check_sigsegv(void *func, enum exception exception, 92*e7f8a3aaSIlya Leoshkevich unsigned long val) 93*e7f8a3aaSIlya Leoshkevich { 94*e7f8a3aaSIlya Leoshkevich int prot; 95*e7f8a3aaSIlya Leoshkevich unsigned long *page; 96*e7f8a3aaSIlya Leoshkevich unsigned long *addr; 97*e7f8a3aaSIlya Leoshkevich int err; 98*e7f8a3aaSIlya Leoshkevich 99*e7f8a3aaSIlya Leoshkevich prot = exception == exception_translation ? PROT_NONE : PROT_READ; 100*e7f8a3aaSIlya Leoshkevich page = mmap(NULL, 4096, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 101*e7f8a3aaSIlya Leoshkevich assert(page != MAP_FAILED); 102*e7f8a3aaSIlya Leoshkevich if (exception == exception_translation) { 103*e7f8a3aaSIlya Leoshkevich /* Hopefully nothing will be mapped at this address. */ 104*e7f8a3aaSIlya Leoshkevich err = munmap(page, 4096); 105*e7f8a3aaSIlya Leoshkevich assert(err == 0); 106*e7f8a3aaSIlya Leoshkevich } 107*e7f8a3aaSIlya Leoshkevich addr = page + (val & 0x1ff); 108*e7f8a3aaSIlya Leoshkevich 109*e7f8a3aaSIlya Leoshkevich expected.sig = SIGSEGV; 110*e7f8a3aaSIlya Leoshkevich expected.addr = page; 111*e7f8a3aaSIlya Leoshkevich expected.psw_addr = (unsigned long)func; 112*e7f8a3aaSIlya Leoshkevich expected.exception = exception; 113*e7f8a3aaSIlya Leoshkevich if (func == stg) { 114*e7f8a3aaSIlya Leoshkevich stg(addr, val); 115*e7f8a3aaSIlya Leoshkevich } else { 116*e7f8a3aaSIlya Leoshkevich assert(func == mvc_8); 117*e7f8a3aaSIlya Leoshkevich mvc_8(addr, &val); 118*e7f8a3aaSIlya Leoshkevich } 119*e7f8a3aaSIlya Leoshkevich assert(*addr == val); 120*e7f8a3aaSIlya Leoshkevich 121*e7f8a3aaSIlya Leoshkevich err = munmap(page, 4096); 122*e7f8a3aaSIlya Leoshkevich assert(err == 0); 123*e7f8a3aaSIlya Leoshkevich } 124*e7f8a3aaSIlya Leoshkevich 125*e7f8a3aaSIlya Leoshkevich int main(void) 126*e7f8a3aaSIlya Leoshkevich { 127*e7f8a3aaSIlya Leoshkevich struct sigaction act; 128*e7f8a3aaSIlya Leoshkevich int err; 129*e7f8a3aaSIlya Leoshkevich 130*e7f8a3aaSIlya Leoshkevich memset(&act, 0, sizeof(act)); 131*e7f8a3aaSIlya Leoshkevich act.sa_sigaction = handle_signal; 132*e7f8a3aaSIlya Leoshkevich act.sa_flags = SA_SIGINFO; 133*e7f8a3aaSIlya Leoshkevich err = sigaction(SIGILL, &act, NULL); 134*e7f8a3aaSIlya Leoshkevich assert(err == 0); 135*e7f8a3aaSIlya Leoshkevich err = sigaction(SIGSEGV, &act, NULL); 136*e7f8a3aaSIlya Leoshkevich assert(err == 0); 137*e7f8a3aaSIlya Leoshkevich 138*e7f8a3aaSIlya Leoshkevich safe_puts("[ RUN ] Operation exception"); 139*e7f8a3aaSIlya Leoshkevich expected.sig = SIGILL; 140*e7f8a3aaSIlya Leoshkevich expected.addr = illegal_op; 141*e7f8a3aaSIlya Leoshkevich expected.psw_addr = (unsigned long)after_illegal_op; 142*e7f8a3aaSIlya Leoshkevich expected.exception = exception_operation; 143*e7f8a3aaSIlya Leoshkevich illegal_op(); 144*e7f8a3aaSIlya Leoshkevich safe_puts("[ OK ]"); 145*e7f8a3aaSIlya Leoshkevich 146*e7f8a3aaSIlya Leoshkevich safe_puts("[ RUN ] Translation exception from stg"); 147*e7f8a3aaSIlya Leoshkevich check_sigsegv(stg, exception_translation, 42); 148*e7f8a3aaSIlya Leoshkevich safe_puts("[ OK ]"); 149*e7f8a3aaSIlya Leoshkevich 150*e7f8a3aaSIlya Leoshkevich safe_puts("[ RUN ] Translation exception from mvc"); 151*e7f8a3aaSIlya Leoshkevich check_sigsegv(mvc_8, exception_translation, 4242); 152*e7f8a3aaSIlya Leoshkevich safe_puts("[ OK ]"); 153*e7f8a3aaSIlya Leoshkevich 154*e7f8a3aaSIlya Leoshkevich safe_puts("[ RUN ] Protection exception from stg"); 155*e7f8a3aaSIlya Leoshkevich check_sigsegv(stg, exception_protection, 424242); 156*e7f8a3aaSIlya Leoshkevich safe_puts("[ OK ]"); 157*e7f8a3aaSIlya Leoshkevich 158*e7f8a3aaSIlya Leoshkevich safe_puts("[ RUN ] Protection exception from mvc"); 159*e7f8a3aaSIlya Leoshkevich check_sigsegv(mvc_8, exception_protection, 42424242); 160*e7f8a3aaSIlya Leoshkevich safe_puts("[ OK ]"); 161*e7f8a3aaSIlya Leoshkevich 162*e7f8a3aaSIlya Leoshkevich safe_puts("[ PASSED ]"); 163*e7f8a3aaSIlya Leoshkevich 164*e7f8a3aaSIlya Leoshkevich _exit(0); 165*e7f8a3aaSIlya Leoshkevich } 166