The patch adds <cpu> element to domain capabilities XML: <cpu> <mode name='host-passthrough' supported='yes'/> <mode name='host-model' supported='yes'/> <mode name='custom' supported='yes'> <model>Broadwell</model> <model>Broadwell-noTSX</model> ... </mode> </cpu> Applications can use it to inspect what CPU configuration modes are supported for a specific combination of domain type, emulator binary, guest architecture and machine type. Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> --- docs/formatdomaincaps.html.in | 44 ++++++ docs/schemas/domaincaps.rng | 43 ++++++ src/conf/domain_capabilities.c | 150 +++++++++++++++++++++ src/conf/domain_capabilities.h | 33 +++++ src/libvirt_private.syms | 4 + tests/domaincapsschemadata/basic.xml | 5 + tests/domaincapsschemadata/full.xml | 9 ++ tests/domaincapsschemadata/libxl-xenfv-usb.xml | 5 + tests/domaincapsschemadata/libxl-xenfv.xml | 5 + tests/domaincapsschemadata/libxl-xenpv-usb.xml | 5 + tests/domaincapsschemadata/libxl-xenpv.xml | 5 + tests/domaincapsschemadata/qemu_1.7.0.x86_64.xml | 5 + .../qemu_2.6.0-gicv2-virt.aarch64.xml | 5 + .../qemu_2.6.0-gicv3-virt.aarch64.xml | 5 + tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml | 5 + tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml | 5 + tests/domaincapsschemadata/qemu_2.6.0.x86_64.xml | 5 + tests/domaincapstest.c | 9 ++ 18 files changed, 347 insertions(+) diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in index d5a8414..15a13c1 100644 --- a/docs/formatdomaincaps.html.in +++ b/docs/formatdomaincaps.html.in @@ -142,6 +142,50 @@ <loader/> element.</dd> </dl> + <h3><a name="elementsCPU">CPU configuration</a></h3> + + <p> + The <code>cpu</code> element exposes options usable for configuring + guest CPU. + </p> + +<pre> +<domainCapabilities> + ... + <cpu> + <mode name='host-passthrough' supported='yes'/> + <mode name='host-model' supported='yes'/> + <mode name='custom' supported='yes'> + <model>Broadwell</model> + <model>Broadwell-noTSX</model> + <model>Haswell</model> + ... + </mode> + </cpu> + ... +<domainCapabilities> +</pre> + + <p> + Each CPU mode understood by libvirt is described with a + <code>mode</code> element which tells whether the particular mode + is supported and provides (when applicable) more details about it: + </p> + + <dl> + <dt><code>host-passthrough</code></dt> + <dd>No mode specific details are provided.</dd> + + <dt><code>host-model</code></dt> + <dd>No mode specific details are provided yet.</dd> + + <dt><code>custom</code></dt> + <dd> + The <code>mode</code> element contains a list of supported CPU + models, each described by a dedicated <code>model</code> element. + </dd> + </dl> + <h3><a name="elementsDevices">Devices</a></h3> <p> diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng index 97da41f..9f3d225 100644 --- a/docs/schemas/domaincaps.rng +++ b/docs/schemas/domaincaps.rng @@ -29,6 +29,9 @@ <ref name='os'/> </optional> <optional> + <ref name='cpu'/> + </optional> + <optional> <ref name='devices'/> </optional> <optional> @@ -68,6 +71,46 @@ </element> </define> + <define name='cpu'> + <element name='cpu'> + <ref name='cpuHost'/> + <ref name='cpuHostModel'/> + <ref name='cpuCustom'/> + </element> + </define> + + <define name='cpuHost'> + <element name='mode'> + <attribute name='name'> + <value>host-passthrough</value> + </attribute> + <ref name='supported'/> + </element> + </define> + + <define name='cpuHostModel'> + <element name='mode'> + <attribute name='name'> + <value>host-model</value> + </attribute> + <ref name='supported'/> + </element> + </define> + + <define name='cpuCustom'> + <element name='mode'> + <attribute name='name'> + <value>custom</value> + </attribute> + <ref name='supported'/> + <zeroOrMore> + <element name='model'> + <text/> + </element> + </zeroOrMore> + </element> + </define> + <define name='devices'> <element name='devices'> <interleave> diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 1676f0e..c07f995 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -30,8 +30,10 @@ #define VIR_FROM_THIS VIR_FROM_CAPABILITIES static virClassPtr virDomainCapsClass; +static virClassPtr virDomainCapsCPUModelsClass; static void virDomainCapsDispose(void *obj); +static void virDomainCapsCPUModelsDispose(void *obj); static int virDomainCapsOnceInit(void) { @@ -40,6 +42,14 @@ static int virDomainCapsOnceInit(void) sizeof(virDomainCaps), virDomainCapsDispose))) return -1; + + virDomainCapsCPUModelsClass = virClassNew(virClassForObject(), + "virDomainCapsCPUModelsClass", + sizeof(virDomainCapsCPUModels), + virDomainCapsCPUModelsDispose); + if (!virDomainCapsCPUModelsClass) + return -1; + return 0; } @@ -68,11 +78,25 @@ virDomainCapsDispose(void *obj) VIR_FREE(caps->path); VIR_FREE(caps->machine); + virObjectUnref(caps->cpu.custom); virDomainCapsStringValuesFree(&caps->os.loader.values); } +static void +virDomainCapsCPUModelsDispose(void *obj) +{ + virDomainCapsCPUModelsPtr cpuModels = obj; + size_t i; + + for (i = 0; i < cpuModels->count; i++) + VIR_FREE(cpuModels->models[i].name); + + VIR_FREE(cpuModels->models); +} + + virDomainCapsPtr virDomainCapsNew(const char *path, const char *machine, @@ -100,6 +124,86 @@ virDomainCapsNew(const char *path, } +virDomainCapsCPUModelsPtr +virDomainCapsCPUModelsNew(size_t nmodels) +{ + virDomainCapsCPUModelsPtr cpuModels = NULL; + + if (virDomainCapsInitialize() < 0) + return NULL; + + if (!(cpuModels = virObjectNew(virDomainCapsCPUModelsClass))) + return NULL; + + if (VIR_ALLOC_N(cpuModels->models, nmodels) < 0) + goto error; + cpuModels->alloc = nmodels; + + return cpuModels; + + error: + virObjectUnref(cpuModels); + return NULL; +} + + +virDomainCapsCPUModelsPtr +virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr old) +{ + virDomainCapsCPUModelsPtr cpuModels; + size_t i; + + if (!(cpuModels = virDomainCapsCPUModelsNew(old->count))) + return NULL; + + for (i = 0; i < old->count; i++) { + if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, -1) < 0) + goto error; + } + + return cpuModels; + + error: + virObjectUnref(cpuModels); + return NULL; +} + + +int +virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, + char **name) +{ + if (VIR_RESIZE_N(cpuModels->models, cpuModels->alloc, + cpuModels->count, 1) < 0) + return -1; + + cpuModels->models[cpuModels->count++].name = *name; + *name = NULL; + return 0; +} + + +int +virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, + const char *name, + ssize_t nameLen) +{ + char *copy = NULL; + + if (VIR_STRNDUP(copy, name, nameLen) < 0) + goto error; + + if (virDomainCapsCPUModelsAddSteal(cpuModels, ©) < 0) + goto error; + + return 0; + + error: + VIR_FREE(copy); + return -1; +} + + int virDomainCapsEnumSet(virDomainCapsEnumPtr capsEnum, const char *capsEnumName, @@ -234,6 +338,51 @@ virDomainCapsOSFormat(virBufferPtr buf, } static void +virDomainCapsCPUCustomFormat(virBufferPtr buf, + virDomainCapsCPUModelsPtr custom) +{ + size_t i; + + virBufferAdjustIndent(buf, 2); + + for (i = 0; i < custom->count; i++) { + virBufferAsprintf(buf, "<model>%s</model>\n", + custom->models[i].name); + } + + virBufferAdjustIndent(buf, -2); +} + +static void +virDomainCapsCPUFormat(virBufferPtr buf, + virDomainCapsCPUPtr cpu) +{ + virBufferAddLit(buf, "<cpu>\n"); + virBufferAdjustIndent(buf, 2); + + virBufferAsprintf(buf, "<mode name='%s' supported='%s'/>\n", + virCPUModeTypeToString(VIR_CPU_MODE_HOST_PASSTHROUGH), + cpu->hostPassthrough ? "yes" : "no"); + + virBufferAsprintf(buf, "<mode name='%s' supported='%s'/>\n", + virCPUModeTypeToString(VIR_CPU_MODE_HOST_MODEL), + cpu->hostModel ? "yes" : "no"); + + virBufferAsprintf(buf, "<mode name='%s' ", + virCPUModeTypeToString(VIR_CPU_MODE_CUSTOM)); + if (cpu->custom && cpu->custom->count) { + virBufferAddLit(buf, "supported='yes'>\n"); + virDomainCapsCPUCustomFormat(buf, cpu->custom); + virBufferAddLit(buf, "</mode>\n"); + } else { + virBufferAddLit(buf, "supported='no'/>\n"); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</cpu>\n"); +} + +static void virDomainCapsDeviceDiskFormat(virBufferPtr buf, virDomainCapsDeviceDiskPtr const disk) { @@ -333,6 +482,7 @@ virDomainCapsFormatInternal(virBufferPtr buf, virBufferAsprintf(buf, "<vcpu max='%d'/>\n", caps->maxvcpus); virDomainCapsOSFormat(buf, &caps->os); + virDomainCapsCPUFormat(buf, &caps->cpu); virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2); diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 492a9cf..509c306 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -102,6 +102,30 @@ struct _virDomainCapsFeatureGIC { virDomainCapsEnum version; /* Info about virGICVersion */ }; +typedef struct _virDomainCapsCPUModel virDomainCapsCPUModel; +typedef virDomainCapsCPUModel *virDomainCapsCPUModelPtr; +struct _virDomainCapsCPUModel { + char *name; +}; + +typedef struct _virDomainCapsCPUModels virDomainCapsCPUModels; +typedef virDomainCapsCPUModels *virDomainCapsCPUModelsPtr; +struct _virDomainCapsCPUModels { + virObject parent; + + size_t alloc; + size_t count; + virDomainCapsCPUModelPtr models; +}; + +typedef struct _virDomainCapsCPU virDomainCapsCPU; +typedef virDomainCapsCPU *virDomainCapsCPUPtr; +struct _virDomainCapsCPU { + bool hostPassthrough; + bool hostModel; + virDomainCapsCPUModelsPtr custom; +}; + struct _virDomainCaps { virObjectLockable parent; @@ -114,6 +138,7 @@ struct _virDomainCaps { int maxvcpus; virDomainCapsOS os; + virDomainCapsCPU cpu; virDomainCapsDeviceDisk disk; virDomainCapsDeviceGraphics graphics; virDomainCapsDeviceVideo video; @@ -129,6 +154,14 @@ virDomainCapsPtr virDomainCapsNew(const char *path, virArch arch, virDomainVirtType virttype); +virDomainCapsCPUModelsPtr virDomainCapsCPUModelsNew(size_t nmodels); +virDomainCapsCPUModelsPtr virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr old); +int virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, + char **name); +int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, + const char *name, + ssize_t nameLen); + # define VIR_DOMAIN_CAPS_ENUM_SET(capsEnum, ...) \ do { \ unsigned int __values[] = {__VA_ARGS__}; \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 419c33d..f91ce17 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -152,6 +152,10 @@ virDomainAuditVcpu; # conf/domain_capabilities.h +virDomainCapsCPUModelsAdd; +virDomainCapsCPUModelsAddSteal; +virDomainCapsCPUModelsCopy; +virDomainCapsCPUModelsNew; virDomainCapsEnumClear; virDomainCapsEnumSet; virDomainCapsFormat; diff --git a/tests/domaincapsschemadata/basic.xml b/tests/domaincapsschemadata/basic.xml index 5513f99..6b788d9 100644 --- a/tests/domaincapsschemadata/basic.xml +++ b/tests/domaincapsschemadata/basic.xml @@ -4,6 +4,11 @@ <machine>my-machine-type</machine> <arch>x86_64</arch> <os supported='no'/> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='no'/> <graphics supported='no'/> diff --git a/tests/domaincapsschemadata/full.xml b/tests/domaincapsschemadata/full.xml index 2f529ff..80fd1f0 100644 --- a/tests/domaincapsschemadata/full.xml +++ b/tests/domaincapsschemadata/full.xml @@ -19,6 +19,15 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='yes'/> + <mode name='host-model' supported='yes'/> + <mode name='custom' supported='yes'> + <model>Model1</model> + <model>Model2</model> + <model>Model3</model> + </mode> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/libxl-xenfv-usb.xml b/tests/domaincapsschemadata/libxl-xenfv-usb.xml index c071d12..6a9e3d9 100644 --- a/tests/domaincapsschemadata/libxl-xenfv-usb.xml +++ b/tests/domaincapsschemadata/libxl-xenfv-usb.xml @@ -17,6 +17,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/libxl-xenfv.xml b/tests/domaincapsschemadata/libxl-xenfv.xml index 9436ef8..d48e699 100644 --- a/tests/domaincapsschemadata/libxl-xenfv.xml +++ b/tests/domaincapsschemadata/libxl-xenfv.xml @@ -17,6 +17,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/libxl-xenpv-usb.xml b/tests/domaincapsschemadata/libxl-xenpv-usb.xml index 4dd07bd..d1a3918 100644 --- a/tests/domaincapsschemadata/libxl-xenpv-usb.xml +++ b/tests/domaincapsschemadata/libxl-xenpv-usb.xml @@ -7,6 +7,11 @@ <os supported='yes'> <loader supported='no'/> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/libxl-xenpv.xml b/tests/domaincapsschemadata/libxl-xenpv.xml index ab00a28..c0e3193 100644 --- a/tests/domaincapsschemadata/libxl-xenpv.xml +++ b/tests/domaincapsschemadata/libxl-xenpv.xml @@ -7,6 +7,11 @@ <os supported='yes'> <loader supported='no'/> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/qemu_1.7.0.x86_64.xml b/tests/domaincapsschemadata/qemu_1.7.0.x86_64.xml index 161d0ab..6da28b0 100644 --- a/tests/domaincapsschemadata/qemu_1.7.0.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_1.7.0.x86_64.xml @@ -18,6 +18,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/qemu_2.6.0-gicv2-virt.aarch64.xml b/tests/domaincapsschemadata/qemu_2.6.0-gicv2-virt.aarch64.xml index f5f0f1c..ee51684 100644 --- a/tests/domaincapsschemadata/qemu_2.6.0-gicv2-virt.aarch64.xml +++ b/tests/domaincapsschemadata/qemu_2.6.0-gicv2-virt.aarch64.xml @@ -18,6 +18,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/qemu_2.6.0-gicv3-virt.aarch64.xml b/tests/domaincapsschemadata/qemu_2.6.0-gicv3-virt.aarch64.xml index 1ae8172..88cced9 100644 --- a/tests/domaincapsschemadata/qemu_2.6.0-gicv3-virt.aarch64.xml +++ b/tests/domaincapsschemadata/qemu_2.6.0-gicv3-virt.aarch64.xml @@ -18,6 +18,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml b/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml index 4e87cd2..09c0e1c 100644 --- a/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml +++ b/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml @@ -18,6 +18,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml b/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml index 583fdf0..40b255e 100644 --- a/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml +++ b/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml @@ -18,6 +18,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapsschemadata/qemu_2.6.0.x86_64.xml b/tests/domaincapsschemadata/qemu_2.6.0.x86_64.xml index c453ce3..6706fec 100644 --- a/tests/domaincapsschemadata/qemu_2.6.0.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_2.6.0.x86_64.xml @@ -18,6 +18,11 @@ </enum> </loader> </os> + <cpu> + <mode name='host-passthrough' supported='no'/> + <mode name='host-model' supported='no'/> + <mode name='custom' supported='no'/> + </cpu> <devices> <disk supported='yes'> <enum name='diskDevice'> diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 5b7b7d0..907c0ad 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -60,6 +60,7 @@ fillAllCaps(virDomainCapsPtr domCaps) { virDomainCapsOSPtr os = &domCaps->os; virDomainCapsLoaderPtr loader = &os->loader; + virDomainCapsCPUPtr cpu = &domCaps->cpu; virDomainCapsDeviceDiskPtr disk = &domCaps->disk; virDomainCapsDeviceGraphicsPtr graphics = &domCaps->graphics; virDomainCapsDeviceVideoPtr video = &domCaps->video; @@ -77,6 +78,14 @@ fillAllCaps(virDomainCapsPtr domCaps) NULL) < 0) return -1; + cpu->hostPassthrough = true; + cpu->hostModel = true; + if (!(cpu->custom = virDomainCapsCPUModelsNew(3)) || + virDomainCapsCPUModelsAdd(cpu->custom, "Model1", -1) < 0 || + virDomainCapsCPUModelsAdd(cpu->custom, "Model2", -1) < 0 || + virDomainCapsCPUModelsAdd(cpu->custom, "Model3", -1) < 0) + return -1; + disk->supported = true; SET_ALL_BITS(disk->diskDevice); SET_ALL_BITS(disk->bus); -- 2.9.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list