[PATCH V2 1/4] conf: Add support for specifying CPU max physical address size
Michal Prívozník
mprivozn at redhat.com
Wed Aug 3 15:29:13 UTC 2022
On 7/29/22 21:34, Jim Fehlig wrote:
> From: Dario Faggioli <dfaggioli at suse.com>
>
> 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 at suse.com>
> Signed-off-by: Jim Fehlig <jfehlig at suse.com>
> ---
> docs/formatdomain.rst | 23 ++++++++
> src/conf/cpu_conf.c | 54 +++++++++++++++++++
> src/conf/cpu_conf.h | 17 ++++++
> src/conf/schemas/cputypes.rng | 19 +++++++
> src/libvirt_private.syms | 2 +
> .../cpu-phys-bits-emulate.xml | 20 +++++++
> .../cpu-phys-bits-passthrough.xml | 20 +++++++
> tests/genericxml2xmltest.c | 3 ++
> 8 files changed, 158 insertions(+)
>
> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
> index 1ed969ac3e..adfdd7b7a5 100644
> --- a/docs/formatdomain.rst
> +++ b/docs/formatdomain.rst
> @@ -1336,6 +1336,7 @@ following collection of elements. :since:`Since 0.7.5`
> <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>
> ...
> @@ -1352,6 +1353,7 @@ following collection of elements. :since:`Since 0.7.5`
>
> <cpu mode='host-passthrough' migratable='off'>
> <cache mode='passthrough'/>
> + <maxphysaddr mode='passthrough'>
> <feature policy='disable' name='lahf_lm'/>
> ...
>
> @@ -1600,6 +1602,27 @@ In case no restrictions need to be put on CPU model and its features, a simpler
> 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`
>
> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
> index 8d80bbd842..e31c4ab467 100644
> --- a/src/conf/cpu_conf.c
> +++ b/src/conf/cpu_conf.c
> @@ -82,6 +82,12 @@ VIR_ENUM_IMPL(virCPUCacheMode,
> "disable",
> );
>
> +VIR_ENUM_IMPL(virCPUMaxPhysAddrMode,
> + VIR_CPU_MAX_PHYS_ADDR_MODE_LAST,
> + "emulate",
> + "passthrough",
> +);
> +
>
> virCPUDef *virCPUDefNew(void)
> {
> @@ -127,6 +133,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);
> }
> @@ -252,6 +259,11 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu)
> *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;
> @@ -644,6 +656,39 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
> def->cache->mode = mode;
> }
>
> + if (virXPathInt("count(./maxphysaddr)", ctxt, &n) < 0) {
> + return -1;
> + } else if (n > 1) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("at most one CPU maximum physical address bits "
> + "element may be specified"));
> + return -1;
> + } else if (n == 1) {
> + g_autofree char *strmode = NULL;
> + int mode;
> + int bits = -1;
> +
> + if (!(strmode = virXPathString("string(./maxphysaddr[1]/@mode)", ctxt)) ||
> + (mode = virCPUMaxPhysAddrModeTypeFromString(strmode)) < 0) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("missing or invalid CPU maximum physical "
> + "address bits mode"));
> + return -1;
> + }
> +
> + if (virXPathBoolean("boolean(./maxphysaddr[1]/@bits)", ctxt) == 1 &&
> + (virXPathInt("string(./maxphysaddr[1]/@bits)", ctxt, &bits) < 0 ||
> + bits < 0)) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("CPU maximum physical address bits < 0"));
> + return -1;
> + }
We have a bit better option here: virXMLProp*().
Which reminds me, the validation (which you put into PostParse callback
in patch 3/4) should be moved into this patch.
Therefore, I suggest squashing this in:
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
index e31c4ab467..d385d76e23 100644
--- a/src/conf/cpu_conf.c
+++ b/src/conf/cpu_conf.c
@@ -334,6 +334,7 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
g_autoptr(virCPUDef) def = NULL;
g_autofree xmlNodePtr *nodes = NULL;
xmlNodePtr topology = NULL;
+ xmlNodePtr maxphysaddrNode = NULL;
VIR_XPATH_NODE_AUTORESTORE(ctxt)
int n;
int rv;
@@ -656,37 +657,19 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
def->cache->mode = mode;
}
- if (virXPathInt("count(./maxphysaddr)", ctxt, &n) < 0) {
- return -1;
- } else if (n > 1) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("at most one CPU maximum physical address bits "
- "element may be specified"));
- return -1;
- } else if (n == 1) {
- g_autofree char *strmode = NULL;
- int mode;
- int bits = -1;
-
- if (!(strmode = virXPathString("string(./maxphysaddr[1]/@mode)", ctxt)) ||
- (mode = virCPUMaxPhysAddrModeTypeFromString(strmode)) < 0) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("missing or invalid CPU maximum physical "
- "address bits mode"));
- return -1;
- }
-
- if (virXPathBoolean("boolean(./maxphysaddr[1]/@bits)", ctxt) == 1 &&
- (virXPathInt("string(./maxphysaddr[1]/@bits)", ctxt, &bits) < 0 ||
- bits < 0)) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("CPU maximum physical address bits < 0"));
- return -1;
- }
-
+ if ((maxphysaddrNode = virXPathNode("./maxphysaddr[1]", ctxt))) {
def->addr = g_new0(virCPUMaxPhysAddrDef, 1);
- def->addr->bits = bits;
- def->addr->mode = mode;
+
+ 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);
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 7fa899e411..36e236f08e 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -332,6 +332,47 @@ qemuValidateDomainDefCpu(virQEMUDriver *driver,
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 (def->cpu->cache) {
virCPUCacheDef *cache = def->cpu->cache;
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index bbe0d02226..3501eadf55 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -249,7 +249,6 @@ mymain(void)
DO_TEST("cpu-phys-bits-emulate");
DO_TEST("cpu-phys-bits-passthrough");
-
virObjectUnref(caps);
virObjectUnref(xmlopt);
Michal
More information about the libvir-list
mailing list