Package: hwloc-contrib / 2.12.0-3~bpo12+1

work_around_legacy_max_proc_being_0 Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
commit 452765963af7532add7060edfefb06dd05a4cb26
Author: Brice Goglin <Brice.Goglin@inria.fr>
Date:   Thu Apr 24 09:08:08 2025 +0200

    x86: work around legacy_max_proc being 0 while HTT feature bit is set
    
    The Intel manual says that legacy_max_proc (CPUID.1.EBX[16-23]) is valid
    if CPUID.1.EDX.HTT[bit 28] is set.
    AMD (at least recent ones) don't say anything about it being invalid.
    
    Unfortunately some Qemu config may keep the former at 0 with the latter set.
    At least this happens when libvirt passes -cpu EPYC-Rome,ht=on to Qemu
    (which sets the HTT bit), and -smp 32,maxcpus=48,sockets=48,cores=1,threads=1
    says each CPU is single threaded (which keeps legacy_max_log_proc to 0).
    This config comes from https://bugzilla.opensuse.org/show_bug.cgi?id=1236038
    
    Calling flsl on this invalid mask leads to undefined behavior and some division
    by zero later (depending on the compiler).
    
    Check whether legacy_max_proc is 0 before using it.
    If 0, assume legacy_max_log_proc is 1, just like we did when HTT is unset.
    
    Thanks to Georg Pfuetzenreuter for the report
    and Anthony Iliopoulos for the debugging.
    
    Refs #714
    
    Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
    (cherry picked from commit 77495cecad7178ccd73ad4962780328f079a0e65)

diff --git a/hwloc/topology-x86.c b/hwloc/topology-x86.c
index f442f7f00..42248f680 100644
--- a/hwloc/topology-x86.c
+++ b/hwloc/topology-x86.c
@@ -653,7 +653,13 @@ static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, uns
   cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
   infos->apicid = ebx >> 24;
   if (edx & (1 << 28)) {
-    legacy_max_log_proc = 1 << hwloc_flsl(((ebx >> 16) & 0xff) - 1);
+    unsigned ebx_16_23 = (ebx >> 16) & 0xff;
+    if (ebx_16_23) {
+      legacy_max_log_proc = 1 << hwloc_flsl(ebx_16_23 - 1);
+    } else {
+      hwloc_debug("HTT bit set in CPUID 0x01.edx, but legacy_max_proc = 0 in ebx, assuming legacy_max_log_proc = 1\n");
+      legacy_max_log_proc = 1;
+    }
   } else {
     hwloc_debug("HTT bit not set in CPUID 0x01.edx, assuming legacy_max_log_proc = 1\n");
     legacy_max_log_proc = 1;