Re: [PATCH v4 21/30] KVM: x86/mmu: Zap invalidated roots via asynchronous worker

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Mar 03, 2022, Paolo Bonzini wrote:
> diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> index 0b88592495f8..9287ee078c49 100644
> --- a/arch/x86/kvm/mmu/mmu.c
> +++ b/arch/x86/kvm/mmu/mmu.c
> @@ -5730,7 +5730,6 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
>  	kvm_make_all_cpus_request(kvm, KVM_REQ_MMU_FREE_OBSOLETE_ROOTS);
>  
>  	kvm_zap_obsolete_pages(kvm);
> -

Spurious whitespace deletion.

>  	write_unlock(&kvm->mmu_lock);
>  
>  	/*
> @@ -5741,11 +5740,8 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
>  	 * Deferring the zap until the final reference to the root is put would
>  	 * lead to use-after-free.
>  	 */
> -	if (is_tdp_mmu_enabled(kvm)) {
> -		read_lock(&kvm->mmu_lock);
> +	if (is_tdp_mmu_enabled(kvm))
>  		kvm_tdp_mmu_zap_invalidated_roots(kvm);
> -		read_unlock(&kvm->mmu_lock);
> -	}
>  }
>  
>  static bool kvm_has_zapped_obsolete_pages(struct kvm *kvm)

...

> +static void tdp_mmu_schedule_zap_root(struct kvm *kvm, struct kvm_mmu_page *root)
> +{

Definitely worth doing (I'll provide more info in the "Zap defunct roots" patch):

	WARN_ON_ONCE(!root->role.invalid || root->tdp_mmu_async_data);

The assertion on role.invalid is a little overkill, but might help document when
and how this is used.

> +	root->tdp_mmu_async_data = kvm;
> +	INIT_WORK(&root->tdp_mmu_async_work, tdp_mmu_zap_root_work);
> +	queue_work(kvm->arch.tdp_mmu_zap_wq, &root->tdp_mmu_async_work);
> +}
> +
> +static inline bool kvm_tdp_root_mark_invalid(struct kvm_mmu_page *page)
> +{
> +	union kvm_mmu_page_role role = page->role;
> +	role.invalid = true;
> +
> +	/* No need to use cmpxchg, only the invalid bit can change.  */
> +	role.word = xchg(&page->role.word, role.word);
> +	return role.invalid;

This helper is unused.  It _could_ be used here, but I think it belongs in the
next patch.  Critically, until zapping defunct roots creates the invariant that
invalid roots are _always_ zapped via worker, kvm_tdp_mmu_invalidate_all_roots()
must not assume that an invalid root is queued for zapping.  I.e. doing this
before the "Zap defunct roots" would be wrong:

	list_for_each_entry(root, &kvm->arch.tdp_mmu_roots, link) {
		if (kvm_tdp_root_mark_invalid(root))
			continue;

		if (WARN_ON_ONCE(!kvm_tdp_mmu_get_root(root)));
			continue;

		tdp_mmu_schedule_zap_root(kvm, root);
	}



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux