diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/i386/helper.c | 47 | ||||
-rw-r--r-- | target/i386/kvm.c | 13 |
2 files changed, 49 insertions, 11 deletions
diff --git a/target/i386/helper.c b/target/i386/helper.c index 70be53e..32fa21a 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -18,6 +18,7 @@ */ #include "qemu/osdep.h" +#include "qapi/qapi-events-run-state.h" #include "cpu.h" #include "exec/exec-all.h" #include "qemu/qemu-print.h" @@ -851,22 +852,35 @@ typedef struct MCEInjectionParams { int flags; } MCEInjectionParams; +static void emit_guest_memory_failure(MemoryFailureAction action, bool ar, + bool recursive) +{ + MemoryFailureFlags mff = {.action_required = ar, .recursive = recursive}; + + qapi_event_send_memory_failure(MEMORY_FAILURE_RECIPIENT_GUEST, action, + &mff); +} + static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) { MCEInjectionParams *params = data.host_ptr; X86CPU *cpu = X86_CPU(cs); CPUX86State *cenv = &cpu->env; uint64_t *banks = cenv->mce_banks + 4 * params->bank; + g_autofree char *msg = NULL; + bool need_reset = false; + bool recursive; + bool ar = !!(params->status & MCI_STATUS_AR); cpu_synchronize_state(cs); + recursive = !!(cenv->mcg_status & MCG_STATUS_MCIP); /* * If there is an MCE exception being processed, ignore this SRAO MCE * unless unconditional injection was requested. */ - if (!(params->flags & MCE_INJECT_UNCOND_AO) - && !(params->status & MCI_STATUS_AR) - && (cenv->mcg_status & MCG_STATUS_MCIP)) { + if (!(params->flags & MCE_INJECT_UNCOND_AO) && !ar && recursive) { + emit_guest_memory_failure(MEMORY_FAILURE_ACTION_IGNORE, ar, recursive); return; } @@ -894,16 +908,27 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) return; } - if ((cenv->mcg_status & MCG_STATUS_MCIP) || - !(cenv->cr[4] & CR4_MCE_MASK)) { - monitor_printf(params->mon, - "CPU %d: Previous MCE still in progress, raising" - " triple fault\n", - cs->cpu_index); - qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); + if (recursive) { + need_reset = true; + msg = g_strdup_printf("CPU %d: Previous MCE still in progress, " + "raising triple fault", cs->cpu_index); + } + + if (!(cenv->cr[4] & CR4_MCE_MASK)) { + need_reset = true; + msg = g_strdup_printf("CPU %d: MCE capability is not enabled, " + "raising triple fault", cs->cpu_index); + } + + if (need_reset) { + emit_guest_memory_failure(MEMORY_FAILURE_ACTION_RESET, ar, + recursive); + monitor_printf(params->mon, "%s", msg); + qemu_log_mask(CPU_LOG_RESET, "%s\n", msg); qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); return; } + if (banks[1] & MCI_STATUS_VAL) { params->status |= MCI_STATUS_OVER; } @@ -923,6 +948,8 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) } else { banks[1] |= MCI_STATUS_OVER; } + + emit_guest_memory_failure(MEMORY_FAILURE_ACTION_INJECT, ar, recursive); } void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, diff --git a/target/i386/kvm.c b/target/i386/kvm.c index f6dae4c..8b12387 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -13,6 +13,7 @@ */ #include "qemu/osdep.h" +#include "qapi/qapi-events-run-state.h" #include "qapi/error.h" #include <sys/ioctl.h> #include <sys/utsname.h> @@ -549,8 +550,17 @@ static void kvm_mce_inject(X86CPU *cpu, hwaddr paddr, int code) (MCM_ADDR_PHYS << 6) | 0xc, flags); } +static void emit_hypervisor_memory_failure(MemoryFailureAction action, bool ar) +{ + MemoryFailureFlags mff = {.action_required = ar, .recursive = false}; + + qapi_event_send_memory_failure(MEMORY_FAILURE_RECIPIENT_HYPERVISOR, action, + &mff); +} + static void hardware_memory_error(void *host_addr) { + emit_hypervisor_memory_failure(MEMORY_FAILURE_ACTION_FATAL, true); error_report("QEMU got Hardware memory error at addr %p", host_addr); exit(1); } @@ -605,7 +615,8 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) hardware_memory_error(addr); } - /* Hope we are lucky for AO MCE */ + /* Hope we are lucky for AO MCE, just notify a event */ + emit_hypervisor_memory_failure(MEMORY_FAILURE_ACTION_IGNORE, false); } static void kvm_reset_exception(CPUX86State *env) |