xref: /aosp_15_r20/external/coreboot/src/arch/x86/smbios.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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