diff --git a/cpus.c b/cpus.c index a628cde23260a82cba51c9146336fe8bdf7e854d..399e2713b831256b8a5aef156c9de53d9b4d827c 100644 --- a/cpus.c +++ b/cpus.c @@ -922,6 +922,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(); } @@ -939,6 +943,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 }; @@ -960,6 +988,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(); } @@ -975,9 +1006,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) { } @@ -985,39 +1014,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; diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 6932709e4ea4473b8fb1f3f5ed1019838574399f..af37195fef469e9198a24eec2efd5840e6b808d2 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -284,6 +284,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 0c48dfdae5fed569c0c5ba3db842e321109ca4f9..f49a786c9858422981377d4294b64a4ce42a5156 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();