All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Ashish Kalra <Ashish.Kalra@amd.com>
Cc: pbonzini@redhat.com, tglx@linutronix.de, mingo@redhat.com,
	bp@alien8.de,  dave.hansen@linux.intel.com, x86@kernel.org,
	hpa@zytor.com,  thomas.lendacky@amd.com, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org,  joro@8bytes.org
Subject: Re: [PATCH] x86/sev: Add support for allowing zero SEV ASIDs.
Date: Tue, 2 Jan 2024 16:30:10 -0800	[thread overview]
Message-ID: <ZZSqkm5WNEUuuA_h@google.com> (raw)
In-Reply-To: <20240102232136.38778-1-Ashish.Kalra@amd.com>

On Tue, Jan 02, 2024, Ashish Kalra wrote:
> @@ -2172,8 +2176,10 @@ void sev_vm_destroy(struct kvm *kvm)
>  
>  void __init sev_set_cpu_caps(void)
>  {
> -	if (!sev_enabled)
> +	if (!sev_guests_enabled) {

Ugh, what a mess.  The module param will show sev_enabled=false, but the caps
and CPUID will show SEV=true.

And this is doubly silly because "sev_enabled" is never actually checked, e.g.
if misc cgroup support is disabled, KVM_SEV_INIT will try to reclaim ASIDs and
eventually fail with -EBUSY, which is super confusing to users.

The other weirdness is that KVM can cause sev_enabled=false && sev_es_enabled=true,
but if *userspace* sets sev_enabled=false then sev_es_enabled is also forced off.

In other words, the least awful option seems to be to keep sev_enabled true :-(

>  		kvm_cpu_cap_clear(X86_FEATURE_SEV);
> +		return;

This is blatantly wrong, as it can result in KVM advertising SEV-ES if SEV is
disabled by the user.

> +	}
>  	if (!sev_es_enabled)
>  		kvm_cpu_cap_clear(X86_FEATURE_SEV_ES);
>  }
> @@ -2229,9 +2235,11 @@ void __init sev_hardware_setup(void)
>  		goto out;
>  	}
>  
> -	sev_asid_count = max_sev_asid - min_sev_asid + 1;
> -	WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
> -	sev_supported = true;
> +	if (min_sev_asid <= max_sev_asid) {
> +		sev_asid_count = max_sev_asid - min_sev_asid + 1;
> +		WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
> +		sev_supported = true;
> +	}
>  
>  	/* SEV-ES support requested? */
>  	if (!sev_es_enabled)
> @@ -2262,7 +2270,8 @@ void __init sev_hardware_setup(void)
>  	if (boot_cpu_has(X86_FEATURE_SEV))
>  		pr_info("SEV %s (ASIDs %u - %u)\n",
>  			sev_supported ? "enabled" : "disabled",
> -			min_sev_asid, max_sev_asid);
> +			sev_supported ? min_sev_asid : 0,
> +			sev_supported ? max_sev_asid : 0);

I honestly think we should print the "garbage" values.  The whole point of
printing the min/max SEV ASIDs was to help users understand why SEV is disabled,
i.e. printing zeroes is counterproductive.

>  	if (boot_cpu_has(X86_FEATURE_SEV_ES))
>  		pr_info("SEV-ES %s (ASIDs %u - %u)\n",
>  			sev_es_supported ? "enabled" : "disabled",

It's all a bit gross, but I think we want something like this (I'm definitely
open to suggestions though):

diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index d0c580607f00..bfac6d17462a 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -143,8 +143,20 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev)
 
 static int sev_asid_new(struct kvm_sev_info *sev)
 {
-       int asid, min_asid, max_asid, ret;
+       /*
+        * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
+        * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.  Note, the
+        * min ASID can end up larger than the max if basic SEV support is
+        * effectively disabled by disallowing use of ASIDs for SEV guests.
+        */
+       unsigned int min_asid = sev->es_active ? 1 : min_sev_asid;
+       unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
+       unsigned int asid;
        bool retry = true;
+       int ret;
+
+       if (min_asid > max_asid)
+               return -ENOTTY;
 
        WARN_ON(sev->misc_cg);
        sev->misc_cg = get_current_misc_cg();
@@ -157,12 +169,6 @@ static int sev_asid_new(struct kvm_sev_info *sev)
 
        mutex_lock(&sev_bitmap_lock);
 
-       /*
-        * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
-        * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
-        */
-       min_asid = sev->es_active ? 1 : min_sev_asid;
-       max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
 again:
        asid = find_next_zero_bit(sev_asid_bitmap, max_asid + 1, min_asid);
        if (asid > max_asid) {
@@ -2232,8 +2238,10 @@ void __init sev_hardware_setup(void)
                goto out;
        }
 
-       sev_asid_count = max_sev_asid - min_sev_asid + 1;
-       WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
+       if (min_sev_asid <= max_sev_asid) {
+               sev_asid_count = max_sev_asid - min_sev_asid + 1;
+               WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
+       }
        sev_supported = true;
 
        /* SEV-ES support requested? */
@@ -2264,8 +2272,9 @@ void __init sev_hardware_setup(void)
 out:
        if (boot_cpu_has(X86_FEATURE_SEV))
                pr_info("SEV %s (ASIDs %u - %u)\n",
-                       sev_supported ? "enabled" : "disabled",
-                       min_sev_asid, max_sev_asid);
+                       sev_supported ? (min_sev_asid <= max_sev_asid ? "enabled" : "unusable") : "disabled",
+                       sev_supported ? min_sev_asid : 0,
+                       sev_supported ? max_sev_asid : 0);
        if (boot_cpu_has(X86_FEATURE_SEV_ES))
                pr_info("SEV-ES %s (ASIDs %u - %u)\n",
                        sev_es_supported ? "enabled" : "disabled",

  reply	other threads:[~2024-01-03  0:30 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-02 23:21 [PATCH] x86/sev: Add support for allowing zero SEV ASIDs Ashish Kalra
2024-01-03  0:30 ` Sean Christopherson [this message]
2024-01-03 20:41   ` Kalra, Ashish
2024-01-03 21:10     ` Sean Christopherson
2024-01-03 21:22       ` Kalra, Ashish
2024-01-03 21:54         ` Sean Christopherson

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=ZZSqkm5WNEUuuA_h@google.com \
    --to=seanjc@google.com \
    --cc=Ashish.Kalra@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.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.