mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 03:59:52 +00:00
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:
parent
a7ada1510c
commit
419fb20a8e
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user