mirror of https://gitee.com/openkylin/libvirt.git
Added the attribute vendor_id to the cpu model
Introducing the attribute vendor_id to force the CPUID instruction in a kvm guest to return the specified vendor.
This commit is contained in:
parent
78290b1641
commit
a3389319ba
|
@ -2854,6 +2854,13 @@
|
|||
</choice>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="vendor_id">
|
||||
<data type="string">
|
||||
<param name='pattern'>[^,]{12}</param>
|
||||
</data>
|
||||
</attribute>
|
||||
</optional>
|
||||
<choice>
|
||||
<text/>
|
||||
<empty/>
|
||||
|
|
|
@ -68,6 +68,7 @@ virCPUDefFreeModel(virCPUDefPtr def)
|
|||
|
||||
VIR_FREE(def->model);
|
||||
VIR_FREE(def->vendor);
|
||||
VIR_FREE(def->vendor_id);
|
||||
|
||||
for (i = 0; i < def->nfeatures; i++)
|
||||
VIR_FREE(def->features[i].name);
|
||||
|
@ -104,6 +105,7 @@ virCPUDefCopyModel(virCPUDefPtr dst,
|
|||
|
||||
if ((src->model && !(dst->model = strdup(src->model)))
|
||||
|| (src->vendor && !(dst->vendor = strdup(src->vendor)))
|
||||
|| (src->vendor_id && !(dst->vendor_id = strdup(src->vendor_id)))
|
||||
|| VIR_ALLOC_N(dst->features, src->nfeatures) < 0)
|
||||
goto no_memory;
|
||||
dst->nfeatures_max = dst->nfeatures = src->nfeatures;
|
||||
|
@ -288,18 +290,46 @@ virCPUDefParseXML(const xmlNodePtr node,
|
|||
}
|
||||
|
||||
if (def->type == VIR_CPU_TYPE_GUEST &&
|
||||
def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH &&
|
||||
virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) {
|
||||
const char *fallback;
|
||||
def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
|
||||
|
||||
fallback = virXPathString("string(./model[1]/@fallback)", ctxt);
|
||||
if (fallback) {
|
||||
def->fallback = virCPUFallbackTypeFromString(fallback);
|
||||
VIR_FREE(fallback);
|
||||
if (def->fallback < 0) {
|
||||
virCPUReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("Invalid fallback attribute"));
|
||||
goto error;
|
||||
if (virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) {
|
||||
const char *fallback;
|
||||
|
||||
fallback = virXPathString("string(./model[1]/@fallback)", ctxt);
|
||||
if (fallback) {
|
||||
def->fallback = virCPUFallbackTypeFromString(fallback);
|
||||
VIR_FREE(fallback);
|
||||
if (def->fallback < 0) {
|
||||
virCPUReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("Invalid fallback attribute"));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (virXPathBoolean("boolean(./model[1]/@vendor_id)", ctxt)) {
|
||||
char *vendor_id;
|
||||
|
||||
vendor_id = virXPathString("string(./model[1]/@vendor_id)",
|
||||
ctxt);
|
||||
if (!vendor_id ||
|
||||
strlen(vendor_id) != VIR_CPU_VENDOR_ID_LENGTH) {
|
||||
virCPUReportError(VIR_ERR_XML_ERROR,
|
||||
_("vendor_id must be exactly"
|
||||
" %d characters long"),
|
||||
VIR_CPU_VENDOR_ID_LENGTH);
|
||||
VIR_FREE(vendor_id);
|
||||
goto error;
|
||||
}
|
||||
/* ensure that the string can be passed to qemu*/
|
||||
for (i = 0; i < strlen(vendor_id); i++) {
|
||||
if (vendor_id[i]==',') {
|
||||
virCPUReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("vendor id is invalid"));
|
||||
VIR_FREE(vendor_id);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
def->vendor_id = vendor_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -588,6 +618,8 @@ virCPUDefFormatBuf(virBufferPtr buf,
|
|||
return -1;
|
||||
}
|
||||
virBufferAsprintf(buf, " fallback='%s'", fallback);
|
||||
if (def->vendor_id)
|
||||
virBufferAsprintf(buf, " vendor_id='%s'", def->vendor_id);
|
||||
}
|
||||
if (formatModel && def->model) {
|
||||
virBufferAsprintf(buf, ">%s</model>\n", def->model);
|
||||
|
@ -738,6 +770,13 @@ virCPUDefIsEqual(virCPUDefPtr src,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if (STRNEQ_NULLABLE(src->vendor_id, dst->vendor_id)) {
|
||||
virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Target CPU model %s does not match source %s"),
|
||||
NULLSTR(dst->vendor_id), NULLSTR(src->vendor_id));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (src->sockets != dst->sockets) {
|
||||
virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Target CPU sockets %d does not match source %d"),
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
# include "buf.h"
|
||||
# include "xml.h"
|
||||
|
||||
# define VIR_CPU_VENDOR_ID_LENGTH 12
|
||||
|
||||
enum virCPUType {
|
||||
VIR_CPU_TYPE_HOST,
|
||||
VIR_CPU_TYPE_GUEST,
|
||||
|
@ -103,6 +105,7 @@ struct _virCPUDef {
|
|||
int match; /* enum virCPUMatch */
|
||||
char *arch;
|
||||
char *model;
|
||||
char *vendor_id; /* vendor id returned by CPUID in the guest */
|
||||
int fallback; /* enum virCPUFallback */
|
||||
char *vendor;
|
||||
unsigned int sockets;
|
||||
|
|
|
@ -3913,7 +3913,9 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
|
|||
}
|
||||
virBufferAddLit(&buf, "host");
|
||||
} else {
|
||||
if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(host->arch)))
|
||||
if (VIR_ALLOC(guest) < 0 ||
|
||||
!(guest->arch = strdup(host->arch)) ||
|
||||
(cpu->vendor_id && !(guest->vendor_id = strdup(cpu->vendor_id))))
|
||||
goto no_memory;
|
||||
|
||||
if (cpu->match == VIR_CPU_MATCH_MINIMUM)
|
||||
|
@ -3927,6 +3929,8 @@ qemuBuildCpuArgStr(const struct qemud_driver *driver,
|
|||
goto cleanup;
|
||||
|
||||
virBufferAdd(&buf, guest->model, -1);
|
||||
if (guest->vendor_id)
|
||||
virBufferAsprintf(&buf, ",vendor=%s", guest->vendor_id);
|
||||
for (i = 0; i < guest->nfeatures; i++) {
|
||||
char sign;
|
||||
if (guest->features[i].policy == VIR_CPU_FEATURE_DISABLE)
|
||||
|
|
|
@ -116,6 +116,7 @@ virCapsPtr testQemuCapsInit(void) {
|
|||
0, /* match */
|
||||
(char *) "x86_64", /* arch */
|
||||
(char *) "core2duo", /* model */
|
||||
NULL, /* vendor_id */
|
||||
0, /* fallback */
|
||||
(char *) "Intel", /* vendor */
|
||||
1, /* sockets */
|
||||
|
|
Loading…
Reference in New Issue