Revision e7701825 target-i386/kvm.c
b/target-i386/kvm.c | ||
---|---|---|
27 | 27 |
#include "hw/pc.h" |
28 | 28 |
#include "hw/apic.h" |
29 | 29 |
#include "ioport.h" |
30 |
#include "kvm_x86.h" |
|
30 | 31 |
|
31 | 32 |
#ifdef CONFIG_KVM_PARA |
32 | 33 |
#include <linux/kvm_para.h> |
... | ... | |
167 | 168 |
} |
168 | 169 |
#endif |
169 | 170 |
|
171 |
#ifdef KVM_CAP_MCE |
|
172 |
static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap, |
|
173 |
int *max_banks) |
|
174 |
{ |
|
175 |
int r; |
|
176 |
|
|
177 |
r = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_MCE); |
|
178 |
if (r > 0) { |
|
179 |
*max_banks = r; |
|
180 |
return kvm_ioctl(s, KVM_X86_GET_MCE_CAP_SUPPORTED, mce_cap); |
|
181 |
} |
|
182 |
return -ENOSYS; |
|
183 |
} |
|
184 |
|
|
185 |
static int kvm_setup_mce(CPUState *env, uint64_t *mcg_cap) |
|
186 |
{ |
|
187 |
return kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, mcg_cap); |
|
188 |
} |
|
189 |
|
|
190 |
static int kvm_set_mce(CPUState *env, struct kvm_x86_mce *m) |
|
191 |
{ |
|
192 |
return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, m); |
|
193 |
} |
|
194 |
|
|
195 |
struct kvm_x86_mce_data |
|
196 |
{ |
|
197 |
CPUState *env; |
|
198 |
struct kvm_x86_mce *mce; |
|
199 |
}; |
|
200 |
|
|
201 |
static void kvm_do_inject_x86_mce(void *_data) |
|
202 |
{ |
|
203 |
struct kvm_x86_mce_data *data = _data; |
|
204 |
int r; |
|
205 |
|
|
206 |
r = kvm_set_mce(data->env, data->mce); |
|
207 |
if (r < 0) |
|
208 |
perror("kvm_set_mce FAILED"); |
|
209 |
} |
|
210 |
#endif |
|
211 |
|
|
212 |
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, |
|
213 |
uint64_t mcg_status, uint64_t addr, uint64_t misc) |
|
214 |
{ |
|
215 |
#ifdef KVM_CAP_MCE |
|
216 |
struct kvm_x86_mce mce = { |
|
217 |
.bank = bank, |
|
218 |
.status = status, |
|
219 |
.mcg_status = mcg_status, |
|
220 |
.addr = addr, |
|
221 |
.misc = misc, |
|
222 |
}; |
|
223 |
struct kvm_x86_mce_data data = { |
|
224 |
.env = cenv, |
|
225 |
.mce = &mce, |
|
226 |
}; |
|
227 |
|
|
228 |
run_on_cpu(cenv, kvm_do_inject_x86_mce, &data); |
|
229 |
#endif |
|
230 |
} |
|
231 |
|
|
170 | 232 |
int kvm_arch_init_vcpu(CPUState *env) |
171 | 233 |
{ |
172 | 234 |
struct { |
... | ... | |
277 | 339 |
|
278 | 340 |
cpuid_data.cpuid.nent = cpuid_i; |
279 | 341 |
|
342 |
#ifdef KVM_CAP_MCE |
|
343 |
if (((env->cpuid_version >> 8)&0xF) >= 6 |
|
344 |
&& (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA) |
|
345 |
&& kvm_check_extension(env->kvm_state, KVM_CAP_MCE) > 0) { |
|
346 |
uint64_t mcg_cap; |
|
347 |
int banks; |
|
348 |
|
|
349 |
if (kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks)) |
|
350 |
perror("kvm_get_mce_cap_supported FAILED"); |
|
351 |
else { |
|
352 |
if (banks > MCE_BANKS_DEF) |
|
353 |
banks = MCE_BANKS_DEF; |
|
354 |
mcg_cap &= MCE_CAP_DEF; |
|
355 |
mcg_cap |= banks; |
|
356 |
if (kvm_setup_mce(env, &mcg_cap)) |
|
357 |
perror("kvm_setup_mce FAILED"); |
|
358 |
else |
|
359 |
env->mcg_cap = mcg_cap; |
|
360 |
} |
|
361 |
} |
|
362 |
#endif |
|
363 |
|
|
280 | 364 |
return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); |
281 | 365 |
} |
282 | 366 |
|
Also available in: Unified diff