[SeaBIOS] [PATCH RFC] x86: use volatile asm for read/write{b, w, l} implementations
Vitaly Kuznetsov
vkuznets at redhat.com
Mon Jan 22 20:05:58 CET 2018
Vitaly Kuznetsov <vkuznets at redhat.com> writes:
> QEMU/KVM guests running nested on top of Hyper-V fail to boot with
> virtio-blk-pci disks, the debug log ends with
>
> Booting from Hard Disk...
> call32_smm 0x000edd01 e97a0
> handle_smi cmd=b5 smbase=0x000a0000
> vp notify fe007000 (2) -- 0x0
> vp read fe005000 (1) -> 0x0
> handle_smi cmd=b5 smbase=0x000a0000
> call32_smm done 0x000edd01 0
> Booting from 0000:7c00
> call32_smm 0x000edd01 e97a4
> handle_smi cmd=b5 smbase=0x000a0000
> vp notify fe007000 (2) -- 0x0
> In resume (status=0)
> In 32bit resume
> Attempting a hard reboot
> ...
>
> I bisected the breakage to the following commit:
>
> commit f46739b1a819750c63fb5849844d99cc2ab001e8
> Author: Kevin O'Connor <kevin at koconnor.net>
> Date: Tue Feb 2 22:34:27 2016 -0500
>
> virtio: Convert to new PCI BAR helper functions
>
> But the commit itself appears to be correct.
It took me a while to get back to this issue and I *hope* that I solved
the mystery: when we access 0xfe007000 for the second time EPT_MISCONFIG
is triggered but VM_EXIT_INSTRUCTION_LEN in VMCS is set to '1' (!!!)
regardless of the real length. So in kvm we do the following:
... if (... && !kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL))
return kvm_skip_emulated_instruction(vcpu);
and kvm_skip_emulated_instruction() does
rip = kvm_rip_read(vcpu);
rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN); <--- this is '1'
kvm_rip_write(vcpu, rip);
so we jump one byte forward and try to execute the new 'instruction'
which is actually just the tail of the old instruction as it is 3 bytes
long.
I think Hyper-V host is misbehaving when it gives us such VMCS for our
L2 guest. I'll check and complain.
--
Vitaly
More information about the SeaBIOS
mailing list