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>
This commit is contained in:
Dario Faggioli 2022-07-29 13:34:33 -06:00 committed by Michal Privoznik
parent 67b03faaf1
commit e6c29f09e5
9 changed files with 190 additions and 0 deletions

View File

@ -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`

View File

@ -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;
@ -322,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;
@ -644,6 +657,21 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
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;
}
@ -811,6 +839,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;
@ -1073,6 +1110,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);

View File

@ -116,6 +116,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;
@ -140,6 +156,7 @@ struct _virCPUDef {
size_t nfeatures_max;
virCPUFeatureDef *features;
virCPUCacheDef *cache;
virCPUMaxPhysAddrDef *addr;
virHostCPUTscInfo *tsc;
virTristateSwitch migratable; /* for host-passthrough mode */
};

View File

@ -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">
@ -432,6 +448,9 @@
<optional>
<ref name="cpuCache"/>
</optional>
<optional>
<ref name="cpuMaxPhysAddr"/>
</optional>
</interleave>
</element>
</define>

View File

@ -120,6 +120,8 @@ virCPUDefParseXMLString;
virCPUDefRef;
virCPUDefStealModel;
virCPUDefUpdateFeature;
virCPUMaxPhysAddrModeTypeFromString;
virCPUMaxPhysAddrModeTypeToString;
virCPUModeTypeToString;

View File

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

View File

@ -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>

View File

@ -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>

View File

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