blob: b63c940ea882f6a9ede06c4d8dfb04a631f2d5da [file] [log] [blame]
Patrick Georgi11f00792020-03-04 15:10:45 +01001/* SPDX-License-Identifier: GPL-2.0-only */
Sven Schnelle164bcfd2011-08-14 20:56:34 +02002
Sven Schnelle164bcfd2011-08-14 20:56:34 +02003#include <string.h>
4#include <smbios.h>
5#include <console/console.h>
Sven Schnelle164bcfd2011-08-14 20:56:34 +02006#include <arch/cpu.h>
7#include <cpu/x86/name.h>
Angel Ponsd62a5012021-06-28 17:18:06 +02008
Konstantin Aladyshevd0df1d72017-08-01 15:52:46 +03009static int smbios_cpu_vendor(u8 *start)
Sven Schnelle164bcfd2011-08-14 20:56:34 +020010{
Rudolf Marek06253cd2012-02-25 23:51:12 +010011 if (cpu_have_cpuid()) {
Ryan Salsamendi1b5eda02017-06-11 18:50:32 -070012 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");
Rudolf Marek06253cd2012-02-25 23:51:12 +010021 }
Sven Schnelle164bcfd2011-08-14 20:56:34 +020022}
23
Konstantin Aladyshevd0df1d72017-08-01 15:52:46 +030024static int smbios_processor_name(u8 *start)
Sven Schnelle164bcfd2011-08-14 20:56:34 +020025{
Nico Huberaa9643e2017-06-20 14:49:04 +020026 u32 tmp[13];
Ryan Salsamendi1b5eda02017-06-11 18:50:32 -070027 const char *str = "Unknown Processor Name";
Rudolf Marek06253cd2012-02-25 23:51:12 +010028 if (cpu_have_cpuid()) {
Ryan Salsamendi1b5eda02017-06-11 18:50:32 -070029 int i;
Felix Held73e9ac62023-02-20 17:46:41 +010030 struct cpuid_result res;
31 if (cpu_cpuid_extended_level() >= 0x80000004) {
Ryan Salsamendi1b5eda02017-06-11 18:50:32 -070032 int j = 0;
Rudolf Marek06253cd2012-02-25 23:51:12 +010033 for (i = 0; i < 3; i++) {
34 res = cpuid(0x80000002 + i);
Ryan Salsamendi1b5eda02017-06-11 18:50:32 -070035 tmp[j++] = res.eax;
36 tmp[j++] = res.ebx;
37 tmp[j++] = res.ecx;
38 tmp[j++] = res.edx;
Rudolf Marek06253cd2012-02-25 23:51:12 +010039 }
Ryan Salsamendi1b5eda02017-06-11 18:50:32 -070040 tmp[12] = 0;
41 str = (const char *)tmp;
Rudolf Marek06253cd2012-02-25 23:51:12 +010042 }
Sven Schnelle164bcfd2011-08-14 20:56:34 +020043 }
Ryan Salsamendi1b5eda02017-06-11 18:50:32 -070044 return smbios_add_string(start, str);
Sven Schnelle164bcfd2011-08-14 20:56:34 +020045}
46
Elyes HAOUAS28fa33c2019-01-25 13:46:43 +010047static int get_socket_type(void)
48{
49 if (CONFIG(CPU_INTEL_SLOT_1))
Li, Jinchengaa990122023-01-03 15:43:40 +080050 return PROCESSOR_UPGRADE_SLOT_1;
Kyösti Mälkki7b73e8522022-11-08 04:43:41 +000051 if (CONFIG(CPU_INTEL_SOCKET_MPGA604))
Li, Jinchengaa990122023-01-03 15:43:40 +080052 return PROCESSOR_UPGRADE_SOCKET_MPGA604;
Elyes HAOUAS28fa33c2019-01-25 13:46:43 +010053 if (CONFIG(CPU_INTEL_SOCKET_LGA775))
Li, Jinchengaa990122023-01-03 15:43:40 +080054 return PROCESSOR_UPGRADE_SOCKET_LGA775;
Zhixing Ma42bb7df2022-09-30 14:22:41 -070055 if (CONFIG(SOC_INTEL_ALDERLAKE))
Li, Jinchengaa990122023-01-03 15:43:40 +080056 return PROCESSOR_UPGRADE_SOCKET_LGA1700;
Jay Patelb7da7d52023-03-13 11:29:59 -070057 if (CONFIG(SOC_INTEL_METEORLAKE))
58 return PROCESSOR_UPGRADE_OTHER;
David Hendricks60416992023-01-28 15:35:37 -080059 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;
Christian Walter55129b32022-09-08 13:17:50 +020063 if (CONFIG(SOC_INTEL_SAPPHIRERAPIDS_SP))
64 return PROCESSOR_UPGRADE_SOCKET_LGA4677;
Elyes HAOUAS28fa33c2019-01-25 13:46:43 +010065
Li, Jinchengaa990122023-01-03 15:43:40 +080066 return PROCESSOR_UPGRADE_UNKNOWN;
Elyes HAOUAS28fa33c2019-01-25 13:46:43 +010067}
68
Morgan Jang92bcc4f2020-07-24 10:36:18 +080069unsigned int __weak smbios_processor_family(struct cpuid_result res)
70{
71 return (res.eax > 0) ? 0x0c : 0x6;
72}
73
Subrata Banike2b5fee2021-07-23 21:02:45 +053074static size_t get_number_of_caches(size_t max_logical_cpus_sharing_cache)
Morgan Jang8ae391d2020-10-06 16:26:17 +080075{
Morgan Jang8ae391d2020-10-06 16:26:17 +080076 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
Morgan Jang8ae391d2020-10-06 16:26:17 +080087 /* 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
Arthur Heymans13c8dc52022-04-07 22:08:23 +0200101#define MAX_CPUS_ENABLED (CONFIG_MAX_CPUS > 0xff ? 0xff : CONFIG_MAX_CPUS)
102
Benjamin Doronea13dc32023-06-20 12:21:27 -0400103int smbios_write_type4(unsigned long *current, int handle)
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200104{
Patrick Rudolphb01ac7e2020-07-26 14:23:37 +0200105 unsigned int cpu_voltage;
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200106 struct cpuid_result res;
Morgan Jang92bcc4f2020-07-24 10:36:18 +0800107 uint16_t characteristics = 0;
Tim Chu27bf0c82020-09-16 00:34:08 -0700108 static unsigned int cnt = 0;
109 char buf[8];
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200110
Rudolf Marek06253cd2012-02-25 23:51:12 +0100111 /* Provide sane defaults even for CPU without CPUID */
112 res.eax = res.edx = 0;
113 res.ebx = 0x10000;
114
Lee Leahy9c7c6f72017-03-16 11:24:09 -0700115 if (cpu_have_cpuid())
Rudolf Marek06253cd2012-02-25 23:51:12 +0100116 res = cpuid(1);
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200117
Angel Ponsd62a5012021-06-28 17:18:06 +0200118 struct smbios_type4 *t = smbios_carve_table(*current, SMBIOS_PROCESSOR_INFORMATION,
119 sizeof(*t), handle);
Tim Chu27bf0c82020-09-16 00:34:08 -0700120
121 snprintf(buf, sizeof(buf), "CPU%d", cnt++);
122 t->socket_designation = smbios_add_string(t->eos, buf);
123
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200124 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);
Morgan Jang92bcc4f2020-07-24 10:36:18 +0800128 t->processor_family = smbios_processor_family(res);
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200129 t->processor_type = 3; /* System Processor */
Andrey Petrov515ef382019-11-15 13:19:08 -0800130 /*
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 */
Fabio Aiuto0805c702022-08-19 17:25:25 +0200143 if (leaf_b_threads == 0)
Andrey Petrov515ef382019-11-15 13:19:08 -0800144 leaf_b_threads = 1;
Fabio Aiuto0805c702022-08-19 17:25:25 +0200145
Patrick Rudolph7a835822020-07-22 16:00:53 +0200146 t->core_count2 = leaf_b_cores / leaf_b_threads;
147 t->core_count = t->core_count2 > 0xff ? 0xff : t->core_count2;
Francois Toguo597922e2019-03-27 18:13:07 -0700148 t->thread_count2 = leaf_b_cores;
149 t->thread_count = t->thread_count2 > 0xff ? 0xff : t->thread_count2;
Andrey Petrov515ef382019-11-15 13:19:08 -0800150 } else {
151 t->core_count = (res.ebx >> 16) & 0xff;
Patrick Rudolph7a835822020-07-22 16:00:53 +0200152 t->core_count2 = t->core_count;
153 t->thread_count2 = t->core_count2;
Francois Toguo597922e2019-03-27 18:13:07 -0700154 t->thread_count = t->thread_count2;
Andrey Petrov515ef382019-11-15 13:19:08 -0800155 }
Andrey Petrov2e032f02019-10-23 15:31:51 -0700156 /* Assume we enable all the cores always, capped only by MAX_CPUS */
Arthur Heymans13c8dc52022-04-07 22:08:23 +0200157 t->core_enabled = MIN(t->core_count, MAX_CPUS_ENABLED);
Patrick Rudolph7a835822020-07-22 16:00:53 +0200158 t->core_enabled2 = MIN(t->core_count2, CONFIG_MAX_CPUS);
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200159 t->l1_cache_handle = 0xffff;
160 t->l2_cache_handle = 0xffff;
161 t->l3_cache_handle = 0xffff;
Johnny Lind3440542020-01-30 18:21:22 +0800162 t->serial_number = smbios_add_string(t->eos, smbios_processor_serial_number());
Angel Ponsbf2f91c2020-07-29 18:14:59 +0200163 t->status = SMBIOS_PROCESSOR_STATUS_CPU_ENABLED | SMBIOS_PROCESSOR_STATUS_POPULATED;
Elyes HAOUAS28fa33c2019-01-25 13:46:43 +0100164 t->processor_upgrade = get_socket_type();
Andrey Petrov2e032f02019-10-23 15:31:51 -0700165 if (cpu_have_cpuid() && cpuid_get_max_func() >= 0x16) {
Andrey Petrov2e032f02019-10-23 15:31:51 -0700166 t->current_speed = cpuid_eax(0x16); /* base frequency */
Morgan Jang92bcc4f2020-07-24 10:36:18 +0800167 t->external_clock = cpuid_ecx(0x16);
Andrey Petrov2e032f02019-10-23 15:31:51 -0700168 } else {
Andrey Petrov2e032f02019-10-23 15:31:51 -0700169 t->current_speed = smbios_cpu_get_current_speed_mhz();
Morgan Jang92bcc4f2020-07-24 10:36:18 +0800170 t->external_clock = smbios_processor_external_clock();
Andrey Petrov2e032f02019-10-23 15:31:51 -0700171 }
Morgan Jang92bcc4f2020-07-24 10:36:18 +0800172
Tim Chu40d45992020-12-14 21:44:40 -0800173 /* This field identifies a capability for the system, not the processor itself. */
174 t->max_speed = smbios_cpu_get_max_speed_mhz();
175
Morgan Jang92bcc4f2020-07-24 10:36:18 +0800176 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 (((cpuid_eax(0x80000000) - 0x80000000) + 1) > 2) {
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();
Patrick Rudolphb01ac7e2020-07-26 14:23:37 +0200193 cpu_voltage = smbios_cpu_get_voltage();
194 if (cpu_voltage > 0)
195 t->voltage = 0x80 | cpu_voltage;
Morgan Jang92bcc4f2020-07-24 10:36:18 +0800196
Angel Ponsa37701a2021-06-28 17:36:53 +0200197 const int len = smbios_full_table_len(&t->header, t->eos);
Sven Schnelle164bcfd2011-08-14 20:56:34 +0200198 *current += len;
199 return len;
200}
201
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100202/*
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100203 * 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
Patrick Rudolph15589b42019-03-30 17:51:06 +0100209 * @param type4 Pointer to SMBIOS type 4 structure
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100210 */
Benjamin Doronea13dc32023-06-20 12:21:27 -0400211int smbios_write_type7_cache_parameters(unsigned long *current,
212 int *handle,
213 int *max_struct_size,
214 struct smbios_type4 *type4)
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100215{
Subrata Banike2b5fee2021-07-23 21:02:45 +0530216 unsigned int cnt = CACHE_L1D;
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100217 int len = 0;
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100218
219 if (!cpu_have_cpuid())
220 return len;
221
Subrata Banik6efc4aa2021-09-01 12:40:47 +0530222 enum cpu_type dcache_cpuid = cpu_check_deterministic_cache_cpuid_supported();
223 if (dcache_cpuid == CPUID_TYPE_INVALID || dcache_cpuid == CPUID_COMMAND_UNSUPPORTED) {
Subrata Banik5586c792021-09-02 13:17:18 +0530224 printk(BIOS_DEBUG, "SMBIOS: Unknown CPU or CPU doesn't support Deterministic "
225 "Cache CPUID leaf\n");
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100226 return len;
227 }
228
229 while (1) {
230 enum smbios_cache_associativity associativity;
231 enum smbios_cache_type type;
Subrata Banike2b5fee2021-07-23 21:02:45 +0530232 struct cpu_cache_info info;
233 if (!fill_cpu_cache_info(cnt++, &info))
234 continue;
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100235
Subrata Banike2b5fee2021-07-23 21:02:45 +0530236 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);
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100241
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
Subrata Banike2b5fee2021-07-23 21:02:45 +0530261 if (info.fully_associative)
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100262 associativity = SMBIOS_CACHE_ASSOCIATIVITY_FULL;
263 else
264 associativity = smbios_cache_associativity(assoc);
265
Patrick Rudolph15589b42019-03-30 17:51:06 +0100266 const int h = (*handle)++;
267
268 update_max(len, *max_struct_size, smbios_write_type7(current, h,
Morgan Jang8ae391d2020-10-06 16:26:17 +0800269 level, smbios_cache_sram_type(), associativity,
Patrick Rudolph15589b42019-03-30 17:51:06 +0100270 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 }
Patrick Rudolphfc5b8092019-03-30 17:37:28 +0100285 };
286
287 return len;
288}