Move the KVM "eat signals" code under CONFIG_LINUX, in preparation for moving it to kvm-all.c; reraise non-MCE SIGBUS immediately, without passing it to KVM. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- cpus.c | 63 ++++++++++++++++++++++++++-------------------------- include/qemu/osdep.h | 9 ++++++++ target/i386/kvm.c | 15 ++----------- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/cpus.c b/cpus.c index b28e08e..ce80783 100644 --- a/cpus.c +++ b/cpus.c @@ -792,6 +792,10 @@ static void sigbus_reraise(void) static void sigbus_handler(int n, siginfo_t *siginfo, void *ctx) { + if (siginfo->si_code != BUS_MCEERR_AO && siginfo->si_code != BUS_MCEERR_AR) { + sigbus_reraise(); + } + if (kvm_on_sigbus(siginfo->si_code, siginfo->si_addr)) { sigbus_reraise(); } @@ -809,6 +813,30 @@ static void qemu_init_sigbus(void) prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0); } +static void dummy_signal(int sig) +{ +} + +static void qemu_kvm_init_cpu_signals(CPUState *cpu) +{ + int r; + sigset_t set; + struct sigaction sigact; + + memset(&sigact, 0, sizeof(sigact)); + sigact.sa_handler = dummy_signal; + sigaction(SIG_IPI, &sigact, NULL); + + pthread_sigmask(SIG_BLOCK, NULL, &set); + sigdelset(&set, SIG_IPI); + sigdelset(&set, SIGBUS); + r = kvm_set_signal_mask(cpu, &set); + if (r) { + fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r)); + exit(1); + } +} + static void qemu_kvm_eat_signals(CPUState *cpu) { struct timespec ts = { 0, 0 }; @@ -830,6 +858,9 @@ static void qemu_kvm_eat_signals(CPUState *cpu) switch (r) { case SIGBUS: + if (siginfo.si_code != BUS_MCEERR_AO && siginfo.si_code != BUS_MCEERR_AR) { + sigbus_reraise(); + } if (kvm_on_sigbus_vcpu(cpu, siginfo.si_code, siginfo.si_addr)) { sigbus_reraise(); } @@ -845,9 +876,7 @@ static void qemu_kvm_eat_signals(CPUState *cpu) } } while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS)); } - #else /* !CONFIG_LINUX */ - static void qemu_init_sigbus(void) { } @@ -855,39 +884,11 @@ static void qemu_init_sigbus(void) static void qemu_kvm_eat_signals(CPUState *cpu) { } -#endif /* !CONFIG_LINUX */ - -#ifndef _WIN32 -static void dummy_signal(int sig) -{ -} - -static void qemu_kvm_init_cpu_signals(CPUState *cpu) -{ - int r; - sigset_t set; - struct sigaction sigact; - - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = dummy_signal; - sigaction(SIG_IPI, &sigact, NULL); - - pthread_sigmask(SIG_BLOCK, NULL, &set); - sigdelset(&set, SIG_IPI); - sigdelset(&set, SIGBUS); - r = kvm_set_signal_mask(cpu, &set); - if (r) { - fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(-r)); - exit(1); - } -} -#else /* _WIN32 */ static void qemu_kvm_init_cpu_signals(CPUState *cpu) { - abort(); } -#endif /* _WIN32 */ +#endif /* !CONFIG_LINUX */ static QemuMutex qemu_global_mutex; static QemuCond qemu_io_proceeded_cond; diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 5201dbd..48bed95 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -277,6 +277,15 @@ void qemu_anon_ram_free(void *ptr, size_t size); #endif +#if defined(CONFIG_LINUX) +#ifndef BUS_MCEERR_AR +#define BUS_MCEERR_AR 4 +#endif +#ifndef BUS_MCEERR_AO +#define BUS_MCEERR_AO 5 +#endif +#endif + #if defined(__linux__) && \ (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)) /* Use 2 MiB alignment so transparent hugepages can be used by KVM. diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 0c48dfd..f49a786 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -64,13 +64,6 @@ * 255 kvm_msr_entry structs */ #define MSR_BUF_SIZE 4096 -#ifndef BUS_MCEERR_AR -#define BUS_MCEERR_AR 4 -#endif -#ifndef BUS_MCEERR_AO -#define BUS_MCEERR_AO 5 -#endif - const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_INFO(SET_TSS_ADDR), KVM_CAP_INFO(EXT_CPUID), @@ -469,9 +462,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) ram_addr_t ram_addr; hwaddr paddr; - if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) { - return 1; - } + assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO); /* Because the MCE happened while running the VCPU, KVM could have * injected action required MCEs too. Action optional MCEs should @@ -504,9 +495,7 @@ int kvm_arch_on_sigbus(int code, void *addr) { X86CPU *cpu = X86_CPU(first_cpu); - if (code != BUS_MCEERR_AR && code != BUS_MCEERR_AO) { - return 1; - } + assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO); if (code == BUS_MCEERR_AR) { hardware_memory_error(); -- 1.8.3.1