]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: report max number of SEV guests
authorDaniel P. Berrangé <berrange@redhat.com>
Wed, 8 Dec 2021 19:53:45 +0000 (14:53 -0500)
committerDaniel P. Berrangé <berrange@redhat.com>
Tue, 14 Dec 2021 16:04:17 +0000 (16:04 +0000)
Different CPU generations have different limits on the number
of SEV/SEV-ES guests that can be run. Since both limits come
from the same overall set, there is typically also BIOS config
to set the tradeoff betweeen SEV and SEV-ES guest limits.

This is important information to expose for a mgmt application
scheduling guests to hosts.

Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/qemu/qemu_capabilities.c
src/qemu/qemu_driver.c
tests/domaincapsdata/qemu_2.12.0-q35.x86_64.xml
tests/domaincapsdata/qemu_2.12.0-tcg.x86_64.xml
tests/domaincapsdata/qemu_2.12.0.x86_64.xml
tests/domaincapsdata/qemu_6.0.0-q35.x86_64.xml
tests/domaincapsdata/qemu_6.0.0-tcg.x86_64.xml
tests/domaincapsdata/qemu_6.0.0.x86_64.xml
tests/testutilsqemu.c

index 4ffd0a98a2e9aae3d5fa162cc426769c2dcb7718..ddd61ecfc93153d03fa2df541d2545e28cf492ed 100644 (file)
@@ -1897,6 +1897,8 @@ virQEMUCapsSEVInfoCopy(virSEVCapability **dst,
 
     tmp->cbitpos = src->cbitpos;
     tmp->reduced_phys_bits = src->reduced_phys_bits;
+    tmp->max_guests = src->max_guests;
+    tmp->max_es_guests = src->max_es_guests;
 
     *dst = g_steal_pointer(&tmp);
     return 0;
@@ -3286,6 +3288,31 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCaps *qemuCaps,
 }
 
 
+static void
+virQEMUCapsGetSEVMaxGuests(virSEVCapability *caps)
+{
+    /*
+     * From Secure Encrypted Virtualization API v0.24, section 6.19.1
+     *
+     * If the guest is SEV-ES enabled, then the ASID must be at least
+     * 1h and at most (MIN_SEV_ASID-1). If the guest is not SEV-ES
+     * enabled, then the ASID must be at least MIN_SEV_ASID and at
+     * most the maximum SEV ASID available. The MIN_SEV_ASID value
+     * is discovered by CPUID Fn8000_001F[EDX]. The maximum SEV ASID
+     * available is discovered by CPUID Fn8000_001F[ECX].
+     */
+    uint32_t min_asid, max_asid;
+    virHostCPUX86GetCPUID(0x8000001F, 0, NULL, NULL,
+                          &max_asid, &min_asid);
+
+    if (max_asid != 0 && min_asid != 0) {
+        caps->max_guests = max_asid - min_asid + 1;
+        caps->max_es_guests = min_asid - 1;
+    } else {
+        caps->max_guests = caps->max_es_guests = 0;
+    }
+}
+
 static int
 virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps,
                                    qemuMonitor *mon)
@@ -3305,6 +3332,8 @@ virQEMUCapsProbeQMPSEVCapabilities(virQEMUCaps *qemuCaps,
         return 0;
     }
 
+    virQEMUCapsGetSEVMaxGuests(caps);
+
     virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
     qemuCaps->sevCapabilities = caps;
     return 0;
@@ -4084,6 +4113,14 @@ virQEMUCapsParseSEVInfo(virQEMUCaps *qemuCaps, xmlXPathContextPtr ctxt)
         return -1;
     }
 
+
+    /* We probe this every time because the values
+     * can change on every reboot via firmware
+     * config tunables. It is cheap to query so
+     * lack of caching is a non-issue
+     */
+    virQEMUCapsGetSEVMaxGuests(sev);
+
     qemuCaps->sevCapabilities = g_steal_pointer(&sev);
     return 0;
 }
@@ -6344,6 +6381,8 @@ virQEMUCapsFillDomainFeatureSEVCaps(virQEMUCaps *qemuCaps,
     domCaps->sev->cert_chain = g_strdup(cap->cert_chain);
     domCaps->sev->cbitpos = cap->cbitpos;
     domCaps->sev->reduced_phys_bits = cap->reduced_phys_bits;
+    domCaps->sev->max_guests = cap->max_guests;
+    domCaps->sev->max_es_guests = cap->max_es_guests;
 }
 
 
index be5cfff8fef002674b7eba0b1627695517da83e1..aae622ea5de29eac427075b12f78341472f165b2 100644 (file)
@@ -19917,6 +19917,16 @@ qemuGetSEVInfoToParams(virQEMUCaps *qemuCaps,
                     sev->reduced_phys_bits) < 0)
         goto cleanup;
 
