mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
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:
parent
67b03faaf1
commit
e6c29f09e5
@ -1336,6 +1336,7 @@ following collection of elements. :since:`Since 0.7.5`
|
|||||||
<vendor>Intel</vendor>
|
<vendor>Intel</vendor>
|
||||||
<topology sockets='1' dies='1' cores='2' threads='1'/>
|
<topology sockets='1' dies='1' cores='2' threads='1'/>
|
||||||
<cache level='3' mode='emulate'/>
|
<cache level='3' mode='emulate'/>
|
||||||
|
<maxphysaddr mode='emulate' bits='42'>
|
||||||
<feature policy='disable' name='lahf_lm'/>
|
<feature policy='disable' name='lahf_lm'/>
|
||||||
</cpu>
|
</cpu>
|
||||||
...
|
...
|
||||||
@ -1352,6 +1353,7 @@ following collection of elements. :since:`Since 0.7.5`
|
|||||||
|
|
||||||
<cpu mode='host-passthrough' migratable='off'>
|
<cpu mode='host-passthrough' migratable='off'>
|
||||||
<cache mode='passthrough'/>
|
<cache mode='passthrough'/>
|
||||||
|
<maxphysaddr mode='passthrough'>
|
||||||
<feature policy='disable' name='lahf_lm'/>
|
<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
|
The virtual CPU will report no CPU cache of the specified level (or no
|
||||||
cache at all if the ``level`` attribute is missing).
|
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
|
Guest NUMA topology can be specified using the ``numa`` element. :since:`Since
|
||||||
0.9.8`
|
0.9.8`
|
||||||
|
|
||||||
|
@ -82,6 +82,12 @@ VIR_ENUM_IMPL(virCPUCacheMode,
|
|||||||
"disable",
|
"disable",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VIR_ENUM_IMPL(virCPUMaxPhysAddrMode,
|
||||||
|
VIR_CPU_MAX_PHYS_ADDR_MODE_LAST,
|
||||||
|
"emulate",
|
||||||
|
"passthrough",
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
virCPUDef *virCPUDefNew(void)
|
virCPUDef *virCPUDefNew(void)
|
||||||
{
|
{
|
||||||
@ -127,6 +133,7 @@ virCPUDefFree(virCPUDef *def)
|
|||||||
if (g_atomic_int_dec_and_test(&def->refs)) {
|
if (g_atomic_int_dec_and_test(&def->refs)) {
|
||||||
virCPUDefFreeModel(def);
|
virCPUDefFreeModel(def);
|
||||||
g_free(def->cache);
|
g_free(def->cache);
|
||||||
|
g_free(def->addr);
|
||||||
g_free(def->tsc);
|
g_free(def->tsc);
|
||||||
g_free(def);
|
g_free(def);
|
||||||
}
|
}
|
||||||
@ -252,6 +259,11 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu)
|
|||||||
*copy->cache = *cpu->cache;
|
*copy->cache = *cpu->cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpu->addr) {
|
||||||
|
copy->addr = g_new0(virCPUMaxPhysAddrDef, 1);
|
||||||
|
*copy->addr = *cpu->addr;
|
||||||
|
}
|
||||||
|
|
||||||
if (cpu->tsc) {
|
if (cpu->tsc) {
|
||||||
copy->tsc = g_new0(virHostCPUTscInfo, 1);
|
copy->tsc = g_new0(virHostCPUTscInfo, 1);
|
||||||
*copy->tsc = *cpu->tsc;
|
*copy->tsc = *cpu->tsc;
|
||||||
@ -322,6 +334,7 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
|
|||||||
g_autoptr(virCPUDef) def = NULL;
|
g_autoptr(virCPUDef) def = NULL;
|
||||||
g_autofree xmlNodePtr *nodes = NULL;
|
g_autofree xmlNodePtr *nodes = NULL;
|
||||||
xmlNodePtr topology = NULL;
|
xmlNodePtr topology = NULL;
|
||||||
|
xmlNodePtr maxphysaddrNode = NULL;
|
||||||
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
VIR_XPATH_NODE_AUTORESTORE(ctxt)
|
||||||
int n;
|
int n;
|
||||||
int rv;
|
int rv;
|
||||||
@ -644,6 +657,21 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
|
|||||||
def->cache->mode = mode;
|
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);
|
*cpu = g_steal_pointer(&def);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -811,6 +839,15 @@ virCPUDefFormatBuf(virBuffer *buf,
|
|||||||
virBufferAddLit(buf, "/>\n");
|
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++) {
|
for (i = 0; i < def->nfeatures; i++) {
|
||||||
virCPUFeatureDef *feature = def->features + i;
|
virCPUFeatureDef *feature = def->features + i;
|
||||||
|
|
||||||
@ -1073,6 +1110,15 @@ virCPUDefIsEqual(virCPUDef *src,
|
|||||||
return false;
|
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) {
|
if (src->nfeatures != dst->nfeatures) {
|
||||||
MISMATCH(_("Target CPU feature count %zu does not match source %zu"),
|
MISMATCH(_("Target CPU feature count %zu does not match source %zu"),
|
||||||
dst->nfeatures, src->nfeatures);
|
dst->nfeatures, src->nfeatures);
|
||||||
|
@ -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;
|
typedef struct _virCPUDef virCPUDef;
|
||||||
struct _virCPUDef {
|
struct _virCPUDef {
|
||||||
int refs;
|
int refs;
|
||||||
@ -140,6 +156,7 @@ struct _virCPUDef {
|
|||||||
size_t nfeatures_max;
|
size_t nfeatures_max;
|
||||||
virCPUFeatureDef *features;
|
virCPUFeatureDef *features;
|
||||||
virCPUCacheDef *cache;
|
virCPUCacheDef *cache;
|
||||||
|
virCPUMaxPhysAddrDef *addr;
|
||||||
virHostCPUTscInfo *tsc;
|
virHostCPUTscInfo *tsc;
|
||||||
virTristateSwitch migratable; /* for host-passthrough mode */
|
virTristateSwitch migratable; /* for host-passthrough mode */
|
||||||
};
|
};
|
||||||
|
@ -305,6 +305,22 @@
|
|||||||
</element>
|
</element>
|
||||||
</define>
|
</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">
|
<define name="hostcpu">
|
||||||
<element name="cpu">
|
<element name="cpu">
|
||||||
<element name="arch">
|
<element name="arch">
|
||||||
@ -432,6 +448,9 @@
|
|||||||
<optional>
|
<optional>
|
||||||
<ref name="cpuCache"/>
|
<ref name="cpuCache"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="cpuMaxPhysAddr"/>
|
||||||
|
</optional>
|
||||||
</interleave>
|
</interleave>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
@ -120,6 +120,8 @@ virCPUDefParseXMLString;
|
|||||||
virCPUDefRef;
|
virCPUDefRef;
|
||||||
virCPUDefStealModel;
|
virCPUDefStealModel;
|
||||||
virCPUDefUpdateFeature;
|
virCPUDefUpdateFeature;
|
||||||
|
virCPUMaxPhysAddrModeTypeFromString;
|
||||||
|
virCPUMaxPhysAddrModeTypeToString;
|
||||||
virCPUModeTypeToString;
|
virCPUModeTypeToString;
|
||||||
|
|
||||||
|
|
||||||
|
@ -332,6 +332,47 @@ qemuValidateDomainDefCpu(virQEMUDriver *driver,
|
|||||||
if (!cpu)
|
if (!cpu)
|
||||||
return 0;
|
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) {
|
if (def->cpu->cache) {
|
||||||
virCPUCacheDef *cache = def->cpu->cache;
|
virCPUCacheDef *cache = def->cpu->cache;
|
||||||
|
|
||||||
|
20
tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml
Normal file
20
tests/genericxml2xmlindata/cpu-phys-bits-emulate.xml
Normal 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>
|
20
tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml
Normal file
20
tests/genericxml2xmlindata/cpu-phys-bits-passthrough.xml
Normal 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>
|
@ -246,6 +246,8 @@ mymain(void)
|
|||||||
|
|
||||||
DO_TEST_BACKUP_FULL("backup-pull-internal-invalid", true);
|
DO_TEST_BACKUP_FULL("backup-pull-internal-invalid", true);
|
||||||
|
|
||||||
|
DO_TEST("cpu-phys-bits-emulate");
|
||||||
|
DO_TEST("cpu-phys-bits-passthrough");
|
||||||
|
|
||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
virObjectUnref(xmlopt);
|
virObjectUnref(xmlopt);
|
||||||
|
Loading…
Reference in New Issue
Block a user