[PATCH 07/35] x86: Optionally avoid injecting AO MCEs while others are pending

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jan Kiszka <jan.kiszka@xxxxxxxxxxx>

Allow to tell cpu_x86_inject_mce that it should ignore Action Optional
MCE events when the target VCPU is still processing another one. This
will be used by KVM soon.

Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx>
CC: Huang Ying <ying.huang@xxxxxxxxx>
CC: Hidetoshi Seto <seto.hidetoshi@xxxxxxxxxxxxxx>
CC: Jin Dongming <jin.dongming@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Marcelo Tosatti <mtosatti@xxxxxxxxxx>
---
 monitor.c            |    7 +++++--
 target-i386/cpu.h    |    5 ++++-
 target-i386/helper.c |   26 +++++++++++++++++++-------
 3 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/monitor.c b/monitor.c
index 662df7c..ae20927 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2709,12 +2709,15 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
     uint64_t mcg_status = qdict_get_int(qdict, "mcg_status");
     uint64_t addr = qdict_get_int(qdict, "addr");
     uint64_t misc = qdict_get_int(qdict, "misc");
-    int broadcast = qdict_get_try_bool(qdict, "broadcast", 0);
+    int flags = MCE_INJECT_UNCOND_AO;
 
+    if (qdict_get_try_bool(qdict, "broadcast", 0)) {
+        flags |= MCE_INJECT_BROADCAST;
+    }
     for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
         if (cenv->cpu_index == cpu_index) {
             cpu_x86_inject_mce(mon, cenv, bank, status, mcg_status, addr, misc,
-                               broadcast);
+                               flags);
             break;
         }
     }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 486af1d..d0eae75 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -987,8 +987,11 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 void do_cpu_init(CPUState *env);
 void do_cpu_sipi(CPUState *env);
 
+#define MCE_INJECT_BROADCAST    1
+#define MCE_INJECT_UNCOND_AO    2
+
 void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
-                        uint64_t misc, int broadcast);
+                        uint64_t misc, int flags);
 
 #endif /* CPU_I386_H */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 462d332..e3ef40c 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1069,11 +1069,20 @@ static void breakpoint_handler(CPUState *env)
 
 static void
 qemu_inject_x86_mce(Monitor *mon, 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 flags)
 {
     uint64_t mcg_cap = cenv->mcg_cap;
     uint64_t *banks = cenv->mce_banks + 4 * bank;
 
+    /*
+     * If there is an MCE exception being processed, ignore this SRAO MCE
+     * unless unconditional injection was requested.
+     */
+    if (!(flags & MCE_INJECT_UNCOND_AO) && !(status & MCI_STATUS_AR)
+        && (cenv->mcg_status & MCG_STATUS_MCIP)) {
+        return;
+    }
     if (status & MCI_STATUS_UC) {
         /*
          * if MSR_MCG_CTL is not all 1s, the uncorrected error
@@ -1127,7 +1136,7 @@ qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status,
 
 void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
                         uint64_t status, uint64_t mcg_status, uint64_t addr,
-                        uint64_t misc, int broadcast)
+                        uint64_t misc, int flags)
 {
     unsigned bank_num = cenv->mcg_cap & 0xff;
     CPUState *env;
@@ -1145,27 +1154,30 @@ void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
         monitor_printf(mon, "Invalid MCE status code\n");
         return;
     }
-    if (broadcast && !cpu_x86_support_mca_broadcast(cenv)) {
+    if ((flags & MCE_INJECT_BROADCAST)
+        && !cpu_x86_support_mca_broadcast(cenv)) {
         monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
         return;
     }
 
     if (kvm_enabled()) {
-        if (broadcast) {
+        if (flags & MCE_INJECT_BROADCAST) {
             flag |= MCE_BROADCAST;
         }
 
         kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
     } else {
-        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc);
-        if (broadcast) {
+        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc,
+                            flags);
+        if (flags & MCE_INJECT_BROADCAST) {
             for (env = first_cpu; env != NULL; env = env->next_cpu) {
                 if (cenv == env) {
                     continue;
                 }
                 qemu_inject_x86_mce(mon, env, 1,
                                     MCI_STATUS_VAL | MCI_STATUS_UC,
-                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0);
+                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0,
+                                    flags);
             }
         }
     }
-- 
1.7.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux