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);