1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <device/device.h>
5 #include <cpu/x86/topology.h>
7 #define CPUID_EXTENDED_CPU_TOPOLOGY2 0x1f
9 #define CPUID_EXTENDED_CPU_TOPOLOGY 0x0b
10 #define LEVEL_TYPE_CORE 2
11 #define LEVEL_TYPE_SMT 1
13 #define CPUID_CPU_TOPOLOGY(x, val) \
14 (((val) >> CPUID_CPU_TOPOLOGY_##x##_SHIFT) & CPUID_CPU_TOPOLOGY_##x##_MASK)
16 #define CPUID_CPU_TOPOLOGY_LEVEL_TYPE_SHIFT 0x8
17 #define CPUID_CPU_TOPOLOGY_LEVEL_TYPE_MASK 0xff
18 #define CPUID_CPU_TOPOLOGY_LEVEL(res) CPUID_CPU_TOPOLOGY(LEVEL_TYPE, (res).ecx)
20 #define CPUID_CPU_TOPOLOGY_LEVEL_BITS_SHIFT 0x0
21 #define CPUID_CPU_TOPOLOGY_LEVEL_BITS_MASK 0x1f
22 #define CPUID_CPU_TOPOLOGY_THREAD_BITS(res) CPUID_CPU_TOPOLOGY(LEVEL_BITS, (res).eax)
23 #define CPUID_CPU_TOPOLOGY_CORE_BITS(res, threadbits) \
24 ((CPUID_CPU_TOPOLOGY(LEVEL_BITS, (res).eax)) - threadbits)
26 /* Return the level shift for the highest supported level (the package) */
27 static enum cb_err
get_cpu_package_bits(uint32_t *package_bits
)
29 struct cpuid_result cpuid_regs
;
30 int level_num
, cpu_id_op
= 0;
31 const uint32_t cpuid_max_func
= cpuid_get_max_func();
34 * Not all CPUs support this, those won't get topology filled in here.
35 * CPU specific code can do this however.
37 if (cpuid_max_func
>= CPUID_EXTENDED_CPU_TOPOLOGY2
)
38 cpu_id_op
= CPUID_EXTENDED_CPU_TOPOLOGY2
;
39 else if (cpuid_max_func
>= CPUID_EXTENDED_CPU_TOPOLOGY
)
40 cpu_id_op
= CPUID_EXTENDED_CPU_TOPOLOGY
;
44 *package_bits
= level_num
= 0;
45 cpuid_regs
= cpuid_ext(cpu_id_op
, level_num
);
48 * Sub-leaf index 0 enumerates SMT level, some AMD CPUs leave this CPUID leaf
49 * reserved so bail out. Cpu specific code can fill in the topology later.
51 if (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs
) != LEVEL_TYPE_SMT
)
55 *package_bits
= (CPUID_CPU_TOPOLOGY(LEVEL_BITS
, (cpuid_regs
).eax
));
57 cpuid_regs
= cpuid_ext(cpu_id_op
, level_num
);
58 /* Stop when level type is invalid i.e 0. */
59 } while (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs
));
64 void set_cpu_node_id_leaf_1f_b(struct device
*cpu
)
66 static uint32_t package_bits
;
67 static enum cb_err package_bits_ret
;
68 static bool done
= false;
71 package_bits_ret
= get_cpu_package_bits(&package_bits
);
75 const uint32_t apicid
= cpu
->path
.apic
.initial_lapicid
;
78 * If leaf_1f or leaf_b does not exist don't update the node_id.
80 if (package_bits_ret
== CB_SUCCESS
)
81 cpu
->path
.apic
.node_id
= (apicid
>> package_bits
);
84 /* Get number of bits for core ID and SMT ID */
85 static enum cb_err
get_cpu_core_thread_bits(uint32_t *core_bits
, uint32_t *thread_bits
)
87 struct cpuid_result cpuid_regs
;
88 int level_num
, cpu_id_op
= 0;
89 const uint32_t cpuid_max_func
= cpuid_get_max_func();
92 * Not all CPUs support this, those won't get topology filled in here.
93 * CPU specific code can do this however.
95 if (cpuid_max_func
< CPUID_EXTENDED_CPU_TOPOLOGY
)
98 cpu_id_op
= CPUID_EXTENDED_CPU_TOPOLOGY
;
100 *core_bits
= level_num
= 0;
101 cpuid_regs
= cpuid_ext(cpu_id_op
, level_num
);
104 * Sub-leaf index 0 enumerates SMT level, some AMD CPUs leave this CPUID leaf
105 * reserved so bail out. Cpu specific code can fill in the topology later.
107 if (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs
) != LEVEL_TYPE_SMT
)
110 *thread_bits
= CPUID_CPU_TOPOLOGY_THREAD_BITS(cpuid_regs
);
113 cpuid_regs
= cpuid_ext(cpu_id_op
, level_num
);
114 if (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs
) == LEVEL_TYPE_CORE
) {
115 *core_bits
= CPUID_CPU_TOPOLOGY_CORE_BITS(cpuid_regs
, *thread_bits
);
118 /* Stop when level type is invalid i.e 0 */
119 } while (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs
));
124 static void set_cpu_topology(struct device
*cpu
, unsigned int node
,
125 unsigned int package
, unsigned int core
,
128 cpu
->path
.apic
.node_id
= node
;
129 cpu
->path
.apic
.package_id
= package
;
130 cpu
->path
.apic
.core_id
= core
;
131 cpu
->path
.apic
.thread_id
= thread
;
134 void set_cpu_topology_from_leaf_b(struct device
*cpu
)
136 static uint32_t core_bits
, thread_bits
;
137 static enum cb_err core_thread_bits_ret
;
138 static bool done
= false;
140 core_thread_bits_ret
= get_cpu_core_thread_bits(&core_bits
, &thread_bits
);
144 const uint32_t apicid
= cpu
->path
.apic
.initial_lapicid
;
145 uint32_t package_id
, core_id
, thread_id
;
147 * If leaf_b does not exist set the following best-guess defaults:
151 * CPU specific code can always update these later on.
153 if (core_thread_bits_ret
!= CB_SUCCESS
) {
158 package_id
= apicid
>> (thread_bits
+ core_bits
);
159 core_id
= (apicid
>> thread_bits
) & ((1 << core_bits
) - 1);
160 thread_id
= apicid
& ((1 << thread_bits
) - 1);
163 set_cpu_topology(cpu
, 0, package_id
, core_id
, thread_id
);