sim-card
/
qemu
Archived
10
0
Fork 0

kvm: x86: Move MCE functions together

Pure function suffling to avoid multiple #ifdef KVM_CAP_MCE sections,
no functional changes. While at it, annotate some #ifdef sections.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
CC: Huang Ying <ying.huang@intel.com>
CC: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
CC: Jin Dongming <jin.dongming@np.css.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
Jan Kiszka 2011-03-02 08:56:12 +01:00 committed by Marcelo Tosatti
parent a7ada1510c
commit 419fb20a8e
1 changed files with 171 additions and 175 deletions

View File

@ -172,7 +172,7 @@ static int get_para_features(CPUState *env)
#endif
return features;
}
#endif
#endif /* CONFIG_KVM_PARA */
#ifdef KVM_CAP_MCE
static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
@ -273,8 +273,174 @@ static void kvm_inject_x86_mce_on(CPUState *env, struct kvm_x86_mce *mce,
run_on_cpu(env, kvm_do_inject_x86_mce, &data);
}
static void kvm_mce_broadcast_rest(CPUState *env);
#endif
static void kvm_mce_broadcast_rest(CPUState *env)
{
struct kvm_x86_mce mce = {
.bank = 1,
.status = MCI_STATUS_VAL | MCI_STATUS_UC,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
.addr = 0,
.misc = 0,
};
CPUState *cenv;
/* Broadcast MCA signal for processor version 06H_EH and above */
if (cpu_x86_support_mca_broadcast(env)) {
for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
if (cenv == env) {
continue;
}
kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
}
}
}
static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
{
struct kvm_x86_mce mce = {
.bank = 9,
.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
| MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
| MCI_STATUS_AR | 0x134,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
.addr = paddr,
.misc = (MCM_ADDR_PHYS << 6) | 0xc,
};
int r;
r = kvm_set_mce(env, &mce);
if (r < 0) {
fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
abort();
}
kvm_mce_broadcast_rest(env);
}
static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
{
struct kvm_x86_mce mce = {
.bank = 9,
.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
| MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
| 0xc0,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
.addr = paddr,
.misc = (MCM_ADDR_PHYS << 6) | 0xc,
};
int r;
r = kvm_set_mce(env, &mce);
if (r < 0) {
fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
abort();
}
kvm_mce_broadcast_rest(env);
}
static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
{
struct kvm_x86_mce mce = {
.bank = 9,
.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
| MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
| 0xc0,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
.addr = paddr,
.misc = (MCM_ADDR_PHYS << 6) | 0xc,
};
kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
kvm_mce_broadcast_rest(env);
}
#endif /* KVM_CAP_MCE */
static void hardware_memory_error(void)
{
fprintf(stderr, "Hardware memory error!\n");
exit(1);
}
int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
{
#ifdef KVM_CAP_MCE
void *vaddr;
ram_addr_t ram_addr;
target_phys_addr_t paddr;
if ((env->mcg_cap & MCG_SER_P) && addr
&& (code == BUS_MCEERR_AR
|| code == BUS_MCEERR_AO)) {
vaddr = (void *)addr;
if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
!kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
fprintf(stderr, "Hardware memory error for memory used by "
"QEMU itself instead of guest system!\n");
/* Hope we are lucky for AO MCE */
if (code == BUS_MCEERR_AO) {
return 0;
} else {
hardware_memory_error();
}
}
if (code == BUS_MCEERR_AR) {
/* Fake an Intel architectural Data Load SRAR UCR */
kvm_mce_inj_srar_dataload(env, paddr);
} else {
/*
* If there is an MCE excpetion being processed, ignore
* this SRAO MCE
*/
if (!kvm_mce_in_progress(env)) {
/* Fake an Intel architectural Memory scrubbing UCR */
kvm_mce_inj_srao_memscrub(env, paddr);
}
}
} else
#endif /* KVM_CAP_MCE */
{
if (code == BUS_MCEERR_AO) {
return 0;
} else if (code == BUS_MCEERR_AR) {
hardware_memory_error();
} else {
return 1;
}
}
return 0;
}
int kvm_arch_on_sigbus(int code, void *addr)
{
#ifdef KVM_CAP_MCE
if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
void *vaddr;
ram_addr_t ram_addr;
target_phys_addr_t paddr;
/* Hope we are lucky for AO MCE */
vaddr = addr;
if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
!kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr,
&paddr)) {
fprintf(stderr, "Hardware memory error for memory used by "
"QEMU itself instead of guest system!: %p\n", addr);
return 0;
}
kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
} else
#endif /* KVM_CAP_MCE */
{
if (code == BUS_MCEERR_AO) {
return 0;
} else if (code == BUS_MCEERR_AR) {
hardware_memory_error();
} else {
return 1;
}
}
return 0;
}
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc,
@ -294,11 +460,11 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
}
kvm_inject_x86_mce_on(cenv, &mce, flag);
#else
#else /* !KVM_CAP_MCE*/
if (flag & ABORT_ON_ERROR) {
abort();
}
#endif
#endif /* !KVM_CAP_MCE*/
}
static void cpu_update_state(void *opaque, int running, int reason)
@ -1783,173 +1949,3 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env)
return !(env->cr[0] & CR0_PE_MASK) ||
((env->segs[R_CS].selector & 3) != 3);
}
static void hardware_memory_error(void)
{
fprintf(stderr, "Hardware memory error!\n");
exit(1);
}
#ifdef KVM_CAP_MCE
static void kvm_mce_broadcast_rest(CPUState *env)
{
struct kvm_x86_mce mce = {
.bank = 1,
.status = MCI_STATUS_VAL | MCI_STATUS_UC,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
.addr = 0,
.misc = 0,
};
CPUState *cenv;
/* Broadcast MCA signal for processor version 06H_EH and above */
if (cpu_x86_support_mca_broadcast(env)) {
for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
if (cenv == env) {
continue;
}
kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
}
}
}
static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
{
struct kvm_x86_mce mce = {
.bank = 9,
.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
| MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
| MCI_STATUS_AR | 0x134,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
.addr = paddr,
.misc = (MCM_ADDR_PHYS << 6) | 0xc,
};
int r;
r = kvm_set_mce(env, &mce);
if (r < 0) {
fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
abort();
}
kvm_mce_broadcast_rest(env);
}
static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
{
struct kvm_x86_mce mce = {
.bank = 9,
.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
| MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
| 0xc0,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
.addr = paddr,
.misc = (MCM_ADDR_PHYS << 6) | 0xc,
};
int r;
r = kvm_set_mce(env, &mce);
if (r < 0) {
fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
abort();
}
kvm_mce_broadcast_rest(env);
}
static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
{
struct kvm_x86_mce mce = {
.bank = 9,
.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
| MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
| 0xc0,
.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
.addr = paddr,
.misc = (MCM_ADDR_PHYS << 6) | 0xc,
};
kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
kvm_mce_broadcast_rest(env);
}
#endif
int kvm_arch_on_sigbus_vcpu(CPUState *env, int code, void *addr)
{
#if defined(KVM_CAP_MCE)
void *vaddr;
ram_addr_t ram_addr;
target_phys_addr_t paddr;
if ((env->mcg_cap & MCG_SER_P) && addr
&& (code == BUS_MCEERR_AR
|| code == BUS_MCEERR_AO)) {
vaddr = (void *)addr;
if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
!kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
fprintf(stderr, "Hardware memory error for memory used by "
"QEMU itself instead of guest system!\n");
/* Hope we are lucky for AO MCE */
if (code == BUS_MCEERR_AO) {
return 0;
} else {
hardware_memory_error();
}
}
if (code == BUS_MCEERR_AR) {
/* Fake an Intel architectural Data Load SRAR UCR */
kvm_mce_inj_srar_dataload(env, paddr);
} else {
/*
* If there is an MCE excpetion being processed, ignore
* this SRAO MCE
*/
if (!kvm_mce_in_progress(env)) {
/* Fake an Intel architectural Memory scrubbing UCR */
kvm_mce_inj_srao_memscrub(env, paddr);
}
}
} else
#endif
{
if (code == BUS_MCEERR_AO) {
return 0;
} else if (code == BUS_MCEERR_AR) {
hardware_memory_error();
} else {
return 1;
}
}
return 0;
}
int kvm_arch_on_sigbus(int code, void *addr)
{
#if defined(KVM_CAP_MCE)
if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
void *vaddr;
ram_addr_t ram_addr;
target_phys_addr_t paddr;
/* Hope we are lucky for AO MCE */
vaddr = addr;
if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
!kvm_physical_memory_addr_from_ram(first_cpu->kvm_state, ram_addr, &paddr)) {
fprintf(stderr, "Hardware memory error for memory used by "
"QEMU itself instead of guest system!: %p\n", addr);
return 0;
}
kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
} else
#endif
{
if (code == BUS_MCEERR_AO) {
return 0;
} else if (code == BUS_MCEERR_AR) {
hardware_memory_error();
} else {
return 1;
}
}
return 0;
}