All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tom Lendacky <thomas.lendacky@amd.com>
To: "Jörg Rödel" <joro@8bytes.org>,
	"Sean Christopherson" <seanjc@google.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>
Cc: x86@kernel.org, Michael Roth <michael.roth@amd.com>,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	coconut-svsm@lists.linux.dev, Joerg Roedel <joerg.roedel@amd.com>
Subject: Re: [PATCH 1/4] kvm: svm: Streamline VMSA setting for VCPUs
Date: Tue, 16 Jun 2026 15:52:55 -0500	[thread overview]
Message-ID: <5dc215d1-ea45-4e4d-b79f-0490c1940639@amd.com> (raw)
In-Reply-To: <20260611123528.572255-2-joro@8bytes.org>

On 6/11/26 07:35, Jörg Rödel wrote:
> From: Joerg Roedel <joerg.roedel@amd.com>
> 
> Streamline the VMSA setting state of vcpus, where a VMSA can be either
> KVM-allocated or guest-provided. This consolidates the various
> tracking state around VMSAs.
> 
> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
> ---
>  arch/x86/kvm/svm/sev.c | 301 ++++++++++++++++++++++++++++-------------
>  arch/x86/kvm/svm/svm.h |  31 ++++-
>  2 files changed, 237 insertions(+), 95 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 6c6a6d663e29..9b1280222e20 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -147,6 +147,9 @@ static bool sev_snp_guest(struct kvm *kvm)
>  }
>  
>  static int snp_decommission_context(struct kvm *kvm);
> +static int kvm_rmp_make_shared(struct kvm *kvm, u64 pfn, enum pg_level level);
> +static void sev_flush_encrypted_page(struct kvm_vcpu *vcpu, void *va);
> +static int snp_page_reclaim(struct kvm *kvm, u64 pfn);

Can this be worked so that we don't add more forward declarations?

