Revision 316378e4

b/monitor.c
2712 2712
    int broadcast = qdict_get_try_bool(qdict, "broadcast", 0);
2713 2713

  
2714 2714
    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
2715
        if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {
2716
            cpu_x86_inject_mce(cenv, bank, status, mcg_status, addr, misc,
2715
        if (cenv->cpu_index == cpu_index) {
2716
            cpu_x86_inject_mce(mon, cenv, bank, status, mcg_status, addr, misc,
2717 2717
                               broadcast);
2718 2718
            break;
2719 2719
        }
b/qemu-common.h
18 18
typedef struct QEMUBH QEMUBH;
19 19
typedef struct DeviceState DeviceState;
20 20

  
21
struct Monitor;
22
typedef struct Monitor Monitor;
23

  
21 24
/* we put basic includes here to avoid repeating them in device drivers */
22 25
#include <stdlib.h>
23 26
#include <stdio.h>
......
327 330
void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
328 331
                            size_t skip);
329 332

  
330
struct Monitor;
331
typedef struct Monitor Monitor;
332

  
333 333
/* Convert a byte between binary and BCD.  */
334 334
static inline uint8_t to_bcd(uint8_t val)
335 335
{
b/target-i386/cpu.h
987 987
void do_cpu_init(CPUState *env);
988 988
void do_cpu_sipi(CPUState *env);
989 989

  
990
void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,
991
                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
992
                        int broadcast);
990
void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
991
                        uint64_t status, uint64_t mcg_status, uint64_t addr,
992
                        uint64_t misc, int broadcast);
993 993

  
994 994
#endif /* CPU_I386_H */
b/target-i386/helper.c
30 30
#include "kvm_x86.h"
31 31
#ifndef CONFIG_USER_ONLY
32 32
#include "sysemu.h"
33
#include "monitor.h"
33 34
#endif
34 35

  
35 36
//#define DEBUG_MMU
......
1067 1068
}
1068 1069

  
1069 1070
static void
1070
qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
1071
qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status,
1071 1072
                    uint64_t mcg_status, uint64_t addr, uint64_t misc)
1072 1073
{
1073 1074
    uint64_t mcg_cap = cenv->mcg_cap;
1074
    uint64_t *banks = cenv->mce_banks;
1075

  
1076
    /*
1077
     * if MSR_MCG_CTL is not all 1s, the uncorrected error
1078
     * reporting is disabled
1079
     */
1080
    if ((status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) &&
1081
        cenv->mcg_ctl != ~(uint64_t)0) {
1082
        return;
1083
    }
1084
    banks += 4 * bank;
1085
    /*
1086
     * if MSR_MCi_CTL is not all 1s, the uncorrected error
1087
     * reporting is disabled for the bank
1088
     */
1089
    if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0) {
1090
        return;
1091
    }
1075
    uint64_t *banks = cenv->mce_banks + 4 * bank;
1076

  
1092 1077
    if (status & MCI_STATUS_UC) {
1078
        /*
1079
         * if MSR_MCG_CTL is not all 1s, the uncorrected error
1080
         * reporting is disabled
1081
         */
1082
        if ((mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
1083
            monitor_printf(mon,
1084
                           "CPU %d: Uncorrected error reporting disabled\n",
1085
                           cenv->cpu_index);
1086
            return;
1087
        }
1088

  
1089
        /*
1090
         * if MSR_MCi_CTL is not all 1s, the uncorrected error
1091
         * reporting is disabled for the bank
1092
         */
1093
        if (banks[0] != ~(uint64_t)0) {
1094
            monitor_printf(mon, "CPU %d: Uncorrected error reporting disabled "
1095
                           "for bank %d\n", cenv->cpu_index, bank);
1096
            return;
1097
        }
1098

  
1093 1099
        if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
1094 1100
            !(cenv->cr[4] & CR4_MCE_MASK)) {
1095
            fprintf(stderr, "injects mce exception while previous "
1096
                    "one is in progress!\n");
1101
            monitor_printf(mon, "CPU %d: Previous MCE still in progress, "
1102
                                "raising triple fault\n", cenv->cpu_index);
1097 1103
            qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1098 1104
            qemu_system_reset_request();
1099 1105
            return;
......
1119 1125
    }
1120 1126
}
1121 1127

  
1122
void cpu_x86_inject_mce(CPUState *cenv, int bank, uint64_t status,
1123
                        uint64_t mcg_status, uint64_t addr, uint64_t misc,
1124
                        int broadcast)
1128
void cpu_x86_inject_mce(Monitor *mon, CPUState *cenv, int bank,
1129
                        uint64_t status, uint64_t mcg_status, uint64_t addr,
1130
                        uint64_t misc, int broadcast)
1125 1131
{
1126 1132
    unsigned bank_num = cenv->mcg_cap & 0xff;
1127 1133
    CPUState *env;
1128 1134
    int flag = 0;
1129 1135

  
1130
    if (bank >= bank_num || !(status & MCI_STATUS_VAL)) {
1136
    if (!cenv->mcg_cap) {
1137
        monitor_printf(mon, "MCE injection not supported\n");
1131 1138
        return;
1132 1139
    }
1133

  
1134
    if (broadcast) {
1135
        if (!cpu_x86_support_mca_broadcast(cenv)) {
1136
            fprintf(stderr, "Current CPU does not support broadcast\n");
1137
            return;
1138
        }
1140
    if (bank >= bank_num) {
1141
        monitor_printf(mon, "Invalid MCE bank number\n");
1142
        return;
1143
    }
1144
    if (!(status & MCI_STATUS_VAL)) {
1145
        monitor_printf(mon, "Invalid MCE status code\n");
1146
        return;
1147
    }
1148
    if (broadcast && !cpu_x86_support_mca_broadcast(cenv)) {
1149
        monitor_printf(mon, "Guest CPU does not support MCA broadcast\n");
1150
        return;
1139 1151
    }
1140 1152

  
1141 1153
    if (kvm_enabled()) {
......
1145 1157

  
1146 1158
        kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
1147 1159
    } else {
1148
        qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
1160
        qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc);
1149 1161
        if (broadcast) {
1150 1162
            for (env = first_cpu; env != NULL; env = env->next_cpu) {
1151 1163
                if (cenv == env) {
1152 1164
                    continue;
1153 1165
                }
1154
                qemu_inject_x86_mce(env, 1, MCI_STATUS_VAL | MCI_STATUS_UC,
1166
                qemu_inject_x86_mce(mon, env, 1,
1167
                                    MCI_STATUS_VAL | MCI_STATUS_UC,
1155 1168
                                    MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0);
1156 1169
            }
1157 1170
        }

Also available in: Unified diff