Currently, hvmloader uses SMBIOS 2.4, however, when using OVMF, the
SMBIOS is patched to 2.8, which has clarified the UUID format (as GUID).
In Linux, if the SMBIOS version is >= 2.6, the GUID format is used, else
(undefined as per SMBIOS spec), big endian is used (used by Xen). Therefore,
you have a endian mismatch causing the UUIDs to mismatch in the guest.
$ cat /sys/hypervisor/uuid
e865e63f-3d30-4f0b-83e0-8fdfc1e30eb7
$ cat /sys/devices/virtual/dmi/id/product_uuid
3fe665e8-303d-0b4f-83e0-8fdfc1e30eb7
$ cat /sys/devices/virtual/dmi/id/product_serial
e865e63f-3d30-4f0b-83e0-8fdfc1e30eb7
This patch updates the SMBIOS version from 2.4 to 2.6 and does the appropriate
modifications of the table. This effectively fix this endianness mismatch with
OVMF; while the UUID displayed by Linux is still the same for SeaBIOS.
Fixes: c683914ef913 ("Add code to generate SMBIOS tables to hvmloader.")
(SMBIOS versions before 2.6 has a ill-defined UUID definition)
Signed-off-by: Teddy Astie <[email protected]>
---
v2:
- rebase onto staging
- introduce missing SMBIOS 2.5-2.6 fields
- check for new SMBIOS 2.6 table lengths
- update UUID conversion comment
- add Fixes: note
---
tools/firmware/hvmloader/smbios.c | 50 ++++++++++++++++++++-----
tools/firmware/hvmloader/smbios_types.h | 9 +++++
2 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/tools/firmware/hvmloader/smbios.c
b/tools/firmware/hvmloader/smbios.c
index 76c7090d16..e445475d78 100644
--- a/tools/firmware/hvmloader/smbios.c
+++ b/tools/firmware/hvmloader/smbios.c
@@ -396,7 +396,7 @@ smbios_entry_point_init(void *start,
memcpy(ep->anchor_string, "_SM_", 4);
ep->length = 0x1f;
ep->smbios_major_version = 2;
- ep->smbios_minor_version = 4;
+ ep->smbios_minor_version = 6;
ep->max_structure_size = max_structure_size;
ep->entry_point_revision = 0;
memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
@@ -505,7 +505,22 @@ smbios_type_1_init(void *start, const char *xen_version,
p->version_str = 3;
p->serial_number_str = 4;
- memcpy(p->uuid, uuid, 16);
+ /*
+ * Xen toolstack uses big endian UUIDs, however GUIDs (which requirement
+ * is clarified by SMBIOS >= 2.6) has the first 3 components appearing as
+ * being little endian and the rest as still being big endian.
+ */
+ /* First component */
+ for ( unsigned int i = 0; i < 4; i++ )
+ p->uuid[i] = uuid[4 - i - 1];
+ /* Second component */
+ p->uuid[4] = uuid[5];
+ p->uuid[5] = uuid[4];
+ /* Third component */
+ p->uuid[6] = uuid[7];
+ p->uuid[7] = uuid[6];
+ /* Rest */
+ memcpy(p->uuid + 8, uuid + 8, 8);
p->wake_up_type = 0x06; /* power switch */
p->sku_str = 0;
@@ -705,8 +720,8 @@ smbios_type_4_init(
struct smbios_type_4 *p = start;
uint32_t eax, ebx, ecx, edx;
- /* Specification says Type 4 table has length of 23h for v2.3+. */
- BUILD_BUG_ON(sizeof(*p) != 35);
+ /* Specification says Type 4 table has length of 2Ah for v2.6. */
+ BUILD_BUG_ON(sizeof(*p) != 42);
memset(p, 0, sizeof(*p));
@@ -716,7 +731,7 @@ smbios_type_4_init(
p->socket_designation_str = 1;
p->processor_type = 0x03; /* CPU */
- p->processor_family = 0x01; /* other */
+ p->processor_family = p->processor_family_2 = 0x01; /* other */
p->manufacturer_str = 2;
cpuid(1, &eax, &ebx, &ecx, &edx);
@@ -736,6 +751,22 @@ smbios_type_4_init(
p->l2_cache_handle = 0xffff; /* No cache information structure provided. */
p->l3_cache_handle = 0xffff; /* No cache information structure provided. */
+ /*
+ * We have a smbios type 4 table per vCPU (which is per socket),
+ * which means here that we have 1 socket per vCPU.
+ */
+ p->core_count = p->core_enabled = p->thread_count = 1;
+
+ /*
+ * We set 64-bits, execute protection and enhanced virtualization.
+ * We don't set Multi-Core (bit 3) because this individual processor
+ * (as being a single vCPU) is only having one core.
+ *
+ * SMBIOS specification says that these bits don't state anything
+ * regarding the actual availability of such features.
+ */
+ p->processor_characteristics = 0x64;
+
start += sizeof(*p);
strncpy(buf, "CPU ", sizeof(buf));
@@ -780,8 +811,8 @@ smbios_type_8_init(void *start)
static void *
smbios_type_9_init(void *start)
{
- /* Specification says Type 9 table has length of 0Dh for v2.1-2.5. */
- BUILD_BUG_ON(sizeof(struct smbios_type_9) != 13);
+ /* Specification says Type 9 table has length of 11h for v2.6+. */
+ BUILD_BUG_ON(sizeof(struct smbios_type_9) != 17);
/* Only present when passed in. */
return smbios_pt_copy(start, 9, SMBIOS_HANDLE_TYPE9,
@@ -870,8 +901,8 @@ smbios_type_17_init(void *start, uint32_t memory_size_mb,
int instance)
char buf[16];
struct smbios_type_17 *p = start;
- /* Specification says Type 17 table has length of 1Bh for v2.3-2.6. */
- BUILD_BUG_ON(sizeof(*p) != 27);
+ /* Specification says Type 17 table has length of 1Ch for v2.6. */
+ BUILD_BUG_ON(sizeof(*p) != 28);
memset(p, 0, sizeof(*p));
@@ -890,6 +921,7 @@ smbios_type_17_init(void *start, uint32_t memory_size_mb,
int instance)
p->bank_locator_str = 0;
p->memory_type = 0x07; /* RAM */
p->type_detail = 0;
+ p->attributes = 0;
start += sizeof(*p);
strcpy(start, "DIMM ");
diff --git a/tools/firmware/hvmloader/smbios_types.h
b/tools/firmware/hvmloader/smbios_types.h
index c04b435d31..860617d86a 100644
--- a/tools/firmware/hvmloader/smbios_types.h
+++ b/tools/firmware/hvmloader/smbios_types.h
@@ -147,6 +147,11 @@ struct smbios_type_4 {
uint8_t serial_number_str;
uint8_t asset_tag_str;
uint8_t part_number_str;
+ uint8_t core_count;
+ uint8_t core_enabled;
+ uint8_t thread_count;
+ uint16_t processor_characteristics;
+ uint16_t processor_family_2;
} __attribute__ ((packed));
/* SMBIOS type 7 - Cache Information */
@@ -185,6 +190,9 @@ struct smbios_type_9 {
uint16_t slot_id;
uint8_t slot_characteristics_1;
uint8_t slot_characteristics_2;
+ uint16_t sgn_base;
+ uint8_t bus_number_base;
+ uint8_t devfn_base;
} __attribute__ ((packed));
/* SMBIOS type 11 - OEM Strings */
@@ -227,6 +235,7 @@ struct smbios_type_17 {
uint8_t serial_number_str;
uint8_t asset_tag_str;
uint8_t part_number_str;
+ uint8_t attributes;
} __attribute__ ((packed));
/* SMBIOS type 19 - Memory Array Mapped Address */
--
2.50.1
Teddy Astie | Vates XCP-ng Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech