File e6c29f09-conf-Add-support-for-specifying-CPU-max-physical-add.patch of Package libvirt.29155

From a6999b15ccf3633e0bddc1c793197c00b34981e7 Mon Sep 17 00:00:00 2001
From: Dario Faggioli <dfaggioli@suse.com>
Date: Fri, 29 Jul 2022 13:34:33 -0600
Subject: [PATCH 2/9] conf: Add support for specifying CPU max physical address
 size

This patch introduces the

    <maxphysaddr mode='passthrough'/>
    <maxphysaddr mode='emulate' bits='42'/>

sub element of /domain/cpu, which allows specifying the guest virtual CPU
address size. This can be useful if the guest needs to have a large amount
of memory.

If mode='passthrough', the virtual CPU will have the same number of address
bits as the host. If mode='emulate', the mandatory bits attribute specifies
the number of address bits.

Signed-off-by: Dario Faggioli <dfaggioli@suse.com>
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit e6c29f09e5b75d7a8d79ae670407060446282c78)

 Conflicts:
	src/qemu/qemu_validate.c
---
 docs/formatdomain.rst                         | 23 ++++++++++
 docs/schemas/cputypes.rng                     | 19 ++++++++
 src/conf/cpu_conf.c                           | 46 +++++++++++++++++++
 src/conf/cpu_conf.h                           | 17 +++++++
 src/libvirt_private.syms                      |  2 +
 src/qemu/qemu_validate.c                      | 41 +++++++++++++++++
 .../cpu-phys-bits-emulate.xml                 | 20 ++++++++
 .../cpu-phys-bits-passthrough.xml             | 20 ++++++++
 tests/genericxml2xmltest.c                    |  2 +
 9 files changed, 190 insertions(+)
 create mode 100644 tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml
 create mode 100644 tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml

Index: libvirt-8.0.0/docs/formatdomain.rst
===================================================================
--- libvirt-8.0.0.orig/docs/formatdomain.rst
+++ libvirt-8.0.0/docs/formatdomain.rst
@@ -1263,6 +1263,7 @@ following collection of elements. :since
      <vendor>Intel</vendor>
      <topology sockets='1' dies='1' cores='2' threads='1'/>
      <cache level='3' mode='emulate'/>
+     <maxphysaddr mode='emulate' bits='42'>
      <feature policy='disable' name='lahf_lm'/>
    </cpu>
    ...
@@ -1279,6 +1280,7 @@ following collection of elements. :since
 
    <cpu mode='host-passthrough' migratable='off'>
      <cache mode='passthrough'/>
+     <maxphysaddr mode='passthrough'>
      <feature policy='disable' name='lahf_lm'/>
    ...
 
@@ -1526,6 +1528,27 @@ In case no restrictions need to be put o
          The virtual CPU will report no CPU cache of the specified level (or no
          cache at all if the ``level`` attribute is missing).
 
+``maxphysaddr``
+   :since:`Since 8.7.0` the ``maxphysaddr`` element describes the virtual CPU
+   address size in bits. The hypervisor default is used if the element is missing.
+
+   ``mode``
+      This mandatory attribute specifies how the address size is presented. The
+      follow modes are supported:
+
+      ``passthrough``
+         The number of physical address bits reported by the host CPU will be
+         passed through to the virtual CPUs
+      ``emulate``
+         The hypervisor will define a specific value for the number of bits
+         of physical addresses via the ``bits`` attribute, which is mandatory.
+	 The number of bits cannot exceed the number of physical address bits
+	 supported by the hypervisor.
+
+   ``bits``
+      The ``bits`` attribute is mandatory if the ``mode`` attribute is set to
+      ``emulate`` and specifies the virtual CPU address size in bits.
+
 Guest NUMA topology can be specified using the ``numa`` element. :since:`Since
 0.9.8`
 
Index: libvirt-8.0.0/docs/schemas/cputypes.rng
===================================================================
--- libvirt-8.0.0.orig/docs/schemas/cputypes.rng
+++ libvirt-8.0.0/docs/schemas/cputypes.rng
@@ -305,6 +305,22 @@
     </element>
   </define>
 
+  <define name="cpuMaxPhysAddr">
+    <element name="maxphysaddr">
+      <attribute name="mode">
+        <choice>
+          <value>emulate</value>
+          <value>passthrough</value>
+        </choice>
+      </attribute>
+      <optional>
+        <attribute name="bits">
+          <ref name="unsignedInt"/>
+        </attribute>
+      </optional>
+    </element>
+  </define>
+
   <define name="hostcpu">
     <element name="cpu">
       <element name="arch">
@@ -419,6 +435,9 @@
         <optional>
           <ref name="cpuCache"/>
         </optional>
+        <optional>
+          <ref name="cpuMaxPhysAddr"/>
+        </optional>
       </interleave>
     </element>
   </define>
