Revision d5bfda33 target-i386/helper.c
b/target-i386/helper.c | ||
---|---|---|
1067 | 1067 |
prev_debug_excp_handler(env); |
1068 | 1068 |
} |
1069 | 1069 |
|
1070 |
static void |
|
1071 |
qemu_inject_x86_mce(Monitor *mon, CPUState *cenv, int bank, uint64_t status, |
|
1072 |
uint64_t mcg_status, uint64_t addr, uint64_t misc, |
|
1073 |
int flags) |
|
1070 |
typedef struct MCEInjectionParams { |
|
1071 |
Monitor *mon; |
|
1072 |
CPUState *env; |
|
1073 |
int bank; |
|
1074 |
uint64_t status; |
|
1075 |
uint64_t mcg_status; |
|
1076 |
uint64_t addr; |
|
1077 |
uint64_t misc; |
|
1078 |
int flags; |
|
1079 |
} MCEInjectionParams; |
|
1080 |
|
|
1081 |
static void do_inject_x86_mce(void *data) |
|
1074 | 1082 |
{ |
1075 |
uint64_t mcg_cap = cenv->mcg_cap; |
|
1076 |
uint64_t *banks = cenv->mce_banks + 4 * bank; |
|
1083 |
MCEInjectionParams *params = data; |
|
1084 |
CPUState *cenv = params->env; |
|
1085 |
uint64_t *banks = cenv->mce_banks + 4 * params->bank; |
|
1086 |
|
|
1087 |
cpu_synchronize_state(cenv); |
|
1077 | 1088 |
|
1078 | 1089 |
/* |
1079 | 1090 |
* If there is an MCE exception being processed, ignore this SRAO MCE |
1080 | 1091 |
* unless unconditional injection was requested. |
1081 | 1092 |
*/ |
1082 |
if (!(flags & MCE_INJECT_UNCOND_AO) && !(status & MCI_STATUS_AR) |
|
1093 |
if (!(params->flags & MCE_INJECT_UNCOND_AO) |
|
1094 |
&& !(params->status & MCI_STATUS_AR) |
|
1083 | 1095 |
&& (cenv->mcg_status & MCG_STATUS_MCIP)) { |
1084 | 1096 |
return; |
1085 | 1097 |
} |
1086 |
if (status & MCI_STATUS_UC) { |
|
1098 |
|
|
1099 |
if (params->status & MCI_STATUS_UC) { |
|
1087 | 1100 |
/* |
1088 | 1101 |
* if MSR_MCG_CTL is not all 1s, the uncorrected error |
1089 | 1102 |
* reporting is disabled |
1090 | 1103 |
*/ |
1091 |
if ((mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) { |
|
1092 |
monitor_printf(mon, |
|
1104 |
if ((cenv->mcg_cap & MCG_CTL_P) && cenv->mcg_ctl != ~(uint64_t)0) {
|
|
1105 |
monitor_printf(params->mon,
|
|
1093 | 1106 |
"CPU %d: Uncorrected error reporting disabled\n", |
1094 | 1107 |
cenv->cpu_index); |
1095 | 1108 |
return; |
... | ... | |
1100 | 1113 |
* reporting is disabled for the bank |
1101 | 1114 |
*/ |
1102 | 1115 |
if (banks[0] != ~(uint64_t)0) { |
1103 |
monitor_printf(mon, "CPU %d: Uncorrected error reporting disabled " |
|
1104 |
"for bank %d\n", cenv->cpu_index, bank); |
|
1116 |
monitor_printf(params->mon, |
|
1117 |
"CPU %d: Uncorrected error reporting disabled for" |
|
1118 |
" bank %d\n", |
|
1119 |
cenv->cpu_index, params->bank); |
|
1105 | 1120 |
return; |
1106 | 1121 |
} |
1107 | 1122 |
|
1108 | 1123 |
if ((cenv->mcg_status & MCG_STATUS_MCIP) || |
1109 | 1124 |
!(cenv->cr[4] & CR4_MCE_MASK)) { |
1110 |
monitor_printf(mon, "CPU %d: Previous MCE still in progress, " |
|
1111 |
"raising triple fault\n", cenv->cpu_index); |
|
1125 |
monitor_printf(params->mon, |
|
1126 |
"CPU %d: Previous MCE still in progress, raising" |
|
1127 |
" triple fault\n", |
|
1128 |
cenv->cpu_index); |
|
1112 | 1129 |
qemu_log_mask(CPU_LOG_RESET, "Triple fault\n"); |
1113 | 1130 |
qemu_system_reset_request(); |
1114 | 1131 |
return; |
1115 | 1132 |
} |
1116 | 1133 |
if (banks[1] & MCI_STATUS_VAL) { |
1117 |
status |= MCI_STATUS_OVER; |
|
1134 |
params->status |= MCI_STATUS_OVER;
|
|
1118 | 1135 |
} |
1119 |
banks[2] = addr; |
|
1120 |
banks[3] = misc; |
|
1121 |
cenv->mcg_status = mcg_status; |
|
1122 |
banks[1] = status; |
|
1136 |
banks[2] = params->addr;
|
|
1137 |
banks[3] = params->misc;
|
|
1138 |
cenv->mcg_status = params->mcg_status;
|
|
1139 |
banks[1] = params->status;
|
|
1123 | 1140 |
cpu_interrupt(cenv, CPU_INTERRUPT_MCE); |
1124 | 1141 |
} else if (!(banks[1] & MCI_STATUS_VAL) |
1125 | 1142 |
|| !(banks[1] & MCI_STATUS_UC)) { |
1126 | 1143 |
if (banks[1] & MCI_STATUS_VAL) { |
1127 |
status |= MCI_STATUS_OVER; |
|
1144 |
params->status |= MCI_STATUS_OVER;
|
|
1128 | 1145 |
} |
1129 |
banks[2] = addr; |
|
1130 |
banks[3] = misc; |
|
1131 |
banks[1] = status; |
|
1146 |
banks[2] = params->addr;
|
|
1147 |
banks[3] = params->misc;
|
|
1148 |
banks[1] = params->status;
|
|
1132 | 1149 |
} else { |
1133 | 1150 |
banks[1] |= MCI_STATUS_OVER; |
1134 | 1151 |
} |
... | ... | |
1138 | 1155 |
uint64_t status, uint64_t mcg_status, uint64_t addr, |
1139 | 1156 |
uint64_t misc, int flags) |
1140 | 1157 |
{ |
1158 |
MCEInjectionParams params = { |
|
1159 |
.mon = mon, |
|
1160 |
.env = cenv, |
|
1161 |
.bank = bank, |
|
1162 |
.status = status, |
|
1163 |
.mcg_status = mcg_status, |
|
1164 |
.addr = addr, |
|
1165 |
.misc = misc, |
|
1166 |
.flags = flags, |
|
1167 |
}; |
|
1141 | 1168 |
unsigned bank_num = cenv->mcg_cap & 0xff; |
1142 | 1169 |
CPUState *env; |
1143 | 1170 |
int flag = 0; |
... | ... | |
1167 | 1194 |
|
1168 | 1195 |
kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag); |
1169 | 1196 |
} else { |
1170 |
qemu_inject_x86_mce(mon, cenv, bank, status, mcg_status, addr, misc, |
|
1171 |
flags); |
|
1197 |
run_on_cpu(cenv, do_inject_x86_mce, ¶ms); |
|
1172 | 1198 |
if (flags & MCE_INJECT_BROADCAST) { |
1199 |
params.bank = 1; |
|
1200 |
params.status = MCI_STATUS_VAL | MCI_STATUS_UC; |
|
1201 |
params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV; |
|
1202 |
params.addr = 0; |
|
1203 |
params.misc = 0; |
|
1173 | 1204 |
for (env = first_cpu; env != NULL; env = env->next_cpu) { |
1174 | 1205 |
if (cenv == env) { |
1175 | 1206 |
continue; |
1176 | 1207 |
} |
1177 |
qemu_inject_x86_mce(mon, env, 1, |
|
1178 |
MCI_STATUS_VAL | MCI_STATUS_UC, |
|
1179 |
MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0, |
|
1180 |
flags); |
|
1208 |
params.env = env; |
|
1209 |
run_on_cpu(cenv, do_inject_x86_mce, ¶ms); |
|
1181 | 1210 |
} |
1182 | 1211 |
} |
1183 | 1212 |
} |
Also available in: Unified diff