[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