This patch uses cpuid to determine the number of packages/sockets in which to
generate the proper number of DMI/SMBIOS Type 4 (Processor Information)
records.
Use "dmidevcode -t 4" to show that only the configured number of
packages/sockets are shown versus the number of CPUs (sockets*cores*threads).
Signed-off-by: Bret Ketchum <bcketchum at gmail.com>
---
src/fw/smbios.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/src/fw/smbios.c b/src/fw/smbios.c
index affb9be..23869b1 100644
--- a/src/fw/smbios.c
+++ b/src/fw/smbios.c
@@ -505,6 +505,52 @@ smbios_init_type_127(void *start)
#define TEMPSMBIOSSIZE (32 * 1024)
+static inline void
+cpuid_count(u32 index, u32 sub, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+{
+ asm volatile("cpuid"
+ : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+ : "0" (index), "c" (sub));
+}
+
+static int package_count(void)
+{
+ char vendor[12];
+ int ret = CountCPUs;
+ u32 cpuid_features, cpuid_high, cpuid_procinfo, cpuid_signature;
+ u32 eax, ebx, ecx, edx;
+
+ cpuid(0, &cpuid_high, &ebx, &ecx, &edx);
+ ((u32 *)&vendor)[0] = ebx;
+ ((u32 *)&vendor)[1] = edx;
+ ((u32 *)&vendor)[2] = ecx;
+
+ cpuid(1, &cpuid_signature, &cpuid_procinfo, &ecx, &cpuid_features);
+
+ if (memcmp(vendor, "GenuineIntel", sizeof(vendor)) == 0) {
+ int logical = (cpuid_features & 0x10000000) != 0
+ ? (cpuid_procinfo >> 16) & 0xff
+ : 1;
+
+ cpuid_count(4, 0, &eax, &ebx, &ecx, &edx);
+
+ /* number of packages/sockets equals the number ACPI IDs
+ * divided by the "Maximum number of addressable IDs for
+ * logical processors in this physical package.
+ */
+ ret = MaxCountCPUs / ((logical == 1)
+ ? (((eax >> 26) & 0x3f) + 1)
+ : logical);
+
+ } else {
+ cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
+
+ ret = ((cpuid_procinfo >> 16) & 0xff) / ((ecx & 0xff) + 1);
+ }
+
+ return(ret);
+}
+
void
smbios_setup(void)
{
@@ -538,8 +584,8 @@ smbios_setup(void)
add_struct(1, p);
add_struct(3, p);
- int cpu_num;
- for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++)
+ int cpu_num, pkg_count = package_count();
+ for (cpu_num = 1; cpu_num <= pkg_count; cpu_num++)
add_struct(4, p, cpu_num);
int ram_mb = (RamSize + RamSizeOver4G) >> 20;
--
1.8.3.1