From 167280e7f639461de5eb35872dca4d3a62cff7ff Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Fri, 22 Apr 2016 11:08:57 +0200 Subject: [PATCH] domcaps: Add support for listing supported CPU models The patch adds element to domain capabilities XML: Broadwell Broadwell-noTSX ... 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 --- docs/formatdomaincaps.html.in | 44 ++++++ docs/schemas/domaincaps.rng | 43 +++++ src/conf/domain_capabilities.c | 149 ++++++++++++++++++ src/conf/domain_capabilities.h | 33 ++++ src/libvirt_private.syms | 4 + tests/domaincapsschemadata/basic.xml | 5 + tests/domaincapsschemadata/full.xml | 9 ++ .../domaincapsschemadata/libxl-xenfv-usb.xml | 5 + tests/domaincapsschemadata/libxl-xenfv.xml | 5 + .../domaincapsschemadata/libxl-xenpv-usb.xml | 5 + tests/domaincapsschemadata/libxl-xenpv.xml | 5 + .../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 + .../qemu_2.6.0.aarch64.xml | 5 + .../qemu_2.6.0.ppc64le.xml | 5 + .../qemu_2.6.0.x86_64.xml | 5 + tests/domaincapstest.c | 9 ++ 18 files changed, 346 insertions(+) diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in index d5a8414aa4..ce43658e06 100644 --- a/docs/formatdomaincaps.html.in +++ b/docs/formatdomaincaps.html.in @@ -142,6 +142,50 @@ <loader/> element. +

CPU configuration

+ +

+ The cpu element exposes options usable for configuring + guest CPUs. +

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

+ Each CPU mode understood by libvirt is described with a + mode element which tells whether the particular mode + is supported and provides (when applicable) more details about it: +

+ +
+
host-passthrough
+
No mode specific details are provided.
+ +
host-model
+
No mode specific details are provided yet.
+ +
custom
+
+ The mode element contains a list of supported CPU + models, each described by a dedicated model element. +
+
+

Devices

diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng index 97da41f533..9f3d225b5e 100644 --- a/docs/schemas/domaincaps.rng +++ b/docs/schemas/domaincaps.rng @@ -28,6 +28,9 @@ + + + @@ -68,6 +71,46 @@ + + + + + + + + + + + + host-passthrough + + + + + + + + + host-model + + + + + + + + + custom + + + + + + + + + + diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 1676f0e10e..e47aa865b1 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->nmodels; i++) + VIR_FREE(cpuModels->models[i].name); + + VIR_FREE(cpuModels->models); +} + + virDomainCapsPtr virDomainCapsNew(const char *path, const char *machine, @@ -100,6 +124,85 @@ 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->nmodels_max = nmodels; + + return cpuModels; + + error: + virObjectUnref(cpuModels); + return NULL; +} + + +virDomainCapsCPUModelsPtr +virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr old) +{ + virDomainCapsCPUModelsPtr cpuModels; + size_t i; + + if (!(cpuModels = virDomainCapsCPUModelsNew(old->nmodels))) + return NULL; + + for (i = 0; i < old->nmodels; 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->nmodels_max, + cpuModels->nmodels, 1) < 0) + return -1; + + VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels++].name, *name); + 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, @@ -233,6 +336,51 @@ virDomainCapsOSFormat(virBufferPtr buf, FORMAT_EPILOGUE(os); } +static void +virDomainCapsCPUCustomFormat(virBufferPtr buf, + virDomainCapsCPUModelsPtr custom) +{ + size_t i; + + virBufferAdjustIndent(buf, 2); + + for (i = 0; i < custom->nmodels; i++) { + virBufferAsprintf(buf, "%s\n", + custom->models[i].name); + } + + virBufferAdjustIndent(buf, -2); +} + +static void +virDomainCapsCPUFormat(virBufferPtr buf, + virDomainCapsCPUPtr cpu) +{ + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + + virBufferAsprintf(buf, "\n", + virCPUModeTypeToString(VIR_CPU_MODE_HOST_PASSTHROUGH), + cpu->hostPassthrough ? "yes" : "no"); + + virBufferAsprintf(buf, "\n", + virCPUModeTypeToString(VIR_CPU_MODE_HOST_MODEL), + cpu->hostModel ? "yes" : "no"); + + virBufferAsprintf(buf, "custom && cpu->custom->nmodels) { + virBufferAddLit(buf, "supported='yes'>\n"); + virDomainCapsCPUCustomFormat(buf, cpu->custom); + virBufferAddLit(buf, "\n"); + } else { + virBufferAddLit(buf, "supported='no'/>\n"); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); +} + static void virDomainCapsDeviceDiskFormat(virBufferPtr buf, virDomainCapsDeviceDiskPtr const disk) @@ -333,6 +481,7 @@ virDomainCapsFormatInternal(virBufferPtr buf, virBufferAsprintf(buf, "\n", caps->maxvcpus); virDomainCapsOSFormat(buf, &caps->os); + virDomainCapsCPUFormat(buf, &caps->cpu); virBufferAddLit(buf, "\n"); virBufferAdjustIndent(buf, 2); diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 492a9cf8db..149a13f328 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 nmodels_max; + size_t nmodels; + 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 03b0865ff8..13e802a58b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -153,6 +153,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 5513f99357..6b788d9144 100644 --- a/tests/domaincapsschemadata/basic.xml +++ b/tests/domaincapsschemadata/basic.xml @@ -4,6 +4,11 @@ my-machine-type x86_64 + + + + + diff --git a/tests/domaincapsschemadata/full.xml b/tests/domaincapsschemadata/full.xml index 2f529ff40c..80fd1f0bc2 100644 --- a/tests/domaincapsschemadata/full.xml +++ b/tests/domaincapsschemadata/full.xml @@ -19,6 +19,15 @@ + + + + + Model1 + Model2 + Model3 + + diff --git a/tests/domaincapsschemadata/libxl-xenfv-usb.xml b/tests/domaincapsschemadata/libxl-xenfv-usb.xml index c071d1240b..6a9e3d96f0 100644 --- a/tests/domaincapsschemadata/libxl-xenfv-usb.xml +++ b/tests/domaincapsschemadata/libxl-xenfv-usb.xml @@ -17,6 +17,11 @@ + + + + + diff --git a/tests/domaincapsschemadata/libxl-xenfv.xml b/tests/domaincapsschemadata/libxl-xenfv.xml index 9436ef89e8..d48e69948e 100644 --- a/tests/domaincapsschemadata/libxl-xenfv.xml +++ b/tests/domaincapsschemadata/libxl-xenfv.xml @@ -17,6 +17,11 @@ + + + + + diff --git a/tests/domaincapsschemadata/libxl-xenpv-usb.xml b/tests/domaincapsschemadata/libxl-xenpv-usb.xml index 4dd07bd966..d1a3918ef2 100644 --- a/tests/domaincapsschemadata/libxl-xenpv-usb.xml +++ b/tests/domaincapsschemadata/libxl-xenpv-usb.xml @@ -7,6 +7,11 @@ + + + + + diff --git a/tests/domaincapsschemadata/libxl-xenpv.xml b/tests/domaincapsschemadata/libxl-xenpv.xml index ab00a28f81..c0e3193fe6 100644 --- a/tests/domaincapsschemadata/libxl-xenpv.xml +++ b/tests/domaincapsschemadata/libxl-xenpv.xml @@ -7,6 +7,11 @@ + + + + + diff --git a/tests/domaincapsschemadata/qemu_1.7.0.x86_64.xml b/tests/domaincapsschemadata/qemu_1.7.0.x86_64.xml index 161d0ab821..6da28b060f 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 @@ + + + + + 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 f5f0f1cd07..ee51684f08 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 @@ + + + + + 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 1ae8172db2..88cced9f9d 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 @@ + + + + + diff --git a/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml b/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml index 4e87cd281b..09c0e1c3db 100644 --- a/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml +++ b/tests/domaincapsschemadata/qemu_2.6.0.aarch64.xml @@ -18,6 +18,11 @@ + + + + + diff --git a/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml b/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml index 583fdf0024..40b255eef1 100644 --- a/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml +++ b/tests/domaincapsschemadata/qemu_2.6.0.ppc64le.xml @@ -18,6 +18,11 @@ + + + + + diff --git a/tests/domaincapsschemadata/qemu_2.6.0.x86_64.xml b/tests/domaincapsschemadata/qemu_2.6.0.x86_64.xml index c453ce35d3..6706fec0f3 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 @@ + + + + + diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 5b7b7d0a7d..907c0ad023 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); -- GitLab