aboutsummaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/helper.c20
-rw-r--r--target-i386/kvm.c16
-rw-r--r--target-i386/kvm_x86.h5
3 files changed, 34 insertions, 7 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2c94130a15..2cfb4a42a7 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1069,18 +1069,34 @@ static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
}
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
- uint64_t mcg_status, uint64_t addr, uint64_t misc)
+ uint64_t mcg_status, uint64_t addr, uint64_t misc,
+ int broadcast)
{
unsigned bank_num = cenv->mcg_cap & 0xff;
+ CPUState *env;
+ int flag = 0;
if (bank >= bank_num || !(status & MCI_STATUS_VAL)) {
return;
}
if (kvm_enabled()) {
- kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, 0);
+ if (broadcast) {
+ flag |= MCE_BROADCAST;
+ }
+
+ kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
} else {
qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
+ if (broadcast) {
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ if (cenv == env) {
+ continue;
+ }
+
+ qemu_inject_x86_mce(env, 1, 0xa000000000000000, 0, 0, 0);
+ }
+ }
}
}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 4004de76dd..8b868ad40a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -264,11 +264,13 @@ static void kvm_do_inject_x86_mce(void *_data)
}
}
}
+
+static void kvm_mce_broadcast_rest(CPUState *env);
#endif
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc,
- int abort_on_error)
+ int flag)
{
#ifdef KVM_CAP_MCE
struct kvm_x86_mce mce = {
@@ -288,10 +290,15 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
return;
}
+ if (flag & MCE_BROADCAST) {
+ kvm_mce_broadcast_rest(cenv);
+ }
+
run_on_cpu(cenv, kvm_do_inject_x86_mce, &data);
#else
- if (abort_on_error)
+ if (flag & ABORT_ON_ERROR) {
abort();
+ }
#endif
}
@@ -1716,7 +1723,8 @@ static void kvm_mce_broadcast_rest(CPUState *env)
continue;
}
kvm_inject_x86_mce(cenv, 1, MCI_STATUS_VAL | MCI_STATUS_UC,
- MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0, 1);
+ MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0,
+ ABORT_ON_ERROR);
}
}
}
@@ -1816,7 +1824,7 @@ int kvm_on_sigbus(int code, void *addr)
| 0xc0;
kvm_inject_x86_mce(first_cpu, 9, status,
MCG_STATUS_MCIP | MCG_STATUS_RIPV, paddr,
- (MCM_ADDR_PHYS << 6) | 0xc, 1);
+ (MCM_ADDR_PHYS << 6) | 0xc, ABORT_ON_ERROR);
kvm_mce_broadcast_rest(first_cpu);
} else
#endif
diff --git a/target-i386/kvm_x86.h b/target-i386/kvm_x86.h
index 04932cf4c8..9d7b584267 100644
--- a/target-i386/kvm_x86.h
+++ b/target-i386/kvm_x86.h
@@ -15,8 +15,11 @@
#ifndef __KVM_X86_H__
#define __KVM_X86_H__
+#define ABORT_ON_ERROR 0x01
+#define MCE_BROADCAST 0x02
+
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc,
- int abort_on_error);
+ int flag);
#endif