Index: libvirt-8.0.0/src/conf/cpu_conf.c
===================================================================
--- libvirt-8.0.0.orig/src/conf/cpu_conf.c
+++ libvirt-8.0.0/src/conf/cpu_conf.c
@@ -84,6 +84,12 @@ VIR_ENUM_IMPL(virCPUCacheMode,
               "disable",
 );
 
+VIR_ENUM_IMPL(virCPUMaxPhysAddrMode,
+              VIR_CPU_MAX_PHYS_ADDR_MODE_LAST,
+              "emulate",
+              "passthrough",
+);
+
 
 virCPUDef *virCPUDefNew(void)
 {
@@ -129,6 +135,7 @@ virCPUDefFree(virCPUDef *def)
     if (g_atomic_int_dec_and_test(&def->refs)) {
         virCPUDefFreeModel(def);
         g_free(def->cache);
+        g_free(def->addr);
         g_free(def->tsc);
         g_free(def);
     }
@@ -251,6 +258,11 @@ virCPUDefCopyWithoutModel(const virCPUDe
         *copy->cache = *cpu->cache;
     }
 
+    if (cpu->addr) {
+        copy->addr = g_new0(virCPUMaxPhysAddrDef, 1);
+        *copy->addr = *cpu->addr;
+    }
+
     if (cpu->tsc) {
         copy->tsc = g_new0(virHostCPUTscInfo, 1);
         *copy->tsc = *cpu->tsc;
@@ -321,6 +333,7 @@ virCPUDefParseXML(xmlXPathContextPtr ctx
     g_autoptr(virCPUDef) def = NULL;
     g_autofree xmlNodePtr *nodes = NULL;
     xmlNodePtr topology = NULL;
+    xmlNodePtr maxphysaddrNode = NULL;
     VIR_XPATH_NODE_AUTORESTORE(ctxt)
     int n;
     size_t i;
@@ -644,6 +657,21 @@ virCPUDefParseXML(xmlXPathContextPtr ctx
         def->cache->mode = mode;
     }
 
+    if ((maxphysaddrNode = virXPathNode("./maxphysaddr[1]", ctxt))) {
+        def->addr = g_new0(virCPUMaxPhysAddrDef, 1);
+
+        if (virXMLPropEnum(maxphysaddrNode, "mode",
+                           virCPUMaxPhysAddrModeTypeFromString,
+                           VIR_XML_PROP_REQUIRED,
+                           &def->addr->mode) < 0)
+            return -1;
+
+        if (virXMLPropInt(maxphysaddrNode, "bits", 10,
+                          VIR_XML_PROP_NONNEGATIVE,
+                          &def->addr->bits, -1) < 0)
+            return -1;
+    }
+
     *cpu = g_steal_pointer(&def);
     return 0;
 }
@@ -803,6 +831,15 @@ virCPUDefFormatBuf(virBuffer *buf,
         virBufferAddLit(buf, "/>\n");
     }
 
+    if (def->addr) {
+        virBufferAddLit(buf, "<maxphysaddr ");
+        virBufferAsprintf(buf, "mode='%s'",
+                          virCPUMaxPhysAddrModeTypeToString(def->addr->mode));
+        if (def->addr->bits != -1)
+            virBufferAsprintf(buf, " bits='%d'", def->addr->bits);
+        virBufferAddLit(buf, "/>\n");
+    }
+
     for (i = 0; i < def->nfeatures; i++) {
         virCPUFeatureDef *feature = def->features + i;
 
@@ -1065,6 +1102,15 @@ virCPUDefIsEqual(virCPUDef *src,
         return false;
     }
 
+    if ((src->addr && !dst->addr) ||
+        (!src->addr && dst->addr) ||
+        (src->addr && dst->addr &&
+         (src->addr->mode != dst->addr->mode ||
+          src->addr->bits != dst->addr->bits))) {
+        MISMATCH("%s", _("Target CPU maxphysaddr does not match source"));
+        return false;
+    }
+
     if (src->nfeatures != dst->nfeatures) {
         MISMATCH(_("Target CPU feature count %zu does not match source %zu"),
                  dst->nfeatures, src->nfeatures);
Index: libvirt-8.0.0/src/conf/cpu_conf.h
===================================================================
--- libvirt-8.0.0.orig/src/conf/cpu_conf.h
+++ libvirt-8.0.0/src/conf/cpu_conf.h
@@ -117,6 +117,22 @@ struct _virCPUCacheDef {
 };
 
 
+typedef enum {
+    VIR_CPU_MAX_PHYS_ADDR_MODE_EMULATE,
+    VIR_CPU_MAX_PHYS_ADDR_MODE_PASSTHROUGH,
+
+    VIR_CPU_MAX_PHYS_ADDR_MODE_LAST
+} virCPUMaxPhysAddrMode;
+
+VIR_ENUM_DECL(virCPUMaxPhysAddrMode);
+
+typedef struct _virCPUMaxPhysAddrDef virCPUMaxPhysAddrDef;
+struct _virCPUMaxPhysAddrDef {
+    int bits;           /* -1 for unspecified */
+    virCPUMaxPhysAddrMode mode;
+};
+
+
 typedef struct _virCPUDef virCPUDef;
 struct _virCPUDef {
     int refs;
@@ -138,6 +154,7 @@ struct _virCPUDef {
     size_t nfeatures_max;
     virCPUFeatureDef *features;
     virCPUCacheDef *cache;
+    virCPUMaxPhysAddrDef *addr;
     virHostCPUTscInfo *tsc;
     virTristateSwitch migratable; /* for host-passthrough mode */
 };
Index: libvirt-8.0.0/src/libvirt_private.syms
===================================================================
--- libvirt-8.0.0.orig/src/libvirt_private.syms
+++ libvirt-8.0.0/src/libvirt_private.syms
@@ -120,6 +120,8 @@ virCPUDefParseXMLString;
 virCPUDefRef;
 virCPUDefStealModel;
 virCPUDefUpdateFeature;
+virCPUMaxPhysAddrModeTypeFromString;
+virCPUMaxPhysAddrModeTypeToString;
 virCPUModeTypeToString;
 
 
Index: libvirt-8.0.0/src/qemu/qemu_validate.c
===================================================================
--- libvirt-8.0.0.orig/src/qemu/qemu_validate.c
+++ libvirt-8.0.0/src/qemu/qemu_validate.c
@@ -340,6 +340,47 @@ qemuValidateDomainDefCpu(virQEMUDriver *
     if (!cpu)
         return 0;
 
+    if (cpu->addr) {
+        const virCPUMaxPhysAddrDef *addr = cpu->addr;
+
+        if (!ARCH_IS_X86(def->os.arch)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("CPU maximum physical address bits specification is not supported for '%s' architecture"),
+                           virArchToString(def->os.arch));
+            return -1;
+        }
+
+        switch (addr->mode) {
+        case VIR_CPU_MAX_PHYS_ADDR_MODE_PASSTHROUGH:
+            if (def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("CPU maximum physical address bits mode '%s' can only be used with '%s' CPUs"),
+                               virCPUMaxPhysAddrModeTypeToString(addr->mode),
+                               virCPUModeTypeToString(VIR_CPU_MODE_HOST_PASSTHROUGH));
+                return -1;
+            }
+            if (addr->bits != -1) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("CPU maximum physical address bits number specification cannot be used with mode='%s'"),
+                               virCPUMaxPhysAddrModeTypeToString(VIR_CPU_MAX_PHYS_ADDR_MODE_PASSTHROUGH));
+                return -1;
+            }
+            break;
+
+        case VIR_CPU_MAX_PHYS_ADDR_MODE_EMULATE:
+            if (addr->bits == -1) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("if using CPU maximum physical address mode='%s', bits= must be specified too"),
+                               virCPUMaxPhysAddrModeTypeToString(VIR_CPU_MAX_PHYS_ADDR_MODE_EMULATE));
+                return -1;
+            }
+            break;
+
+        case VIR_CPU_MAX_PHYS_ADDR_MODE_LAST:
+            break;
+        }
+    }
+
     if (!cpu->model && cpu->mode == VIR_CPU_MODE_CUSTOM)
         return 0;
 
