1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <smbios.h>
4 #include <console/console.h>
5 #include <arch/cpu.h>
6 #include <cpu/x86/name.h>
7 #include <stdio.h>
8
smbios_cpu_vendor(u8 * start)9 static int smbios_cpu_vendor(u8 *start)
10 {
11 if (cpu_have_cpuid()) {
12 u32 tmp[4];
13 const struct cpuid_result res = cpuid(0);
14 tmp[0] = res.ebx;
15 tmp[1] = res.edx;
16 tmp[2] = res.ecx;
17 tmp[3] = 0;
18 return smbios_add_string(start, (const char *)tmp);
19 } else {
20 return smbios_add_string(start, "Unknown");
21 }
22 }
23
smbios_processor_name(u8 * start)24 static int smbios_processor_name(u8 *start)
25 {
26 u32 tmp[13];
27 const char *str = "Unknown Processor Name";
28 if (cpu_have_cpuid()) {
29 int i;
30 struct cpuid_result res;
31 if (cpu_cpuid_extended_level() >= 0x80000004) {
32 int j = 0;
33 for (i = 0; i < 3; i++) {
34 res = cpuid(0x80000002 + i);
35 tmp[j++] = res.eax;
36 tmp[j++] = res.ebx;
37 tmp[j++] = res.ecx;
38 tmp[j++] = res.edx;
39 }
40 tmp[12] = 0;
41 str = (const char *)tmp;
42 }
43 }
44 return smbios_add_string(start, str);
45 }
46
get_socket_type(void)47 static int get_socket_type(void)
48 {
49 if (CONFIG(CPU_INTEL_SLOT_1))
50 return PROCESSOR_UPGRADE_SLOT_1;
51 if (CONFIG(CPU_INTEL_SOCKET_MPGA604))
52 return PROCESSOR_UPGRADE_SOCKET_MPGA604;
53 if (CONFIG(CPU_INTEL_SOCKET_LGA775))
54 return PROCESSOR_UPGRADE_SOCKET_LGA775;
55 if (CONFIG(SOC_INTEL_ALDERLAKE))
56 return PROCESSOR_UPGRADE_SOCKET_LGA1700;
57 if (CONFIG(SOC_INTEL_METEORLAKE))
58 return PROCESSOR_UPGRADE_OTHER;
59 if (CONFIG(SOC_INTEL_SKYLAKE_SP))
60 return PROCESSOR_UPGRADE_SOCKET_LGA3647_1;
61 if (CONFIG(SOC_INTEL_COOPERLAKE_SP))
62 return PROCESSOR_UPGRADE_SOCKET_LGA4189;
63 if (CONFIG(SOC_INTEL_SAPPHIRERAPIDS_SP))
64 return PROCESSOR_UPGRADE_SOCKET_LGA4677;
65
66 return PROCESSOR_UPGRADE_UNKNOWN;
67 }
68
smbios_processor_family(struct cpuid_result res)69 unsigned int __weak smbios_processor_family(struct cpuid_result res)
70 {
71 return (res.eax > 0) ? SMBIOS_PROCESSOR_FAMILY_PENTIUM_PRO : SMBIOS_PROCESSOR_FAMILY_INTEL486;
72 }
73
get_number_of_caches(size_t max_logical_cpus_sharing_cache)74 static size_t get_number_of_caches(size_t max_logical_cpus_sharing_cache)
75 {
76 size_t number_of_cpus_per_package = 0;
77 size_t max_logical_cpus_per_package = 0;
78 struct cpuid_result res;
79
80 if (!cpu_have_cpuid())
81 return 1;
82
83 res = cpuid(1);
84
85 max_logical_cpus_per_package = (res.ebx >> 16) & 0xff;
86
87 /* Check if it's last level cache */
88 if (max_logical_cpus_sharing_cache == max_logical_cpus_per_package)
89 return 1;
90
91 if (cpuid_get_max_func() >= 0xb) {
92 res = cpuid_ext(0xb, 1);
93 number_of_cpus_per_package = res.ebx & 0xff;
94 } else {
95 number_of_cpus_per_package = max_logical_cpus_per_package;
96 }
97
98 return number_of_cpus_per_package / max_logical_cpus_sharing_cache;
99 }
100
101 #define MAX_CPUS_ENABLED (CONFIG_MAX_CPUS > 0xff ? 0xff : CONFIG_MAX_CPUS)
102
smbios_write_type4(unsigned long * current,int handle)103 int smbios_write_type4(unsigned long *current, int handle)
104 {
105 unsigned int cpu_voltage;
106 struct cpuid_result res;
107 uint16_t characteristics = 0;
108 static unsigned int cnt = 0;
109 char buf[8];
110
111 /* Provide sane defaults even for CPU without CPUID */
112 res.eax = res.edx = 0;
113 res.ebx = 0x10000;
114
115 if (cpu_have_cpuid())
116 res = cpuid(1);
117
118 struct smbios_type4 *t = smbios_carve_table(*current, SMBIOS_PROCESSOR_INFORMATION,
119 sizeof(*t), handle);
120
121 snprintf(buf, sizeof(buf), "CPU%d", cnt++);
122 t->socket_designation = smbios_add_string(t->eos, buf);
123
124 t->processor_id[0] = res.eax;
125 t->processor_id[1] = res.edx;
126 t->processor_manufacturer = smbios_cpu_vendor(t->eos);
127 t->processor_version = smbios_processor_name(t->eos);
128 t->processor_family = smbios_processor_family(res);
129 t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
130 /*
131 * If CPUID leaf 11 is available, calculate "core count" by dividing
132 * SMT_ID (logical processors in a core) by Core_ID (number of cores).
133 * This seems to be the way to arrive to a number of cores mentioned on
134 * ark.intel.com.
135 */
136 if (cpu_have_cpuid() && cpuid_get_max_func() >= 0xb) {
137 uint32_t leaf_b_cores = 0, leaf_b_threads = 0;
138 res = cpuid_ext(0xb, 1);
139 leaf_b_cores = res.ebx;
140 res = cpuid_ext(0xb, 0);
141 leaf_b_threads = res.ebx;
142 /* if hyperthreading is not available, pretend this is 1 */
143 if (leaf_b_threads == 0)
144 leaf_b_threads = 1;
145
146 t->core_count2 = leaf_b_cores / leaf_b_threads;
147 t->core_count = t->core_count2 > 0xff ? 0xff : t->core_count2;
148 t->thread_count2 = leaf_b_cores;
149 t->thread_count = t->thread_count2 > 0xff ? 0xff : t->thread_count2;
150 } else {
151 t->core_count = (res.ebx >> 16) & 0xff;
152 t->core_count2 = t->core_count;
153 t->thread_count2 = t->core_count2;
154 t->thread_count = t->thread_count2;
155 }
156 /* Assume we enable all the cores always, capped only by MAX_CPUS */
157 t->core_enabled = MIN(t->core_count, MAX_CPUS_ENABLED);
158 t->core_enabled2 = MIN(t->core_count2, CONFIG_MAX_CPUS);
159 t->l1_cache_handle = 0xffff;
160 t->l2_cache_handle = 0xffff;
161 t->l3_cache_handle = 0xffff;
162 t->serial_number = smbios_add_string(t->eos, smbios_processor_serial_number());
163 t->status = SMBIOS_PROCESSOR_STATUS_CPU_ENABLED | SMBIOS_PROCESSOR_STATUS_POPULATED;
164 t->processor_upgrade = get_socket_type();
165 if (cpu_have_cpuid() && cpuid_get_max_func() >= 0x16) {
166 t->current_speed = cpuid_eax(0x16); /* base frequency */
167 t->external_clock = cpuid_ecx(0x16);
168 } else {
169 t->current_speed = smbios_cpu_get_current_speed_mhz();
170 t->external_clock = smbios_processor_external_clock();
171 }
172
173 /* This field identifies a capability for the system, not the processor itself. */
174 t->max_speed = smbios_cpu_get_max_speed_mhz();
175
176 if (cpu_have_cpuid()) {
177 res = cpuid(1);
178
179 if ((res.ecx) & BIT(5))
180 characteristics |= BIT(6); /* BIT6: Enhanced Virtualization */
181
182 if ((res.edx) & BIT(28))
183 characteristics |= BIT(4); /* BIT4: Hardware Thread */
184
185 if (cpu_cpuid_extended_level() >= 0x80000001) {
186 res = cpuid(0x80000001);
187
188 if ((res.edx) & BIT(20))
189 characteristics |= BIT(5); /* BIT5: Execute Protection */
190 }
191 }
192 t->processor_characteristics = characteristics | smbios_processor_characteristics();
193 cpu_voltage = smbios_cpu_get_voltage();
194 if (cpu_voltage > 0)
195 t->voltage = 0x80 | cpu_voltage;
196
197 const int len = smbios_full_table_len(&t->header, t->eos);
198 *current += len;
199 return len;
200 }
201
202 /*
203 * Parse the "Deterministic Cache Parameters" as provided by Intel in
204 * leaf 4 or AMD in extended leaf 0x8000001d.
205 *
206 * @param current Pointer to memory address to write the tables to
207 * @param handle Pointer to handle for the tables
208 * @param max_struct_size Pointer to maximum struct size
209 * @param type4 Pointer to SMBIOS type 4 structure
210 */
smbios_write_type7_cache_parameters(unsigned long * current,int * handle,int * max_struct_size,struct smbios_type4 * type4)211 int smbios_write_type7_cache_parameters(unsigned long *current,
212 int *handle,
213 int *max_struct_size,
214 struct smbios_type4 *type4)
215 {
216 unsigned int cnt = CACHE_L1D;
217 int len = 0;
218
219 if (!cpu_have_cpuid())
220 return len;
221
222 enum cpu_type dcache_cpuid = cpu_check_deterministic_cache_cpuid_supported();
223 if (dcache_cpuid == CPUID_TYPE_INVALID || dcache_cpuid == CPUID_COMMAND_UNSUPPORTED) {
224 printk(BIOS_DEBUG, "SMBIOS: Unknown CPU or CPU doesn't support Deterministic "
225 "Cache CPUID leaf\n");
226 return len;
227 }
228
229 while (1) {
230 enum smbios_cache_associativity associativity;
231 enum smbios_cache_type type;
232 struct cpu_cache_info info;
233 if (!fill_cpu_cache_info(cnt++, &info))
234 continue;
235
236 const u8 cache_type = info.type;
237 const u8 level = info.level;
238 const size_t assoc = info.num_ways;
239 const size_t cache_share = info.num_cores_shared;
240 const size_t cache_size = info.size * get_number_of_caches(cache_share);
241
242 if (!cache_type)
243 /* No more caches in the system */
244 break;
245
246 switch (cache_type) {
247 case 1:
248 type = SMBIOS_CACHE_TYPE_DATA;
249 break;
250 case 2:
251 type = SMBIOS_CACHE_TYPE_INSTRUCTION;
252 break;
253 case 3:
254 type = SMBIOS_CACHE_TYPE_UNIFIED;
255 break;
256 default:
257 type = SMBIOS_CACHE_TYPE_UNKNOWN;
258 break;
259 }
260
261 if (info.fully_associative)
262 associativity = SMBIOS_CACHE_ASSOCIATIVITY_FULL;
263 else
264 associativity = smbios_cache_associativity(assoc);
265
266 const int h = (*handle)++;
267
268 update_max(len, *max_struct_size, smbios_write_type7(current, h,
269 level, smbios_cache_sram_type(), associativity,
270 type, cache_size, cache_size));
271
272 if (type4) {
273 switch (level) {
274 case 1:
275 type4->l1_cache_handle = h;
276 break;
277 case 2:
278 type4->l2_cache_handle = h;
279 break;
280 case 3:
281 type4->l3_cache_handle = h;
282 break;
283 }
284 }
285 };
286
287 return len;
288 }
289