drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / src / arch / x86 / smbios.c
blob97d5f242567b488f3a6f38d6915a5f9371c170db
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <smbios.h>
4 #include <console/console.h>
5 #include <arch/cpu.h>
6 #include <cpu/x86/name.h>
7 #include <stdio.h>
9 static int smbios_cpu_vendor(u8 *start)
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");
24 static int smbios_processor_name(u8 *start)
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;
40 tmp[12] = 0;
41 str = (const char *)tmp;
44 return smbios_add_string(start, str);
47 static int get_socket_type(void)
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(CPU_INTEL_SOCKET_LGA1700))
56 return PROCESSOR_UPGRADE_SOCKET_LGA1700;
57 if (CONFIG(CPU_INTEL_SOCKET_LGA4189))
58 return PROCESSOR_UPGRADE_SOCKET_LGA4189;
59 if (CONFIG(CPU_INTEL_SOCKET_LGA4677))
60 return PROCESSOR_UPGRADE_SOCKET_LGA4677;
61 if (CONFIG(CPU_INTEL_SOCKET_LGA3647_1))
62 return PROCESSOR_UPGRADE_SOCKET_LGA3647_1;
63 if (CONFIG(CPU_INTEL_SOCKET_OTHER))
64 return PROCESSOR_UPGRADE_OTHER;
66 return PROCESSOR_UPGRADE_UNKNOWN;
69 unsigned int __weak smbios_processor_family(struct cpuid_result res)
71 return (res.eax > 0) ? SMBIOS_PROCESSOR_FAMILY_PENTIUM_PRO : SMBIOS_PROCESSOR_FAMILY_INTEL486;
74 static size_t get_number_of_caches(size_t max_logical_cpus_sharing_cache)
76 size_t number_of_cpus_per_package = 0;
77 size_t max_logical_cpus_per_package = 0;
78 struct cpuid_result res;
80 if (!cpu_have_cpuid())
81 return 1;
83 res = cpuid(1);
85 max_logical_cpus_per_package = (res.ebx >> 16) & 0xff;
87 /* Check if it's last level cache */
88 if (max_logical_cpus_sharing_cache == max_logical_cpus_per_package)
89 return 1;
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;
98 return number_of_cpus_per_package / max_logical_cpus_sharing_cache;
101 #define MAX_CPUS_ENABLED (CONFIG_MAX_CPUS > 0xff ? 0xff : CONFIG_MAX_CPUS)
103 int smbios_write_type4(unsigned long *current, int handle)
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];
111 /* Provide sane defaults even for CPU without CPUID */
112 res.eax = res.edx = 0;
113 res.ebx = 0x10000;
115 if (cpu_have_cpuid())
116 res = cpuid(1);
118 struct smbios_type4 *t = smbios_carve_table(*current, SMBIOS_PROCESSOR_INFORMATION,
119 sizeof(*t), handle);
121 snprintf(buf, sizeof(buf), "CPU%d", cnt++);
122 t->socket_designation = smbios_add_string(t->eos, buf);
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;
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.
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;
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;
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();
173 /* This field identifies a capability for the system, not the processor itself. */
174 t->max_speed = smbios_cpu_get_max_speed_mhz();
176 if (cpu_have_cpuid()) {
177 res = cpuid(1);
179 if ((res.ecx) & BIT(5))
180 characteristics |= BIT(6); /* BIT6: Enhanced Virtualization */
182 if ((res.edx) & BIT(28))
183 characteristics |= BIT(4); /* BIT4: Hardware Thread */
185 if (cpu_cpuid_extended_level() >= 0x80000001) {
186 res = cpuid(0x80000001);
188 if ((res.edx) & BIT(20))
189 characteristics |= BIT(5); /* BIT5: Execute Protection */
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;
197 const int len = smbios_full_table_len(&t->header, t->eos);
198 *current += len;
199 return len;
203 * Parse the "Deterministic Cache Parameters" as provided by Intel in
204 * leaf 4 or AMD in extended leaf 0x8000001d.
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
211 int smbios_write_type7_cache_parameters(unsigned long *current,
212 int *handle,
213 int *max_struct_size,
214 struct smbios_type4 *type4)
216 unsigned int cnt = CACHE_L1D;
217 int len = 0;
219 if (!cpu_have_cpuid())
220 return len;
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;
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;
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);
242 if (!cache_type)
243 /* No more caches in the system */
244 break;
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;
261 if (info.fully_associative)
262 associativity = SMBIOS_CACHE_ASSOCIATIVITY_FULL;
263 else
264 associativity = smbios_cache_associativity(assoc);
266 const int h = (*handle)++;
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));
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;
287 return len;