Index: libvirt-8.0.0/tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml
===================================================================
--- /dev/null
+++ libvirt-8.0.0/tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml
@@ -0,0 +1,20 @@
+<domain type='kvm'>
+  <name>foo</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <cpu mode='host-passthrough'>
+    <maxphysaddr mode='emulate' bits='42'/>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+  </devices>
+</domain>
Index: libvirt-8.0.0/tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml
===================================================================
--- /dev/null
+++ libvirt-8.0.0/tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml
@@ -0,0 +1,20 @@
+<domain type='kvm'>
+  <name>foo</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <cpu mode='host-passthrough'>
+    <maxphysaddr mode='passthrough'/>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+  </devices>
+</domain>
Index: libvirt-8.0.0/tests/genericxml2xmltest.c
===================================================================
--- libvirt-8.0.0.orig/tests/genericxml2xmltest.c
+++ libvirt-8.0.0/tests/genericxml2xmltest.c
@@ -246,6 +246,8 @@ mymain(void)
 
     DO_TEST_BACKUP_FULL("backup-pull-internal-invalid", true);
 
+    DO_TEST("cpu-phys-bits-emulate");
+    DO_TEST("cpu-phys-bits-passthrough");
 
     virObjectUnref(caps);
     virObjectUnref(xmlopt);
openSUSE Build Service is sponsored by