Re: reproducible BUG() in kvm_mmu_get_root() in TDP MMU

From: Paolo Bonzini
Date: Tue Jan 05 2021 - 13:07:58 EST


On 05/01/21 18:49, Ben Gardon wrote:
for_each_tdp_mmu_root(kvm, root) {
kvm_mmu_get_root(kvm, root);
<Do something, yield the MMU lock>
kvm_mmu_put_root(kvm, root);
}

In these cases the get and put root calls are there to ensure that the
root is not freed while the function is running, however they do this
too well. If the put root call reduces the root's root_count to 0, it
should be removed from the roots list and freed before the MMU lock is
released. However the above pattern never bothers to free the root.
The following would fix this bug:

-kvm_mmu_put_root(kvm, root);
+if (kvm_mmu_put_root(kvm, root))
+ kvm_tdp_mmu_free_root(kvm, root);

Is it worth writing a more complex iterator struct, so that for_each_tdp_mmu_root takes care of the get and put?

Paolo