• Avi Kivity's avatar
    KVM: MMU: Force cr3 reload with two dimensional paging on mov cr3 emulation · e676505a
    Avi Kivity authored
    Currently the MMU's ->new_cr3() callback does nothing when guest paging
    is disabled or when two-dimentional paging (e.g. EPT on Intel) is active.
    This means that an emulated write to cr3 can be lost; kvm_set_cr3() will
    write vcpu-arch.cr3, but the GUEST_CR3 field in the VMCS will retain its
    old value and this is what the guest sees.
    
    This bug did not have any effect until now because:
    - with unrestricted guest, or with svm, we never emulate a mov cr3 instruction
    - without unrestricted guest, and with paging enabled, we also never emulate a
      mov cr3 instruction
    - without unrestricted guest, but with paging disabled, the guest's cr3 is
      ignored until the guest enables paging; at this point the value from arch.cr3
      is loaded correctly my the mov cr0 instruction which turns on paging
    
    However, the patchset that enables big real mode causes us to emulate mov cr3
    instructions in protected mode sometimes (when guest state is not virtualizable
    by vmx); this mov cr3 is effectively ignored and will crash the guest.
    
    The fix is to make nonpaging_new_cr3() call mmu_free_roots() to force a cr3
    reload.  This is awkward because now all the new_cr3 callbacks to the same
    thing, and because mmu_free_roots() is somewhat of an overkill; but fixing
    that is more complicated and will be done after this minimal fix.
    
    Observed in the Window XP 32-bit installer while bringing up secondary vcpus.
    Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
    e676505a
mmu.c 97.4 KB