+    if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
+                    VIR_NODE_SEV_MAX_GUESTS,
+                    sev->max_guests) < 0)
+        goto cleanup;
+
+    if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
+                    VIR_NODE_SEV_MAX_ES_GUESTS,
+                    sev->max_es_guests) < 0)
+        goto cleanup;
+
     *params = g_steal_pointer(&sevParams);
     *nparams = n;
     return 0;
index 26816ff06669e1c32e7c8c600f8efec8c8204897..0dc5995c090521433019176bc22e5d461a8cb616 100644 (file)
     <sev supported='yes'>
       <cbitpos>47</cbitpos>
       <reducedPhysBits>1</reducedPhysBits>
-      <maxGuests>0</maxGuests>
-      <maxESGuests>0</maxESGuests>
+      <maxGuests>59</maxGuests>
+      <maxESGuests>450</maxESGuests>
     </sev>
   </features>
 </domainCapabilities>
index 5840a8b921abb4856c0cafe5f026b77d9af0e49c..575506d852b7d2a1c7165d72f5effa9813683897 100644 (file)
     <sev supported='yes'>
       <cbitpos>47</cbitpos>
       <reducedPhysBits>1</reducedPhysBits>
-      <maxGuests>0</maxGuests>
-      <maxESGuests>0</maxESGuests>
+      <maxGuests>59</maxGuests>
+      <maxESGuests>450</maxESGuests>
     </sev>
   </features>
 </domainCapabilities>
index 21d1b6946e5298ee9bd69801fcb95b96c7bcc5db..c8a5558536b11d8321a9c360696eae92ec8f25a5 100644 (file)
     <sev supported='yes'>
       <cbitpos>47</cbitpos>
       <reducedPhysBits>1</reducedPhysBits>
-      <maxGuests>0</maxGuests>
-      <maxESGuests>0</maxESGuests>
+      <maxGuests>59</maxGuests>
+      <maxESGuests>450</maxESGuests>
     </sev>
   </features>
 </domainCapabilities>
index 3415d44019dde99ae96abbfd601522fea90a3477..4595e70f6173f8cbc187a74cb882f95925ffc38c 100644 (file)
     <sev supported='yes'>
       <cbitpos>47</cbitpos>
       <reducedPhysBits>1</reducedPhysBits>
-      <maxGuests>0</maxGuests>
-      <maxESGuests>0</maxESGuests>
+      <maxGuests>59</maxGuests>
+      <maxESGuests>450</maxESGuests>
     </sev>
   </features>
 </domainCapabilities>
index f58be3af6ce2dd71bd72906aa6cd8a81cd7bf704..6b85c9c45ae388d962cf057cd1cfca2615436c84 100644 (file)
     <sev supported='yes'>
       <cbitpos>47</cbitpos>
       <reducedPhysBits>1</reducedPhysBits>
-      <maxGuests>0</maxGuests>
-      <maxESGuests>0</maxESGuests>
+      <maxGuests>59</maxGuests>
+      <maxESGuests>450</maxESGuests>
     </sev>
   </features>
 </domainCapabilities>
index 0a2615c519420efab660111c94886878929c33df..a6fa3742116da7ab90027f976b89997bf71cef79 100644 (file)
     <sev supported='yes'>
       <cbitpos>47</cbitpos>
       <reducedPhysBits>1</reducedPhysBits>
-      <maxGuests>0</maxGuests>
-      <maxESGuests>0</maxESGuests>
+      <maxGuests>59</maxGuests>
+      <maxESGuests>450</maxESGuests>
     </sev>
   </features>
 </domainCapabilities>
index 5bd1d40ad4603cea8e896250b591fc5722086492..7b19575d8b563afab7bd44528a90f75c89ad97b2 100644 (file)
@@ -143,6 +143,29 @@ virCapabilitiesHostNUMANewHost(void)
     return virTestCapsBuildNUMATopology(3);
 }
 
+void
+virHostCPUX86GetCPUID(uint32_t leaf,
+                      uint32_t extended,
+                      uint32_t *eax,
+                      uint32_t *ebx,
+                      uint32_t *ecx,
+                      uint32_t *edx)
+{
+    if (eax)
+        *eax = 0;
+    if (ebx)
+        *ebx = 0;
+    if (ecx)
+        *ecx = 0;
+    if (edx)
+        *edx = 0;
+    if (leaf == 0x8000001F && extended == 0) {
+        if (ecx)
+            *ecx = 509;
+        if (edx)
+            *edx = 451;
+    }
+}
 
 static int
 testQemuAddGuest(virCaps *caps,