On Thu, Oct 29, 2020 at 03:55:36PM +0000, Dario Faggioli wrote: > This patch introduces the: > > <maxphysaddr mode='passthrough'/> > <maxphysaddr mode='emulate' bits='42'/> > > sub element of /domain/cpu. That makes sense as a location. > > 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. I notice that QEMU recently (well in 2018) introduced a further option "host-phys-bits-limit". This says to use host phys bits, but cap it at a certain level. I don't see that this does anything that we can't already do with the existing "phys-bits" setting though - it merely automates the lookup of the host bits. So I don't think we particlarly need host-phys-bits-limit in libvirt. What I think we do want though is for the <capabilities> XML to report the host CPU's phys bits, so mgmt apps can query this and use it to decide on a suitable guest limit. We have ABIs for checking guest ABI compatibility, which should probably validate these new settings somewhree. > > 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); > > Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|