@@ -743,13 +743,14 @@ static void smbios_build_type_16_table(unsigned dimm_cnt)
#define MAX_T17_STD_SZ 0x7FFF /* (32G - 1M), in Megabytes */
#define MAX_T17_EXT_SZ 0x80000000 /* 2P, in Megabytes */
+#define T17_BASE 0x1100
static void smbios_build_type_17_table(unsigned instance, uint64_t size)
{
char loc_str[128];
uint64_t size_mb;
- SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(17, T17_BASE + instance, true); /* required */
t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
@@ -785,12 +786,15 @@ static void smbios_build_type_17_table(unsigned instance, uint64_t size)
SMBIOS_BUILD_TABLE_POST;
}
-static void smbios_build_type_19_table(unsigned instance,
+#define T19_BASE 0x1300
+
+static void smbios_build_type_19_table(unsigned instance, unsigned offset,
uint64_t start, uint64_t size)
{
uint64_t end, start_kb, end_kb;
- SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(19, T19_BASE + \
+ offset + instance, true); /* required */
end = start + size - 1;
assert(end > start);
@@ -982,7 +986,7 @@ void smbios_get_tables(MachineState *ms,
uint8_t **anchor, size_t *anchor_len,
Error **errp)
{
- unsigned i, dimm_cnt;
+ unsigned i, dimm_cnt, offset;
if (smbios_legacy) {
*tables = *anchor = NULL;
@@ -1012,6 +1016,16 @@ void smbios_get_tables(MachineState *ms,
dimm_cnt = QEMU_ALIGN_UP(current_machine->ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ;
+ /*
+ * The offset determines if we need to keep additional space betweeen
+ * table 17 and table 19 so that they do not overlap. For example,
+ * for a VM with larger than 8 TB guest memory and DIMM size of 16 GiB,
+ * the default space between the two tables (T19_BASE - T17_BASE = 512)
+ * is not enough.
+ */
+ offset = (dimm_cnt > (T19_BASE - T17_BASE)) ? \
+ dimm_cnt - (T19_BASE - T17_BASE) : 0;
+
smbios_build_type_16_table(dimm_cnt);
for (i = 0; i < dimm_cnt; i++) {
@@ -1019,7 +1033,7 @@ void smbios_get_tables(MachineState *ms,
}
for (i = 0; i < mem_array_size; i++) {
- smbios_build_type_19_table(i, mem_array[i].address,
+ smbios_build_type_19_table(i, offset, mem_array[i].address,
mem_array[i].length);
}
The current implementation of smbios table handle assignment does not leave enough gap between tables 17 and table 19 for guests with larger than 8 TB of memory. This change fixes this issue. This change calculates if additional space between the tables need to be set aside and then reserves that additional space. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2023977 Signed-off-by: Ani Sinha <ani@anisinha.ca> --- hw/smbios/smbios.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)