mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
domcaps: Add support for listing supported CPU models
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@redhat.com>
This commit is contained in:
parent
350e3fee0e
commit
167280e7f6
@ -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
|
||||
<a href="formatdomain.html#elementsCPU">guest CPUs</a>.
|
||||
</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>
|
||||
|
@ -28,6 +28,9 @@
|
||||
<optional>
|
||||
<ref name='os'/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name='cpu'/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name='devices'/>
|
||||
</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>
|
||||
|
@ -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, "<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->nmodels) {
|
||||
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 +481,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);
|
||||
|
@ -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__}; \
|
||||
|
@ -153,6 +153,10 @@ virDomainAuditVcpu;
|
||||
|
||||
|
||||
# conf/domain_capabilities.h
|
||||
virDomainCapsCPUModelsAdd;
|
||||
virDomainCapsCPUModelsAddSteal;
|
||||
virDomainCapsCPUModelsCopy;
|
||||
virDomainCapsCPUModelsNew;
|
||||
virDomainCapsEnumClear;
|
||||
virDomainCapsEnumSet;
|
||||
virDomainCapsFormat;
|
||||
|
@ -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'/>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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'>
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user