In QEMU-KVM, physical address != RAM address. While MCE simulation needs physical address instead of RAM address. So kvm_physical_memory_addr_from_ram() is implemented to do the conversion, and it is invoked before being filled in the IA32_MCi_ADDR MSR. Reported-by: Dean Nelson <dnelson@xxxxxxxxxx> Signed-off-by: Huang Ying <ying.huang@xxxxxxxxx> --- kvm-all.c | 18 ++++++++++++++++++ kvm.h | 3 +++ qemu-kvm.c | 13 ++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -1137,12 +1137,15 @@ static void sigbus_handler(int n, struct if (first_cpu->mcg_cap && siginfo->ssi_addr && siginfo->ssi_code == BUS_MCEERR_AO) { uint64_t status; + void *vaddr; + ram_addr_t ram_addr; unsigned long paddr; CPUState *cenv; /* Hope we are lucky for AO MCE */ - if (do_qemu_ram_addr_from_host((void *)(intptr_t)siginfo->ssi_addr, - &paddr)) { + vaddr = (void *)(intptr_t)siginfo->ssi_addr; + if (do_qemu_ram_addr_from_host(vaddr, &ram_addr) || + !kvm_physical_memory_addr_from_ram(kvm_state, ram_addr, &paddr)) { fprintf(stderr, "Hardware memory error for memory used by " "QEMU itself instead of guest system!: %llx\n", (unsigned long long)siginfo->ssi_addr); @@ -1316,6 +1319,8 @@ static void kvm_on_sigbus(CPUState *env, struct kvm_x86_mce mce = { .bank = 9, }; + void *vaddr; + ram_addr_t ram_addr; unsigned long paddr; int r; @@ -1347,7 +1352,9 @@ static void kvm_on_sigbus(CPUState *env, mce.misc = (MCM_ADDR_PHYS << 6) | 0xc; mce.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV; } - if (do_qemu_ram_addr_from_host((void *)siginfo->si_addr, &paddr)) { + vaddr = (void *)siginfo->si_addr; + if (do_qemu_ram_addr_from_host(vaddr, &ram_addr) || + !kvm_physical_memory_addr_from_ram(kvm_state, ram_addr, &paddr)) { fprintf(stderr, "Hardware memory error for memory used by " "QEMU itself instaed of guest system!\n"); /* Hope we are lucky for AO MCE */ --- a/kvm-all.c +++ b/kvm-all.c @@ -141,6 +141,24 @@ static KVMSlot *kvm_lookup_overlapping_s return found; } +int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr, + target_phys_addr_t *phys_addr) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(s->slots); i++) { + KVMSlot *mem = &s->slots[i]; + + if (ram_addr >= mem->phys_offset && + ram_addr < mem->phys_offset + mem->memory_size) { + *phys_addr = mem->start_addr + (ram_addr - mem->phys_offset); + return 1; + } + } + + return 0; +} + static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot) { struct kvm_userspace_memory_region mem; --- a/kvm.h +++ b/kvm.h @@ -195,4 +195,7 @@ int kvm_set_irqfd(int gsi, int fd, bool #endif int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign); + +int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr, + target_phys_addr_t *phys_addr); #endif -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html