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