1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

ESX add x86_64 detection based on the CPUID

* src/esx/esx_driver.c: add esxSupportsLongMode() and update esxCapsInit()
* src/esx/esx_vi.[ch]: Add AnyType handling for lists
* src/esx/esx_vi_types.c: bind VI type HostCpuIdInfo
This commit is contained in:
Matthias Bolte 2009-09-23 14:29:39 +02:00 committed by Daniel Veillard
parent af4c893eb7
commit 15b0c4ffdb
5 changed files with 325 additions and 9 deletions

View File

@ -27,6 +27,7 @@
* - Memory model: http://www.vmware.com/pdf/esx3_memory.pdf
* - VI API reference: http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/
* - VMX-file parameters: http://www.sanbarrow.com/vmx.html
* - CPUID: http://www.sandpile.org/ia32/cpuid.htm
*/
#include <config.h>
@ -62,19 +63,144 @@ typedef struct _esxPrivate {
char *transport;
int32_t maxVcpus;
esxVI_Boolean supportsVMotion;
esxVI_Boolean supportsLongMode; /* aka x86_64 */
int32_t usedCpuTimeCounterId;
} esxPrivate;
static esxVI_Boolean
esxSupportsLongMode(virConnectPtr conn)
{
esxPrivate *priv = (esxPrivate *)conn->privateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *hostSystem = NULL;
esxVI_DynamicProperty *dynamicProperty = NULL;
esxVI_HostCpuIdInfo *hostCpuIdInfoList = NULL;
esxVI_HostCpuIdInfo *hostCpuIdInfo = NULL;
char edxLongModeBit = '?';
char edxFirstBit = '?';
if (priv->phantom) {
ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
"Not possible with a phantom connection");
goto failure;
}
if (priv->supportsLongMode != esxVI_Boolean_Undefined) {
return priv->supportsLongMode;
}
if (esxVI_EnsureSession(conn, priv->host) < 0) {
goto failure;
}
if (esxVI_String_AppendValueToList(conn, &propertyNameList,
"hardware.cpuFeature") < 0 ||
esxVI_GetObjectContent(conn, priv->host, priv->host->hostFolder,
"HostSystem", propertyNameList,
esxVI_Boolean_True, &hostSystem) < 0) {
goto failure;
}
if (hostSystem == NULL) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Could not retrieve the HostSystem object");
goto failure;
}
for (dynamicProperty = hostSystem->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, "hardware.cpuFeature")) {
if (esxVI_HostCpuIdInfo_CastListFromAnyType
(conn, dynamicProperty->val, &hostCpuIdInfoList) < 0) {
goto failure;
}
for (hostCpuIdInfo = hostCpuIdInfoList; hostCpuIdInfo != NULL;
hostCpuIdInfo = hostCpuIdInfo->_next) {
if (hostCpuIdInfo->level->value == -2147483647) { /* 0x80000001 */
#define _SKIP4 "%*c%*c%*c%*c"
#define _SKIP12 _SKIP4":"_SKIP4":"_SKIP4
/* Expected format: "--X-:----:----:----:----:----:----:----" */
if (sscanf(hostCpuIdInfo->edx,
"%*c%*c%c%*c:"_SKIP12":"_SKIP12":%*c%*c%*c%c",
&edxLongModeBit, &edxFirstBit) != 2) {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"HostSystem property 'hardware.cpuFeature[].edx' "
"with value '%s' doesn't have expected format "
"'----:----:----:----:----:----:----:----'",
hostCpuIdInfo->edx);
goto failure;
}
#undef _SKIP4
#undef _SKIP12
if (edxLongModeBit == '1') {
priv->supportsLongMode = esxVI_Boolean_True;
} else if (edxLongModeBit == '0') {
priv->supportsLongMode = esxVI_Boolean_False;
} else {
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Bit 29 (Long Mode) of HostSystem property "
"'hardware.cpuFeature[].edx' with value '%s' "
"has unexpected value '%c', expecting '0' "
"or '1'", hostCpuIdInfo->edx, edxLongModeBit);
goto failure;
}
break;
}
}
break;
} else {
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
}
}
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&hostSystem);
esxVI_HostCpuIdInfo_Free(&hostCpuIdInfoList);
return priv->supportsLongMode;
failure:
priv->supportsLongMode = esxVI_Boolean_Undefined;
goto cleanup;
}
static virCapsPtr
esxCapsInit(virConnectPtr conn)
{
esxPrivate *priv = (esxPrivate *)conn->privateData;
esxVI_Boolean supportsLongMode = esxVI_Boolean_Undefined;
virCapsPtr caps = NULL;
virCapsGuestPtr guest = NULL;
/* FIXME: Need to detect real host architecture */
caps = virCapabilitiesNew("i686", 1, 1);
if (priv->phantom) {
ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID,
"Not possible with a phantom connection");
return NULL;
}
supportsLongMode = esxSupportsLongMode(conn);
if (supportsLongMode == esxVI_Boolean_Undefined) {
return NULL;
}
if (supportsLongMode == esxVI_Boolean_True) {
caps = virCapabilitiesNew("x86_64", 1, 1);
} else {
caps = virCapabilitiesNew("i686", 1, 1);
}
if (caps == NULL) {
virReportOOMError(conn);
@ -84,9 +210,9 @@ esxCapsInit(virConnectPtr conn)
virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x00, 0x50, 0x56 });
virCapabilitiesAddHostMigrateTransport(caps, "esx");
/* FIXME: Need to detect real host architecture and word size */
guest =
virCapabilitiesAddGuest(caps, "hvm", "i686", 32, NULL, NULL, 0, NULL);
/* i686 */
guest = virCapabilitiesAddGuest(caps, "hvm", "i686", 32, NULL, NULL, 0,
NULL);
if (guest == NULL) {
goto failure;
@ -101,6 +227,25 @@ esxCapsInit(virConnectPtr conn)
goto failure;
}
/* x86_64 */
if (supportsLongMode == esxVI_Boolean_True) {
guest = virCapabilitiesAddGuest(caps, "hvm", "x86_64", 64, NULL, NULL,
0, NULL);
if (guest == NULL) {
goto failure;
}
/*
* FIXME: Maybe distinguish betwen ESX and GSX here, see
* esxVMX_ParseConfig() and VIR_DOMAIN_VIRT_VMWARE
*/
if (virCapabilitiesAddGuestDomain(guest, "vmware", NULL, NULL, 0,
NULL) == NULL) {
goto failure;
}
}
return caps;
failure:
@ -181,6 +326,7 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
priv->phantom = phantom;
priv->maxVcpus = -1;
priv->supportsVMotion = esxVI_Boolean_Undefined;
priv->supportsLongMode = esxVI_Boolean_Undefined;
priv->usedCpuTimeCounterId = -1;
/* Request credentials and login to non-phantom host/vCenter */
@ -331,7 +477,11 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
}
VIR_FREE(vCenter);
}
conn->privateData = priv;
if (! phantom) {
/* Setup capabilities */
priv->caps = esxCapsInit(conn);
@ -340,8 +490,6 @@ esxOpen(virConnectPtr conn, virConnectAuthPtr auth, int flags ATTRIBUTE_UNUSED)
}
}
conn->privateData = priv;
return VIR_DRV_OPEN_SUCCESS;
failure:

