This patch introduces the: <maxphysaddr mode='passthrough'/> <maxphysaddr mode='emulate' bits='42'/> sub element of /domain/cpu. Purpose is being able to have a guest see the physical address size exactly as the host does (if mode='passthrough' is used) or any size the user wants it to see (if mode='emulate' is used and bits='' is specified). This can be useful if the VM needs to have a large amount of memory. Signed-off-by: Dario Faggioli <dfaggioli@xxxxxxxx> --- docs/formatdomain.rst | 21 ++++++++ docs/schemas/cputypes.rng | 19 +++++++ src/conf/cpu_conf.c | 52 ++++++++++++++++++++ src/conf/cpu_conf.h | 17 +++++++ src/libvirt_private.syms | 2 + .../genericxml2xmlindata/cpu-phys-bits-emulate.xml | 20 ++++++++ .../cpu-phys-bits-passthrough.xml | 20 ++++++++ tests/genericxml2xmltest.c | 3 + 8 files changed, 154 insertions(+) create mode 100644 tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml create mode 100644 tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index ae635bedff..851391011f 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1207,6 +1207,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> ... @@ -1223,6 +1224,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'/> ... @@ -1446,6 +1448,25 @@ 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). +``maxphysaddress`` + :since:`Since 6.10.0` the ``maxphysaddr`` element specifies the size in bits + of the physical addresses. The default behavior is that the vCPUs will see + what it is configured by default in the hypervisor itself. + + ``mode`` + The following values 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`` arrtibute, which is mandatory. + + ``bits`` + The number of bits of the physical addresses that the vCPUs should see, + if the ``mode`` attribute is set to ``emulate``. + Guest NUMA topology can be specified using the ``numa`` element. :since:`Since 0.9.8` diff --git a/docs/schemas/cputypes.rng b/docs/schemas/cputypes.rng index aea6ff0267..232115226a 100644 --- a/docs/schemas/cputypes.rng +++ b/docs/schemas/cputypes.rng @@ -299,6 +299,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"> @@ -410,6 +426,9 @@ <optional> <ref name="cpuCache"/> </optional> + <optional> + <ref name="cpuMaxPhysAddr"/> + </optional> </interleave> </element> </define> diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 7778e01131..a151bbf45b 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -83,6 +83,11 @@ VIR_ENUM_IMPL(virCPUCacheMode, "disable", ); +VIR_ENUM_IMPL(virCPUMaxPhysAddrMode, + VIR_CPU_MAX_PHYS_ADDR_MODE_LAST, + "emulate", + "passthrough", +); virCPUDefPtr virCPUDefNew(void) { @@ -128,6 +133,7 @@ virCPUDefFree(virCPUDefPtr def) if (g_atomic_int_dec_and_test(&def->refs)) { virCPUDefFreeModel(def); VIR_FREE(def->cache); + VIR_FREE(def->addr); VIR_FREE(def->tsc); VIR_FREE(def); } @@ -250,6 +256,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; @@ -670,6 +681,38 @@ 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) { + int bits = -1; + g_autofree char *strmode = NULL; + int mode; + + 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 (!(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; + } + + def->addr = g_new0(virCPUMaxPhysAddrDef, 1); + def->addr->bits = bits; + def->addr->mode = mode; + } *cpu = g_steal_pointer(&def); return 0; } @@ -841,6 +884,15 @@ virCPUDefFormatBuf(virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } + if (def->addr) { + virBufferAddLit(buf, "<maxphysaddr "); + if (def->addr->bits != -1) + virBufferAsprintf(buf, "bits='%d' ", def->addr->bits); + virBufferAsprintf(buf, "mode='%s'", + virCPUMaxPhysAddrModeTypeToString(def->addr->mode)); + virBufferAddLit(buf, "/>\n"); + } + for (i = 0; i < def->nfeatures; i++) { virCPUFeatureDefPtr feature = def->features + i; diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index 3ef14b7932..e7bbe916a3 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -117,6 +117,22 @@ struct _virCPUCacheDef { virCPUCacheMode mode; }; +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; +typedef virCPUMaxPhysAddrDef *virCPUMaxPhysAddrDefPtr; +struct _virCPUMaxPhysAddrDef { + int bits; /* -1 for unspecified */ + virCPUMaxPhysAddrMode mode; +}; + typedef struct _virCPUDef virCPUDef; typedef virCPUDef *virCPUDefPtr; @@ -140,6 +156,7 @@ struct _virCPUDef { size_t nfeatures_max; virCPUFeatureDefPtr features; virCPUCacheDefPtr cache; + virCPUMaxPhysAddrDefPtr addr; virHostCPUTscInfoPtr tsc; virTristateSwitch migratable; /* for host-passthrough mode */ }; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 95e50835ad..8629f81d33 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -117,6 +117,8 @@ virCPUDefParseXMLString; virCPUDefRef; virCPUDefStealModel; virCPUDefUpdateFeature; +virCPUMaxPhysAddrModeTypeFromString; +virCPUMaxPhysAddrModeTypeToString; virCPUModeTypeToString; diff --git a/tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml b/tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml new file mode 100644 index 0000000000..0b1b0f1672 --- /dev/null +++ b/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 bits='42' mode='emulate'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + </devices> +</domain> diff --git a/tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml b/tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml new file mode 100644 index 0000000000..cce676eaa6 --- /dev/null +++ b/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> diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c index 5110bfba86..6c1c6e699f 100644 --- a/tests/genericxml2xmltest.c +++ b/tests/genericxml2xmltest.c @@ -256,6 +256,9 @@ 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);