aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/i386/helper.c47
-rw-r--r--target/i386/kvm.c13
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)