View File

@ -832,6 +832,74 @@ esxVI_List_DeepCopy(virConnectPtr conn, esxVI_List **destList,
return -1;
}
int
esxVI_List_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType,
esxVI_List **list,
esxVI_List_CastFromAnyTypeFunc castFromAnyTypeFunc,
esxVI_List_FreeFunc freeFunc)
{
int result = 0;
xmlNodePtr childNode = NULL;
esxVI_AnyType *childAnyType = NULL;
esxVI_List *item = NULL;
if (list == NULL || *list != NULL ||
castFromAnyTypeFunc == NULL || freeFunc == NULL) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
goto failure;
}
if (anyType == NULL) {
return 0;
}
if (! STRPREFIX(anyType->other, "ArrayOf")) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Expecting type to begin with 'ArrayOf' but found '%s'",
anyType->other);
goto failure;
}
for (childNode = anyType->_node->xmlChildrenNode; childNode != NULL;
childNode = childNode->next) {
if (childNode->type != XML_ELEMENT_NODE) {
ESX_VI_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
"Wrong XML element type %d", childNode->type);
goto failure;
}
esxVI_AnyType_Free(&childAnyType);
if (esxVI_AnyType_Deserialize(conn, childNode, &childAnyType) < 0) {
goto failure;
}
item = NULL;
if (castFromAnyTypeFunc(conn, childAnyType, &item) < 0) {
goto failure;
}
if (esxVI_List_Append(conn, list, item) < 0) {
goto failure;
}
}
cleanup:
esxVI_AnyType_Free(&childAnyType);
return result;
failure:
freeFunc(list);
result = -1;
goto cleanup;
}
int
esxVI_List_Serialize(virConnectPtr conn, esxVI_List *list, const char *element,
virBufferPtr output, esxVI_Boolean required,

View File

@ -150,6 +150,9 @@ struct _esxVI_List {
typedef int (*esxVI_List_FreeFunc) (esxVI_List **item);
typedef int (*esxVI_List_DeepCopyFunc) (virConnectPtr conn, esxVI_List **dest,
esxVI_List *src);
typedef int (*esxVI_List_CastFromAnyTypeFunc) (virConnectPtr conn,
esxVI_AnyType *anyType,
esxVI_List **item);
typedef int (*esxVI_List_SerializeFunc) (virConnectPtr conn, esxVI_List *item,
const char *element,
virBufferPtr output,
@ -162,6 +165,10 @@ int esxVI_List_DeepCopy(virConnectPtr conn, esxVI_List **destList,
esxVI_List *srcList,
esxVI_List_DeepCopyFunc deepCopyFunc,
esxVI_List_FreeFunc freeFunc);
int esxVI_List_CastFromAnyType(virConnectPtr conn, esxVI_AnyType *anyType,
esxVI_List **list,
esxVI_List_CastFromAnyTypeFunc castFromAnyTypeFunc,
esxVI_List_FreeFunc freeFunc);
int esxVI_List_Serialize(virConnectPtr conn, esxVI_List *list,
const char *element, virBufferPtr output,
esxVI_Boolean required,

View File

@ -115,6 +115,21 @@
#define ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(_type) \
int \
esxVI_##_type##_CastListFromAnyType(virConnectPtr conn, \
esxVI_AnyType *anyType, \
esxVI_##_type **list) \
{ \
return esxVI_List_CastFromAnyType \
(conn, anyType, (esxVI_List **)list, \
(esxVI_List_CastFromAnyTypeFunc) \
esxVI_##_type##_CastFromAnyType, \
(esxVI_List_FreeFunc)esxVI_##_type##_Free); \
}
#define ESX_VI__TEMPLATE__LIST__SERIALIZE(_type) \
int \
esxVI_##_type##_SerializeList(virConnectPtr conn, esxVI_##_type *list, \
@ -1467,6 +1482,51 @@ ESX_VI__TEMPLATE__LIST__DESERIALIZE(DynamicProperty);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VI Type: HostCpuIdInfo
*/
/* esxVI_HostCpuIdInfo_Alloc */
ESX_VI__TEMPLATE__ALLOC(HostCpuIdInfo);
/* esxVI_HostCpuIdInfo_Free */
ESX_VI__TEMPLATE__FREE(HostCpuIdInfo,
{
esxVI_HostCpuIdInfo_Free(&item->_next);
VIR_FREE(item->vendor);
VIR_FREE(item->eax);
VIR_FREE(item->ebx);
VIR_FREE(item->ecx);
VIR_FREE(item->edx);
});
/* esxVI_HostCpuIdInfo_CastFromAnyType */
ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(HostCpuIdInfo);
/* esxVI_HostCpuIdInfo_CastListFromAnyType */
ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(HostCpuIdInfo);
/* esxVI_HostCpuIdInfo_Deserialize */
ESX_VI__TEMPLATE__DESERIALIZE(HostCpuIdInfo,
{
ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(Int, level);
ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, vendor);
ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, eax);
ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, ebx);
ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, ecx);
ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, edx);
},
{
ESX_VI__TEMPLATE__PROPERTY__REQUIRED(level);
});
/* esxVI_HostCpuIdInfo_DeserializeList */
ESX_VI__TEMPLATE__LIST__DESERIALIZE(HostCpuIdInfo);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VI Type: SelectionSpec
*/