>  
>  struct enc_region {
>  	struct list_head list;
> @@ -156,6 +159,173 @@ struct enc_region {
>  	unsigned long size;
>  };
>  
> +static void *sev_es_vmsa_ref(struct kvm_vcpu *vcpu)

sev_es_get_kvm_shared_vmsa ?

> +{
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	void *vmsa = NULL;
> +
> +	if (svm->sev_es.vmsa.vmsa_state == VMSA_SHARED) {
> +		vmsa = page_address(svm->sev_es.vmsa.vmsa_page);
> +	}
> +
> +	return vmsa;

How about just:

	if (svm->sev_es.vmsa.vmsa_state == VMSA_SHARED)
		return page_address(svm->sev_es.vmsa.vmsa_page);

	return NULL;

> +}
> +
> +static int sev_es_vcpu_alloc_vmsa(struct kvm_vcpu *vcpu)

sev_es_alloc_kvm_vmsa ?

> +{
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	struct page *vmsa_page;
> +
> +	if (WARN_ON_ONCE(svm->sev_es.vmsa.vmsa_state != VMSA_NONE))
> +		return -EINVAL;
> +
> +	/*
> +	 * SEV-ES guests require a separate (from the VMCB) VMSA page used to
> +	 * contain the encrypted register state of the guest.
> +	 */
> +	vmsa_page = snp_safe_alloc_page();
> +	if (!vmsa_page)
> +		return -ENOMEM;
> +
> +	svm->sev_es.vmsa.vmsa_state = VMSA_SHARED;
> +	svm->sev_es.vmsa.vmsa_page = vmsa_page;
> +
> +	return 0;
> +}
> +
> +static int sev_es_vcpu_vmsa_make_private(struct kvm_vcpu *vcpu)

sev_es_make_kvm_vmsa_private ?

> +{
> +	struct kvm_sev_info *sev = to_kvm_sev_info(vcpu->kvm);
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	void *vmsa = sev_es_vmsa_ref(vcpu);
> +
> +	if (!vmsa)
> +		return -EINVAL;
> +
> +	if (is_sev_snp_guest(vcpu)) {
> +		u64 pfn = __pa(vmsa) >> PAGE_SHIFT;
> +		int ret;
> +
> +		/* Transition the VMSA page to a firmware state. */
> +		ret = rmp_make_private(pfn, INITIAL_VMSA_GPA, PG_LEVEL_4K, sev->asid, true);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	svm->sev_es.vmsa.vmsa_state = VMSA_PRIVATE;
> +
> +	return 0;
> +}
> +
> +static void sev_es_vcpu_free_vmsa(struct kvm_vcpu *vcpu)

sev_es_free_kvm_vmsa ?

> +{
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	void *vmsa_ptr;

s/vmsa_ptr/vmsa/

> +
> +	switch (svm->sev_es.vmsa.vmsa_state) {
> +	case VMSA_NONE:
> +	case VMSA_GUEST:
> +		break;
> +	case VMSA_PRIVATE:
> +		vmsa_ptr = page_address(svm->sev_es.vmsa.vmsa_page);
> +
> +		if (is_sev_snp_guest(vcpu)) {
> +			u64 pfn = __pa(vmsa_ptr) >> PAGE_SHIFT;

PHYS_PFN(__pa(vmsa));

> +
> +			if (kvm_rmp_make_shared(vcpu->kvm, pfn, PG_LEVEL_4K)) {
> +				pr_err("Failed to make VMSA page shared - leaking it to avoid re-use\n");
> +				goto out;

s/goto out/break/
> +			}
> +		}
> +
> +		if (vcpu->arch.guest_state_protected)
> +			sev_flush_encrypted_page(vcpu, vmsa_ptr);
> +
> +		fallthrough;
> +	case VMSA_SHARED:
> +		__free_page(svm->sev_es.vmsa.vmsa_page);
> +		break;
> +	default:
> +		BUG();

WARN_ON or WARN_ON_ONCE() instead of BUG().
> +	}
> +out:

If using the 'break' above, then no need for this label.

> +
> +	svm->sev_es.vmsa.vmsa_page = NULL;
> +	svm->sev_es.vmsa.vmsa_state = VMSA_NONE;
> +}
> +
> +static void sev_snp_vcpu_reclaim_vmsa(struct kvm_vcpu *vcpu)

sev_snp_reclaim_kvm_vmsa ?

> +{
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	void *vmsa_ptr;

s/vmsa_ptr/vmsa/

> +	u64 pfn;
> +
> +	if (WARN_ON_ONCE(!is_sev_snp_guest(vcpu) ||
> +	                 svm->sev_es.vmsa.vmsa_state != VMSA_PRIVATE))
> +		return;
> +
> +	vmsa_ptr = page_address(svm->sev_es.vmsa.vmsa_page);
> +	pfn = __pa(vmsa_ptr) >> PAGE_SHIFT;

PHYS_PFN()

> +
> +	if (!snp_page_reclaim(vcpu->kvm, pfn))
> +		__free_page(svm->sev_es.vmsa.vmsa_page);

Should you issue a message here similar to above about leaking the page
if snp_page_reclaim() fails?

> +
> +	svm->sev_es.vmsa.vmsa_page = NULL;
> +	svm->sev_es.vmsa.vmsa_state = VMSA_NONE;
> +}
> +
> +static void sev_es_set_guest_vmsa(struct kvm_vcpu *vcpu, gpa_t vmsa_gpa)
> +{
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +
> +	sev_es_vcpu_free_vmsa(vcpu);
> +
> +	svm->sev_es.vmsa.vmsa_state = VMSA_GUEST;
> +	svm->sev_es.vmsa.vmsa_gpa = vmsa_gpa;
> +}
> +
> +static u64 sev_es_vmsa_pa(struct kvm_vcpu *vcpu)
> +{
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	enum vmsa_state vmsa_state = svm->sev_es.vmsa.vmsa_state;
> +	u64 vmsa_pa = INVALID_PAGE;
> +
> +	if (vmsa_state == VMSA_GUEST) {

Would a switch statement like you have in sev_es_vcpu_free_vmsa() be
more consistent?

Also, you could return INVALID_PAGE directly instead of having the goto's.

	switch (svm->sev_es.vmsa.vmsa_state) {
	case VMSA_NONE:
		return INVALID_PAGE;

	case VMSA_SHARED:
	case VMSA_PRIVATE:
		return __pa(page_address(svm->sev_es.vmsa.vmsa_page));

	case VMSA_GUEST:
		...
	}

> +		gpa_t vmsa_gpa = svm->sev_es.vmsa.vmsa_gpa;
> +		struct kvm_memory_slot *slot;
> +		struct page *page;
> +		kvm_pfn_t pfn;
> +		gfn_t gfn;
> +
> +		gfn = gpa_to_gfn(vmsa_gpa);
> +
> +		slot = gfn_to_memslot(vcpu->kvm, gfn);
> +		if (!slot)
> +			goto out;
> +
> +		/*
> +		 * The new VMSA will be private memory guest memory, so retrieve the
> +		 * PFN from the gmem backend.
> +		 */
> +		if (kvm_gmem_get_pfn(vcpu->kvm, slot, gfn, &pfn, &page, NULL))
> +			goto out;
> +
> +		vmsa_pa = pfn_to_hpa(pfn);
> +
> +		/*
> +		 * gmem pages aren't currently migratable, but if this ever changes
> +		 * then care should be taken to ensure the guest vmsa is pinned
> +		 * through some other means.
> +		 */
> +		kvm_release_page_clean(page);
> +	} else if (vmsa_state == VMSA_PRIVATE || vmsa_state == VMSA_SHARED) {
> +		vmsa_pa = __pa(page_address(svm->sev_es.vmsa.vmsa_page));
> +	}
> +
> +out:
> +	return vmsa_pa;
> +}
> +
>  /* Called with the sev_bitmap_lock held, or on shutdown  */
>  static int sev_flush_asids(unsigned int min_asid, unsigned int max_asid)
>  {
> @@ -925,7 +1095,7 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
>  {
>  	struct kvm_vcpu *vcpu = &svm->vcpu;
>  	struct kvm_sev_info *sev = to_kvm_sev_info(vcpu->kvm);
> -	struct sev_es_save_area *save = svm->sev_es.vmsa;
> +	struct sev_es_save_area *save = sev_es_vmsa_ref(vcpu);
>  	struct xregs_state *xsave;
>  	const u8 *s;
>  	u8 *d;
> @@ -1026,6 +1196,7 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  {
>  	struct sev_data_launch_update_vmsa vmsa;
>  	struct vcpu_svm *svm = to_svm(vcpu);
> +	void *vmsa_ref = sev_es_vmsa_ref(vcpu);

Might make more sense rename the sev_data_launch_update_vmsa variable to
vmsa_lu and keep this as just vmsa ?\

>  	int ret;
>  
>  	if (vcpu->guest_debug) {
> @@ -1043,15 +1214,19 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  	 * the VMSA memory content (i.e it will write the same memory region
>  	 * with the guest's key), so invalidate it first.
>  	 */
> -	clflush_cache_range(svm->sev_es.vmsa, PAGE_SIZE);
> +	clflush_cache_range(vmsa_ref, PAGE_SIZE);
>  
>  	vmsa.reserved = 0;
>  	vmsa.handle = to_kvm_sev_info(kvm)->handle;
> -	vmsa.address = __sme_pa(svm->sev_es.vmsa);
> +	vmsa.address = __sme_pa(vmsa_ref);
>  	vmsa.len = PAGE_SIZE;
>  	ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_VMSA, &vmsa, error);
>  	if (ret)
> -	  return ret;
> +		goto free_vmsa;
> +
> +	ret = sev_es_vcpu_vmsa_make_private(vcpu);
> +	if (ret)
> +		goto free_vmsa;

Similar to the SNP path, you can probably move this to before the
LAUNCH_UPDATE, just for consistency.
>  
>  	/*
>  	 * SEV-ES guests maintain an encrypted version of their FPU
> @@ -1069,7 +1244,13 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,
>  	 * MSR_IA32_DEBUGCTLMSR when guest_state_protected is not set.
>  	 */
>  	svm_enable_lbrv(vcpu);
> +
>  	return 0;
> +
> +free_vmsa:
> +	sev_es_vcpu_free_vmsa(vcpu);
> +
> +	return ret;
>  }
>  
>  static int sev_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
> @@ -2508,23 +2689,22 @@ static int snp_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
>  
>  	kvm_for_each_vcpu(i, vcpu, kvm) {
>  		struct vcpu_svm *svm = to_svm(vcpu);
> -		u64 pfn = __pa(svm->sev_es.vmsa) >> PAGE_SHIFT;
> +		void *vmsa = sev_es_vmsa_ref(vcpu);
>  
>  		ret = sev_es_sync_vmsa(svm);
>  		if (ret)
>  			goto out;
>  
> -		/* Transition the VMSA page to a firmware state. */
> -		ret = rmp_make_private(pfn, INITIAL_VMSA_GPA, PG_LEVEL_4K, sev->asid, true);
> +		ret = sev_es_vcpu_vmsa_make_private(vcpu);
>  		if (ret)
>  			goto out;
>  
>  		/* Issue the SNP command to encrypt the VMSA */
> -		data.address = __sme_pa(svm->sev_es.vmsa);
> +		data.address = __sme_pa(vmsa);
>  		ret = __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_LAUNCH_UPDATE,
>  				      &data, &argp->error);
>  		if (ret) {
> -			snp_page_reclaim(kvm, pfn);
> +			sev_snp_vcpu_reclaim_vmsa(vcpu);
>  
>  			goto out;
>  		}

It might be nice to break the loop contents out into its own function
like is done with ES. I haven't looked ahead in the series to see if
that would make it easier to supply/measure a single VMSA or not, though.

> @@ -3593,31 +3773,13 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
>  
>  void sev_free_vcpu(struct kvm_vcpu *vcpu)
>  {
> -	struct vcpu_svm *svm;
> +	struct vcpu_svm *svm = to_svm(vcpu);

You can probably reduce the churn here by keeping this line unchanged
and not deleting the assignment below.

>  
>  	if (!is_sev_es_guest(vcpu))
>  		return;
>  
> -	svm = to_svm(vcpu);
> -
> -	/*
> -	 * If it's an SNP guest, then the VMSA was marked in the RMP table as
> -	 * a guest-owned page. Transition the page to hypervisor state before
> -	 * releasing it back to the system.
> -	 */
> -	if (is_sev_snp_guest(vcpu)) {
> -		u64 pfn = __pa(svm->sev_es.vmsa) >> PAGE_SHIFT;
> -
> -		if (kvm_rmp_make_shared(vcpu->kvm, pfn, PG_LEVEL_4K))
> -			goto skip_vmsa_free;
> -	}
> -
> -	if (vcpu->arch.guest_state_protected)
> -		sev_flush_encrypted_page(vcpu, svm->sev_es.vmsa);
> -
> -	__free_page(virt_to_page(svm->sev_es.vmsa));
> +	sev_es_vcpu_free_vmsa(vcpu);
>  
> -skip_vmsa_free:
>  	__sev_es_unmap_ghcb(svm);
>  }
>  
> @@ -4067,10 +4229,7 @@ static int snp_begin_psc(struct vcpu_svm *svm)
>  static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
>  {
>  	struct vcpu_svm *svm = to_svm(vcpu);
> -	struct kvm_memory_slot *slot;
> -	struct page *page;
> -	kvm_pfn_t pfn;
> -	gfn_t gfn;
> +	u64 vmsa_pa;
>  
>  	guard(mutex)(&svm->sev_es.snp_vmsa_mutex);
>  
> @@ -4092,46 +4251,17 @@ static void sev_snp_init_protected_guest_state(struct kvm_vcpu *vcpu)
>  	 */
>  	vmcb_mark_all_dirty(svm->vmcb);
>  
> -	if (!VALID_PAGE(svm->sev_es.snp_vmsa_gpa))
> -		return;
> -
> -	gfn = gpa_to_gfn(svm->sev_es.snp_vmsa_gpa);
> -	svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
> +	sev_es_set_guest_vmsa(vcpu, svm->sev_es.req_vmsa_gpa);
> +	vmsa_pa = sev_es_vmsa_pa(vcpu);
>  
> -	slot = gfn_to_memslot(vcpu->kvm, gfn);
> -	if (!slot)
> +	if (!VALID_PAGE(vmsa_pa))
>  		return;
>  
> -	/*
> -	 * The new VMSA will be private memory guest memory, so retrieve the
> -	 * PFN from the gmem backend.
> -	 */
> -	if (kvm_gmem_get_pfn(vcpu->kvm, slot, gfn, &pfn, &page, NULL))
> -		return;
> -
> -	/*
> -	 * From this point forward, the VMSA will always be a guest-mapped page
> -	 * rather than the initial one allocated by KVM in svm->sev_es.vmsa. In
> -	 * theory, svm->sev_es.vmsa could be free'd and cleaned up here, but
> -	 * that involves cleanups like flushing caches, which would ideally be
> -	 * handled during teardown rather than guest boot.  Deferring that also
> -	 * allows the existing logic for SEV-ES VMSAs to be re-used with
> -	 * minimal SNP-specific changes.
> -	 */
> -	svm->sev_es.snp_has_guest_vmsa = true;
> -
>  	/* Use the new VMSA */
> -	svm->vmcb->control.vmsa_pa = pfn_to_hpa(pfn);
> +	svm->vmcb->control.vmsa_pa = vmsa_pa;
>  
>  	/* Mark the vCPU as runnable */
>  	kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE);
> -
> -	/*
> -	 * gmem pages aren't currently migratable, but if this ever changes
> -	 * then care should be taken to ensure svm->sev_es.vmsa is pinned
> -	 * through some other means.
> -	 */
> -	kvm_release_page_clean(page);
>  }
>  
>  static int sev_snp_ap_creation(struct vcpu_svm *svm)
> @@ -4187,10 +4317,10 @@ static int sev_snp_ap_creation(struct vcpu_svm *svm)
>  			return -EINVAL;
>  		}
>  
> -		target_svm->sev_es.snp_vmsa_gpa = svm->vmcb->control.exit_info_2;
> +		target_svm->sev_es.req_vmsa_gpa = svm->vmcb->control.exit_info_2;
>  		break;
>  	case SVM_VMGEXIT_AP_DESTROY:
> -		target_svm->sev_es.snp_vmsa_gpa = INVALID_PAGE;
> +		target_svm->sev_es.req_vmsa_gpa = INVALID_PAGE;
>  		break;
>  	default:
>  		vcpu_unimpl(vcpu, "vmgexit: invalid AP creation request [%#x] from guest\n",
> @@ -4708,20 +4838,7 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm, bool init_event)
>  	struct vmcb *vmcb = svm->vmcb01.ptr;
>  
>  	svm->vmcb->control.misc_ctl |= SVM_MISC_ENABLE_SEV_ES;
> -
> -	/*
> -	 * An SEV-ES guest requires a VMSA area that is a separate from the
> -	 * VMCB page. Do not include the encryption mask on the VMSA physical
> -	 * address since hardware will access it using the guest key.  Note,
> -	 * the VMSA will be NULL if this vCPU is the destination for intrahost
> -	 * migration, and will be copied later.
> -	 */
> -	if (!svm->sev_es.snp_has_guest_vmsa) {
> -		if (svm->sev_es.vmsa)
> -			svm->vmcb->control.vmsa_pa = __pa(svm->sev_es.vmsa);
> -		else
> -			svm->vmcb->control.vmsa_pa = INVALID_PAGE;
> -	}
> +	svm->vmcb->control.vmsa_pa = sev_es_vmsa_pa(&svm->vcpu);
>  
>  	if (cpu_feature_enabled(X86_FEATURE_ALLOWED_SEV_FEATURES))
>  		svm->vmcb->control.allowed_sev_features = sev->vmsa_features |
> @@ -4797,7 +4914,7 @@ void sev_init_vmcb(struct vcpu_svm *svm, bool init_event)
>  int sev_vcpu_create(struct kvm_vcpu *vcpu)
>  {
>  	struct vcpu_svm *svm = to_svm(vcpu);
> -	struct page *vmsa_page;
> +	int ret;
>  
>  	mutex_init(&svm->sev_es.snp_vmsa_mutex);
>  
> @@ -4808,11 +4925,9 @@ int sev_vcpu_create(struct kvm_vcpu *vcpu)
>  	 * SEV-ES guests require a separate (from the VMCB) VMSA page used to
>  	 * contain the encrypted register state of the guest.
>  	 */
> -	vmsa_page = snp_safe_alloc_page();
> -	if (!vmsa_page)
> -		return -ENOMEM;
> -
> -	svm->sev_es.vmsa = page_address(vmsa_page);
> +	ret = sev_es_vcpu_alloc_vmsa(vcpu);
> +	if (ret)
> +		return ret;
>  
>  	vcpu->arch.guest_tsc_protected = snp_is_secure_tsc_enabled(vcpu->kvm);
>  
> @@ -5227,12 +5342,14 @@ struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
>  	if (!is_sev_es_guest(vcpu))
>  		return NULL;
>  
> +	vmsa = sev_es_vmsa_ref(vcpu);
> +
>  	/*
>  	 * If the VMSA has not yet been encrypted, return a pointer to the
>  	 * current un-encrypted VMSA.
>  	 */
> -	if (!vcpu->arch.guest_state_protected)
> -		return (struct vmcb_save_area *)svm->sev_es.vmsa;
> +	if (vmsa)
> +		return vmsa;
>  
>  	sev = to_kvm_sev_info(vcpu->kvm);
>  
> @@ -5303,8 +5420,10 @@ struct vmcb_save_area *sev_decrypt_vmsa(struct kvm_vcpu *vcpu)
>  
>  void sev_free_decrypted_vmsa(struct kvm_vcpu *vcpu, struct vmcb_save_area *vmsa)
>  {
> +	struct vmcb_save_area *vmsa_ptr = sev_es_vmsa_ref(vcpu);
> +
>  	/* If the VMSA has not yet been encrypted, nothing was allocated */
> -	if (!vcpu->arch.guest_state_protected || !vmsa)
> +	if (vmsa == vmsa_ptr)

Can't this just be

	if (sev_es_vmsa_ref(vcpu))

And then you save defining a new variable.

>  		return;
>  
>  	free_page((unsigned long)vmsa);
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 5137416be593..3d4799f09b23 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -240,9 +240,29 @@ struct svm_nested_state {
>  	bool force_msr_bitmap_recalc;
>  };
>  
> +enum vmsa_state {
> +	/* No VMSA set */
> +	VMSA_NONE,
> +	/* VMSA allocated by KVM - Shared in RMP (if applicable) */
> +	VMSA_SHARED,

VMSA_KVM_SHARED

> +	/* VMSA allocated by KVM - Guest-private in RMP (SEV-SNP only) */
> +	VMSA_PRIVATE,

VMSA_KVM_PRIVATE

> +	/* Guest-owned VMSA */
> +	VMSA_GUEST,

VMSA_GUEST_OWNED

This way ownership of the page becomes more obvious when used in the code.

> +};
> +
> +struct sev_es_vmsa_state {
> +	enum vmsa_state vmsa_state;
> +	union {
> +		/* state == (KVM_SHARED || KVM_PRIVATE) */
> +		struct page *vmsa_page;
> +		/* state == GUEST */
> +		gpa_t vmsa_gpa;
> +	};
> +};
> +
>  struct vcpu_sev_es_state {
>  	/* SEV-ES support */
> -	struct sev_es_save_area *vmsa;
>  	struct ghcb *ghcb;
>  	u8 valid_bitmap[16];
>  	struct kvm_host_map ghcb_map;
> @@ -266,10 +286,13 @@ struct vcpu_sev_es_state {
>  
>  	u64 ghcb_registered_gpa;
>  
> -	struct mutex snp_vmsa_mutex; /* Used to handle concurrent updates of VMSA. */
> -	gpa_t snp_vmsa_gpa;
> +	/* VMSA related state */
> +	struct mutex snp_vmsa_mutex;	/* Used to handle concurrent updates of VMSA. */
> +	struct sev_es_vmsa_state vmsa;	/* VMSA currently used by the VCPU */
> +	gpa_t req_vmsa_gpa;		/* Requested new VMSA GPA */
> +
> +	bool snp_ap_runnable;

I don't see this used in the patch anywhere.

Thanks,
Tom

>  	bool snp_ap_waiting_for_reset;
> -	bool snp_has_guest_vmsa;
>  };
>  
>  struct vcpu_svm {


  parent reply	other threads:[~2026-06-16 20:53 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-11 12:35 [PATCH 0/4] KVM: SEV: Support direct setting of VMSA for SEV-SNP guests Jörg Rödel
2026-06-11 12:35 ` [PATCH 1/4] kvm: svm: Streamline VMSA setting for VCPUs Jörg Rödel
2026-06-11 12:56   ` sashiko-bot
2026-06-11 14:13     ` Jörg Rödel
2026-06-16 20:52   ` Tom Lendacky [this message]
2026-06-11 12:35 ` [PATCH 2/4] kvm: svm: Defer VMSA allocation to LAUNCH_FINISH stage Jörg Rödel
2026-06-11 12:58   ` sashiko-bot
2026-06-11 14:29     ` Jörg Rödel
2026-06-16 21:33   ` Tom Lendacky
2026-06-11 12:35 ` [PATCH 3/4] kvm: svm: Support guest-provided VMSA for launching Jörg Rödel
2026-06-11 13:05   ` sashiko-bot
2026-06-11 14:43     ` Jörg Rödel
2026-06-16 21:48   ` Tom Lendacky
2026-06-11 12:35 ` [PATCH 4/4] kvm: svm: Support KVM_SEV_SNP_PAGE_TYPE_VMSA at SNP_LAUNCH_UPDATE Jörg Rödel
2026-06-11 12:43   ` Sean Christopherson
2026-06-11 13:23     ` Jörg Rödel
2026-06-16 17:55       ` Sean Christopherson
2026-06-17  6:45         ` Jörg Rödel
2026-06-17 13:00           ` Sean Christopherson
2026-06-17 13:25             ` Jörg Rödel
2026-06-17 13:37               ` Sean Christopherson
2026-06-17 14:44                 ` Jörg Rödel
2026-06-17 13:18           ` James Bottomley
2026-06-17 13:28             ` Jörg Rödel
2026-06-17 13:45               ` James Bottomley
2026-06-17 14:53                 ` Jörg Rödel
2026-06-11 12:58   ` sashiko-bot
2026-06-11 15:23     ` Jörg Rödel
2026-06-16 22:11   ` Tom Lendacky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5dc215d1-ea45-4e4d-b79f-0490c1940639@amd.com \
    --to=thomas.lendacky@amd.com \
    --cc=coconut-svsm@lists.linux.dev \
    --cc=joerg.roedel@amd.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michael.roth@amd.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.