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 |
}
|