View File

@ -71,6 +71,7 @@ typedef enum _esxVI_VirtualMachinePowerState esxVI_VirtualMachinePowerState;
typedef struct _esxVI_Fault esxVI_Fault;
typedef struct _esxVI_ManagedObjectReference esxVI_ManagedObjectReference;
typedef struct _esxVI_DynamicProperty esxVI_DynamicProperty;
typedef struct _esxVI_HostCpuIdInfo esxVI_HostCpuIdInfo;
typedef struct _esxVI_SelectionSpec esxVI_SelectionSpec;
typedef struct _esxVI_TraversalSpec esxVI_TraversalSpec;
typedef struct _esxVI_ObjectSpec esxVI_ObjectSpec;
@ -527,7 +528,39 @@ int esxVI_DynamicProperty_Deserialize(virConnectPtr conn, xmlNodePtr node,
esxVI_DynamicProperty **dynamicProperty);
int esxVI_DynamicProperty_DeserializeList
(virConnectPtr conn, xmlNodePtr node,
esxVI_DynamicProperty **dynamicProperty);
esxVI_DynamicProperty **dynamicPropertyList);
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* VI Type: HostCpuIdInfo
*/
struct _esxVI_HostCpuIdInfo {
esxVI_HostCpuIdInfo *_next; /* optional */
esxVI_Int *level; /* required */
char *vendor; /* optional */
char *eax; /* optional */
char *ebx; /* optional */
char *ecx; /* optional */
char *edx; /* optional */
};
int esxVI_HostCpuIdInfo_Alloc(virConnectPtr conn,
esxVI_HostCpuIdInfo **hostCpuIdInfo);
void esxVI_HostCpuIdInfo_Free(esxVI_HostCpuIdInfo **hostCpuIdInfoList);
int esxVI_HostCpuIdInfo_CastFromAnyType(virConnectPtr conn,
esxVI_AnyType *anyType,
esxVI_HostCpuIdInfo **hostCpuIdInfo);
int esxVI_HostCpuIdInfo_CastListFromAnyType
(virConnectPtr conn, esxVI_AnyType *anyType,
esxVI_HostCpuIdInfo **hostCpuIdInfoList);
int esxVI_HostCpuIdInfo_Deserialize(virConnectPtr conn, xmlNodePtr node,
esxVI_HostCpuIdInfo **hostCpuIdInfo);
int esxVI_HostCpuIdInfo_DeserializeList
(virConnectPtr conn, xmlNodePtr node,
esxVI_HostCpuIdInfo **hostCpuIdInfoList);
@ -632,7 +665,7 @@ int esxVI_PropertyChange_Deserialize(virConnectPtr conn, xmlNodePtr node,
esxVI_PropertyChange **propertyChange);
int esxVI_PropertyChange_DeserializeList
(virConnectPtr conn, xmlNodePtr node,
esxVI_PropertyChange **propertyChange);
esxVI_PropertyChange **propertyChangeList);