mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 11:35:19 +00:00
cpu_x86: Add support for storing MSR features in CPU map
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
370177e2f6
commit
fcf4846a6b
@ -199,6 +199,8 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
|
|||||||
{
|
{
|
||||||
const virCPUx86CPUID *cpuid1;
|
const virCPUx86CPUID *cpuid1;
|
||||||
const virCPUx86CPUID *cpuid2;
|
const virCPUx86CPUID *cpuid2;
|
||||||
|
const virCPUx86MSR *msr1;
|
||||||
|
const virCPUx86MSR *msr2;
|
||||||
|
|
||||||
switch (item1->type) {
|
switch (item1->type) {
|
||||||
case VIR_CPU_X86_DATA_CPUID:
|
case VIR_CPU_X86_DATA_CPUID:
|
||||||
@ -209,6 +211,12 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
|
|||||||
cpuid1->ecx == cpuid2->ecx &&
|
cpuid1->ecx == cpuid2->ecx &&
|
||||||
cpuid1->edx == cpuid2->edx);
|
cpuid1->edx == cpuid2->edx);
|
||||||
|
|
||||||
|
case VIR_CPU_X86_DATA_MSR:
|
||||||
|
msr1 = &item1->data.msr;
|
||||||
|
msr2 = &item2->data.msr;
|
||||||
|
return (msr1->eax == msr2->eax &&
|
||||||
|
msr1->edx == msr2->edx);
|
||||||
|
|
||||||
case VIR_CPU_X86_DATA_NONE:
|
case VIR_CPU_X86_DATA_NONE:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -222,6 +230,8 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
|
|||||||
{
|
{
|
||||||
const virCPUx86CPUID *cpuid;
|
const virCPUx86CPUID *cpuid;
|
||||||
const virCPUx86CPUID *cpuidMask;
|
const virCPUx86CPUID *cpuidMask;
|
||||||
|
const virCPUx86MSR *msr;
|
||||||
|
const virCPUx86MSR *msrMask;
|
||||||
|
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case VIR_CPU_X86_DATA_CPUID:
|
case VIR_CPU_X86_DATA_CPUID:
|
||||||
@ -232,6 +242,12 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
|
|||||||
(cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx &&
|
(cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx &&
|
||||||
(cpuid->edx & cpuidMask->edx) == cpuidMask->edx);
|
(cpuid->edx & cpuidMask->edx) == cpuidMask->edx);
|
||||||
|
|
||||||
|
case VIR_CPU_X86_DATA_MSR:
|
||||||
|
msr = &item->data.msr;
|
||||||
|
msrMask = &mask->data.msr;
|
||||||
|
return ((msr->eax & msrMask->eax) == msrMask->eax &&
|
||||||
|
(msr->edx & msrMask->edx) == msrMask->edx);
|
||||||
|
|
||||||
case VIR_CPU_X86_DATA_NONE:
|
case VIR_CPU_X86_DATA_NONE:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@ -245,6 +261,8 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
|
|||||||
{
|
{
|
||||||
virCPUx86CPUIDPtr cpuid;
|
virCPUx86CPUIDPtr cpuid;
|
||||||
const virCPUx86CPUID *cpuidMask;
|
const virCPUx86CPUID *cpuidMask;
|
||||||
|
virCPUx86MSRPtr msr;
|
||||||
|
const virCPUx86MSR *msrMask;
|
||||||
|
|
||||||
if (!mask)
|
if (!mask)
|
||||||
return;
|
return;
|
||||||
@ -259,6 +277,13 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
|
|||||||
cpuid->edx |= cpuidMask->edx;
|
cpuid->edx |= cpuidMask->edx;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_CPU_X86_DATA_MSR:
|
||||||
|
msr = &item->data.msr;
|
||||||
|
msrMask = &mask->data.msr;
|
||||||
|
msr->eax |= msrMask->eax;
|
||||||
|
msr->edx |= msrMask->edx;
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_CPU_X86_DATA_NONE:
|
case VIR_CPU_X86_DATA_NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -272,6 +297,8 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
|
|||||||
{
|
{
|
||||||
virCPUx86CPUIDPtr cpuid;
|
virCPUx86CPUIDPtr cpuid;
|
||||||
const virCPUx86CPUID *cpuidMask;
|
const virCPUx86CPUID *cpuidMask;
|
||||||
|
virCPUx86MSRPtr msr;
|
||||||
|
const virCPUx86MSR *msrMask;
|
||||||
|
|
||||||
if (!mask)
|
if (!mask)
|
||||||
return;
|
return;
|
||||||
@ -286,6 +313,13 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
|
|||||||
cpuid->edx &= ~cpuidMask->edx;
|
cpuid->edx &= ~cpuidMask->edx;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_CPU_X86_DATA_MSR:
|
||||||
|
msr = &item->data.msr;
|
||||||
|
msrMask = &mask->data.msr;
|
||||||
|
msr->eax &= ~msrMask->eax;
|
||||||
|
msr->edx &= ~msrMask->edx;
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_CPU_X86_DATA_NONE:
|
case VIR_CPU_X86_DATA_NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -299,6 +333,8 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
|
|||||||
{
|
{
|
||||||
virCPUx86CPUIDPtr cpuid;
|
virCPUx86CPUIDPtr cpuid;
|
||||||
const virCPUx86CPUID *cpuidMask;
|
const virCPUx86CPUID *cpuidMask;
|
||||||
|
virCPUx86MSRPtr msr;
|
||||||
|
const virCPUx86MSR *msrMask;
|
||||||
|
|
||||||
if (!mask)
|
if (!mask)
|
||||||
return;
|
return;
|
||||||
@ -313,6 +349,13 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
|
|||||||
cpuid->edx &= cpuidMask->edx;
|
cpuid->edx &= cpuidMask->edx;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_CPU_X86_DATA_MSR:
|
||||||
|
msr = &item->data.msr;
|
||||||
|
msrMask = &mask->data.msr;
|
||||||
|
msr->eax &= msrMask->eax;
|
||||||
|
msr->edx &= msrMask->edx;
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_CPU_X86_DATA_NONE:
|
case VIR_CPU_X86_DATA_NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -375,6 +418,14 @@ virCPUx86DataSorter(const void *a, const void *b)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_CPU_X86_DATA_MSR:
|
||||||
|
if (da->data.msr.index > db->data.msr.index)
|
||||||
|
return 1;
|
||||||
|
else if (da->data.msr.index < db->data.msr.index)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_CPU_X86_DATA_NONE:
|
case VIR_CPU_X86_DATA_NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -979,6 +1030,31 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
x86ParseMSR(xmlXPathContextPtr ctxt,
|
||||||
|
virCPUx86DataItemPtr item)
|
||||||
|
{
|
||||||
|
virCPUx86MSRPtr msr;
|
||||||
|
unsigned long index;
|
||||||
|
unsigned long eax;
|
||||||
|
unsigned long edx;
|
||||||
|
|
||||||
|
memset(item, 0, sizeof(*item));
|
||||||
|
|
||||||
|
if (virXPathULongHex("string(@index)", ctxt, &index) < 0 ||
|
||||||
|
virXPathULongHex("string(@eax)", ctxt, &eax) < 0 ||
|
||||||
|
virXPathULongHex("string(@edx)", ctxt, &edx) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
item->type = VIR_CPU_X86_DATA_MSR;
|
||||||
|
msr = &item->data.msr;
|
||||||
|
msr->index = index;
|
||||||
|
msr->eax = eax;
|
||||||
|
msr->edx = edx;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
x86FeatureParse(xmlXPathContextPtr ctxt,
|
x86FeatureParse(xmlXPathContextPtr ctxt,
|
||||||
const char *name,
|
const char *name,
|
||||||
@ -1011,25 +1087,35 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
|
|||||||
if (STREQ_NULLABLE(str, "no"))
|
if (STREQ_NULLABLE(str, "no"))
|
||||||
feature->migratable = false;
|
feature->migratable = false;
|
||||||
|
|
||||||
n = virXPathNodeSet("./cpuid", ctxt, &nodes);
|
n = virXPathNodeSet("./cpuid|./msr", ctxt, &nodes);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Missing cpuid for feature %s"),
|
_("Missing cpuid or msr element in feature %s"),
|
||||||
feature->name);
|
feature->name);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
ctxt->node = nodes[i];
|
ctxt->node = nodes[i];
|
||||||
if (x86ParseCPUID(ctxt, &item) < 0) {
|
if (virXMLNodeNameEqual(nodes[i], "cpuid")) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
if (x86ParseCPUID(ctxt, &item) < 0) {
|
||||||
_("Invalid cpuid[%zu] in %s feature"),
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
i, feature->name);
|
_("Invalid cpuid[%zu] in %s feature"),
|
||||||
goto cleanup;
|
i, feature->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (x86ParseMSR(ctxt, &item) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Invalid msr[%zu] in %s feature"),
|
||||||
|
i, feature->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virCPUx86DataAddItem(&feature->data, &item))
|
if (virCPUx86DataAddItem(&feature->data, &item))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1545,6 +1631,7 @@ virCPUx86DataFormat(const virCPUData *data)
|
|||||||
virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
|
virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
|
||||||
while ((item = virCPUx86DataNext(&iter))) {
|
while ((item = virCPUx86DataNext(&iter))) {
|
||||||
virCPUx86CPUIDPtr cpuid;
|
virCPUx86CPUIDPtr cpuid;
|
||||||
|
virCPUx86MSRPtr msr;
|
||||||
|
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case VIR_CPU_X86_DATA_CPUID:
|
case VIR_CPU_X86_DATA_CPUID:
|
||||||
@ -1557,6 +1644,13 @@ virCPUx86DataFormat(const virCPUData *data)
|
|||||||
cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
|
cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_CPU_X86_DATA_MSR:
|
||||||
|
msr = &item->data.msr;
|
||||||
|
virBufferAsprintf(&buf,
|
||||||
|
" <msr index='0x%x' eax='0x%08x' edx='0x%08x'/>\n",
|
||||||
|
msr->index, msr->eax, msr->edx);
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_CPU_X86_DATA_NONE:
|
case VIR_CPU_X86_DATA_NONE:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1580,7 +1674,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
|
|||||||
size_t i;
|
size_t i;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = virXPathNodeSet("/cpudata/cpuid", ctxt, &nodes);
|
n = virXPathNodeSet("/cpudata/cpuid|/cpudata/msr", ctxt, &nodes);
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("no x86 CPU data found"));
|
_("no x86 CPU data found"));
|
||||||
@ -1592,11 +1686,20 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
|
|||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
ctxt->node = nodes[i];
|
ctxt->node = nodes[i];
|
||||||
if (x86ParseCPUID(ctxt, &item) < 0) {
|
if (virXMLNodeNameEqual(nodes[i], "cpuid")) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
if (x86ParseCPUID(ctxt, &item) < 0) {
|
||||||
_("failed to parse cpuid[%zu]"), i);
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
goto error;
|
_("failed to parse cpuid[%zu]"), i);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (x86ParseMSR(ctxt, &item) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("failed to parse msr[%zu]"), i);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virCPUx86DataAdd(cpuData, &item) < 0)
|
if (virCPUx86DataAdd(cpuData, &item) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,14 @@ struct _virCPUx86CPUID {
|
|||||||
uint32_t edx;
|
uint32_t edx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virCPUx86MSR virCPUx86MSR;
|
||||||
|
typedef virCPUx86MSR *virCPUx86MSRPtr;
|
||||||
|
struct _virCPUx86MSR {
|
||||||
|
uint32_t index;
|
||||||
|
uint32_t eax;
|
||||||
|
uint32_t edx;
|
||||||
|
};
|
||||||
|
|
||||||
# define CPUX86_BASIC 0x0
|
# define CPUX86_BASIC 0x0
|
||||||
# define CPUX86_KVM 0x40000000
|
# define CPUX86_KVM 0x40000000
|
||||||
# define CPUX86_EXTENDED 0x80000000
|
# define CPUX86_EXTENDED 0x80000000
|
||||||
@ -72,6 +80,7 @@ struct _virCPUx86CPUID {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
VIR_CPU_X86_DATA_NONE = 0,
|
VIR_CPU_X86_DATA_NONE = 0,
|
||||||
VIR_CPU_X86_DATA_CPUID,
|
VIR_CPU_X86_DATA_CPUID,
|
||||||
|
VIR_CPU_X86_DATA_MSR,
|
||||||
} virCPUx86DataType;
|
} virCPUx86DataType;
|
||||||
|
|
||||||
typedef struct _virCPUx86DataItem virCPUx86DataItem;
|
typedef struct _virCPUx86DataItem virCPUx86DataItem;
|
||||||
@ -80,6 +89,7 @@ struct _virCPUx86DataItem {
|
|||||||
virCPUx86DataType type;
|
virCPUx86DataType type;
|
||||||
union {
|
union {
|
||||||
virCPUx86CPUID cpuid;
|
virCPUx86CPUID cpuid;
|
||||||
|
virCPUx86MSR msr;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -307,7 +307,8 @@ def parseMap():
|
|||||||
|
|
||||||
cpuMap = {}
|
cpuMap = {}
|
||||||
for feature in data["cpus"]["feature"]:
|
for feature in data["cpus"]["feature"]:
|
||||||
cpuMap[feature["@name"]] = parseFeature(feature["cpuid"])
|
if "cpuid" in feature:
|
||||||
|
cpuMap[feature["@name"]] = parseFeature(feature["cpuid"])
|
||||||
|
|
||||||
return cpuMap
|
return cpuMap
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user