diff options
| -rw-r--r-- | block/io.c | 7 | ||||
| -rw-r--r-- | linux-user/s390x/cpu_loop.c | 66 | ||||
| -rw-r--r-- | meson.build | 2 | ||||
| m--------- | slirp | 0 | ||||
| -rw-r--r-- | tests/tcg/s390x/Makefile.target | 2 | ||||
| -rw-r--r-- | tests/tcg/s390x/trap.c | 102 |
6 files changed, 154 insertions, 25 deletions
diff --git a/block/io.c b/block/io.c index e0a689c584..a19942718b 100644 --- a/block/io.c +++ b/block/io.c @@ -1841,7 +1841,7 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, ret = bdrv_pad_request(bs, &qiov, &qiov_offset, &offset, &bytes, &pad, NULL); if (ret < 0) { - return ret; + goto fail; } tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); @@ -1849,10 +1849,11 @@ int coroutine_fn bdrv_co_preadv_part(BdrvChild *child, bs->bl.request_alignment, qiov, qiov_offset, flags); tracked_request_end(&req); - bdrv_dec_in_flight(bs); - bdrv_padding_destroy(&pad); +fail: + bdrv_dec_in_flight(bs); + return ret; } diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c index f2d1215fb1..6a69a6dd26 100644 --- a/linux-user/s390x/cpu_loop.c +++ b/linux-user/s390x/cpu_loop.c @@ -25,6 +25,35 @@ /* s390x masks the fault address it reports in si_addr for SIGSEGV and SIGBUS */ #define S390X_FAIL_ADDR_MASK -4096LL +static int get_pgm_data_si_code(int dxc_code) +{ + switch (dxc_code) { + /* Non-simulated IEEE exceptions */ + case 0x80: + return TARGET_FPE_FLTINV; + case 0x40: + return TARGET_FPE_FLTDIV; + case 0x20: + case 0x28: + case 0x2c: + return TARGET_FPE_FLTOVF; + case 0x10: + case 0x18: + case 0x1c: + return TARGET_FPE_FLTUND; + case 0x08: + case 0x0c: + return TARGET_FPE_FLTRES; + } + /* + * Non-IEEE and simulated IEEE: + * Includes compare-and-trap, quantum exception, etc. + * Simulated IEEE are included here to match current + * s390x linux kernel. + */ + return 0; +} + void cpu_loop(CPUS390XState *env) { CPUState *cs = env_cpu(env); @@ -64,7 +93,13 @@ void cpu_loop(CPUS390XState *env) case EXCP_DEBUG: sig = TARGET_SIGTRAP; n = TARGET_TRAP_BRKPT; - goto do_signal_pc; + /* + * For SIGTRAP the PSW must point after the instruction, which it + * already does thanks to s390x_tr_tb_stop(). si_addr doesn't need + * to be filled. + */ + addr = 0; + goto do_signal; case EXCP_PGM: n = env->int_pgm_code; switch (n) { @@ -100,29 +135,14 @@ void cpu_loop(CPUS390XState *env) case PGM_DATA: n = (env->fpc >> 8) & 0xff; - if (n == 0xff) { - /* compare-and-trap */ + if (n == 0) { goto do_sigill_opn; - } else { - /* An IEEE exception, simulated or otherwise. */ - if (n & 0x80) { - n = TARGET_FPE_FLTINV; - } else if (n & 0x40) { - n = TARGET_FPE_FLTDIV; - } else if (n & 0x20) { - n = TARGET_FPE_FLTOVF; - } else if (n & 0x10) { - n = TARGET_FPE_FLTUND; - } else if (n & 0x08) { - n = TARGET_FPE_FLTRES; - } else { - /* ??? Quantum exception; BFP, DFP error. */ - goto do_sigill_opn; - } - sig = TARGET_SIGFPE; - goto do_signal_pc; } + sig = TARGET_SIGFPE; + n = get_pgm_data_si_code(n); + goto do_signal_pc; + default: fprintf(stderr, "Unhandled program exception: %#x\n", n); cpu_dump_state(cs, stderr, 0); @@ -132,6 +152,10 @@ void cpu_loop(CPUS390XState *env) do_signal_pc: addr = env->psw.addr; + /* + * For SIGILL and SIGFPE the PSW must point after the instruction. + */ + env->psw.addr += env->int_pgm_ilen; do_signal: info.si_signo = sig; info.si_errno = 0; diff --git a/meson.build b/meson.build index f2e148eaf9..af9bbb83db 100644 --- a/meson.build +++ b/meson.build @@ -1824,6 +1824,8 @@ if have_system slirp_deps = [] if targetos == 'windows' slirp_deps = cc.find_library('iphlpapi') + elif targetos == 'darwin' + slirp_deps = cc.find_library('resolv') endif slirp_conf = configuration_data() slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0]) diff --git a/slirp b/slirp -Subproject 8f43a99191afb47ca3f3c6972f6306209f367ec +Subproject a88d9ace234a24ce1c17189642ef9104799425e diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 5d3de1b27a..bd084c7840 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -8,4 +8,4 @@ TESTS+=exrl-trtr TESTS+=pack TESTS+=mvo TESTS+=mvc - +TESTS+=trap diff --git a/tests/tcg/s390x/trap.c b/tests/tcg/s390x/trap.c new file mode 100644 index 0000000000..d4c61c7f52 --- /dev/null +++ b/tests/tcg/s390x/trap.c @@ -0,0 +1,102 @@ +/* + * Copyright 2021 IBM Corp. + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <signal.h> + +static void error1(const char *filename, int line, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d: ", filename, line); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +static int __chk_error(const char *filename, int line, int ret) +{ + if (ret < 0) { + error1(filename, line, "%m (ret=%d, errno=%d/%s)", + ret, errno, strerror(errno)); + } + return ret; +} + +#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__) + +#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret)) + +int sigfpe_count; +int sigill_count; + +static void sig_handler(int sig, siginfo_t *si, void *puc) +{ + if (sig == SIGFPE) { + if (si->si_code != 0) { + error("unexpected si_code: 0x%x != 0", si->si_code); + } + ++sigfpe_count; + return; + } + + if (sig == SIGILL) { + ++sigill_count; + return; + } + + error("unexpected signal 0x%x\n", sig); +} + +int main(int argc, char **argv) +{ + sigfpe_count = sigill_count = 0; + + struct sigaction act; + + /* Set up SIG handler */ + act.sa_sigaction = sig_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + chk_error(sigaction(SIGFPE, &act, NULL)); + chk_error(sigaction(SIGILL, &act, NULL)); + + uint64_t z = 0x0ull; + uint64_t lz = 0xffffffffffffffffull; + asm volatile ( + "lg %%r13,%[lz]\n" + "cgitne %%r13,0\n" /* SIGFPE */ + "lg %%r13,%[z]\n" + "cgitne %%r13,0\n" /* no trap */ + "nopr\n" + "lg %%r13,%[lz]\n" + "citne %%r13,0\n" /* SIGFPE */ + "lg %%r13,%[z]\n" + "citne %%r13,0\n" /* no trap */ + "nopr\n" + : + : [z] "m" (z), [lz] "m" (lz) + : "memory", "r13"); + + if (sigfpe_count != 2) { + error("unexpected SIGFPE count: %d != 2", sigfpe_count); + } + if (sigill_count != 0) { + error("unexpected SIGILL count: %d != 0", sigill_count); + } + + printf("PASS\n"); + return 0; +} |