• Sean Christopherson's avatar
    KVM: x86/mmu: Differentiate between nr zapped and list unstable · 83cdb568
    Sean Christopherson authored
    The return value of kvm_mmu_prepare_zap_page() has evolved to become
    overloaded to convey two separate pieces of information.  1) was at
    least one page zapped and 2) has the list of MMU pages become unstable.
    
    In it's original incarnation (as kvm_mmu_zap_page()), there was no
    return value at all.  Commit 07385413 ("KVM: MMU: awareness of new
    kvm_mmu_zap_page behaviour") added a return value in preparation for
    commit 4731d4c7 ("KVM: MMU: out of sync shadow core").  Although
    the return value was of type 'int', it was actually used as a boolean
    to indicate whether or not active_mmu_pages may have become unstable due
    to zapping children.  Walking a list with list_for_each_entry_safe()
    only protects against deleting/moving the current entry, i.e. zapping a
    child page would break iteration due to modifying any number of entries.
    
    Later, commit 60c8aec6 ("KVM: MMU: use page array in unsync walk")
    modified mmu_zap_unsync_children() to return an approximation of the
    number of children zapped.  This was not intentional, it was simply a
    side effect of how the code was written.
    
    The unintented side affect was then morphed into an actual feature by
    commit 77662e00 ("KVM: MMU: fix kvm_mmu_zap_page() and its calling
    path"), which modified kvm_mmu_change_mmu_pages() to use the number of
    zapped pages when determining the number of MMU pages in use by the VM.
    
    Finally, commit 54a4f023 ("KVM: MMU: make kvm_mmu_zap_page() return
    the number of pages it actually freed") added the initial page to the
    return value to make its behavior more consistent with what most users
    would expect.  Incorporating the initial parent page in the return value
    of kvm_mmu_zap_page() breaks the original usage of restarting a list
    walk on a non-zero return value to handle a potentially unstable list,
    i.e. walks will unnecessarily restart when any page is zapped.
    
    Fix this by restoring the original behavior of kvm_mmu_zap_page(), i.e.
    return a boolean to indicate that the list may be unstable and move the
    number of zapped children to a dedicated parameter.  Since the majority
    of callers to kvm_mmu_prepare_zap_page() don't care about either return
    value, preserve the current definition of kvm_mmu_prepare_zap_page() by
    making it a wrapper of a new helper, __kvm_mmu_prepare_zap_page().  This
    avoids having to update every call site and also provides cleaner code
    for functions that only care about the number of pages zapped.
    
    Fixes: 54a4f023 ("KVM: MMU: make kvm_mmu_zap_page() return
                          the number of pages it actually freed")
    Signed-off-by: default avatarSean Christopherson <sean.j.christopherson@intel.com>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    83cdb568
mmu.c 158 KB