blob: 8042057e075c1a5ab39139897226d5e4963d6843 [file] [log] [blame]
Benjamin Doron69bc2cc2023-06-14 19:03:04 -04001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <arch/cache.h>
4#include <arch/lib_helpers.h>
5#include <arch/smc.h>
6#include <console/console.h>
7#include <smbios.h>
Elyes Haouasbdd03c22024-05-27 11:20:07 +02008#include <stdio.h>
Benjamin Doron69bc2cc2023-06-14 19:03:04 -04009#include <string.h>
10
11static void smbios_processor_id(u32 *processor_id)
12{
13 uint32_t jep106code, soc_revision;
14 uint64_t midr_el1;
15
16 if (smccc_supports_arch_soc_id()) {
17 smccc_arch_soc_id(&jep106code, &soc_revision);
18 processor_id[0] = jep106code;
19 processor_id[1] = soc_revision;
20 } else {
21 midr_el1 = raw_read_midr_el1();
22 processor_id[0] = midr_el1;
23 processor_id[1] = 0;
24 }
25}
26
27static int smbios_processor_manufacturer(u8 *start)
28{
29 char midr_el1_implementer;
30 char buf[32];
31
32 // [31:24] - Implementer code
33 midr_el1_implementer = (raw_read_midr_el1() & 0xff000000) >> 24;
34
35 snprintf(buf, sizeof(buf), "CPU implementer %x", midr_el1_implementer);
36 return smbios_add_string(start, buf);
37}
38
39static int smbios_processor_name(u8 *start)
40{
41 uint16_t midr_el1_partnumber;
42 char buf[32];
43
44 // [15:4] - PartNum
45 midr_el1_partnumber = (raw_read_midr_el1() & 0xfff0) >> 4;
46
47 snprintf(buf, sizeof(buf), "ARMv8 Processor rev %d", midr_el1_partnumber);
48 return smbios_add_string(start, buf);
49}
50
51#define MAX_CPUS_ENABLED(cpus) (cpus > 0xff ? 0xff : cpus)
52
53/* NOTE: Not handling big.LITTLE clusters. Consider using MP services (not yet) or the DSU. */
54int smbios_write_type4(unsigned long *current, int handle)
55{
56 static unsigned int cnt = 0;
57 char buf[8];
58 uint16_t characteristics = 0;
59 unsigned int cpu_voltage;
60
61 struct smbios_type4 *t = smbios_carve_table(*current, SMBIOS_PROCESSOR_INFORMATION,
62 sizeof(*t), handle);
63
64 snprintf(buf, sizeof(buf), "CPU%d", cnt++);
65 t->socket_designation = smbios_add_string(t->eos, buf);
66
67 smbios_processor_id(t->processor_id);
68 t->processor_manufacturer = smbios_processor_manufacturer(t->eos);
69 t->processor_version = smbios_processor_name(t->eos);
70 t->processor_family = 0xfe; /* Use processor_family2 field */
71 t->processor_family2 = 0x101; /* ARMv8 */
Elyes Haouasb72f5942024-05-25 11:17:15 +020072 t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
Benjamin Doron69bc2cc2023-06-14 19:03:04 -040073
74 smbios_cpu_get_core_counts(&t->core_count2, &t->thread_count2);
75 t->core_count = MAX_CPUS_ENABLED(t->core_count2);
76 t->thread_count = MAX_CPUS_ENABLED(t->thread_count2);
77 /* Assume we always enable all cores */
78 t->core_enabled = t->core_count;
79 t->core_enabled2 = t->core_count2;
80 t->l1_cache_handle = 0xffff;
81 t->l2_cache_handle = 0xffff;
82 t->l3_cache_handle = 0xffff;
83 t->serial_number = smbios_add_string(t->eos, smbios_processor_serial_number());
84 t->status = SMBIOS_PROCESSOR_STATUS_CPU_ENABLED | SMBIOS_PROCESSOR_STATUS_POPULATED;
85 t->processor_upgrade = PROCESSOR_UPGRADE_UNKNOWN;
86
87 t->external_clock = smbios_processor_external_clock();
88 if (t->external_clock == 0)
89 t->external_clock = (raw_read_cntfrq_el0() / 1000 / 1000);
90
91 t->current_speed = smbios_cpu_get_current_speed_mhz();
92
93 /* This field identifies a capability for the system, not the processor itself. */
94 t->max_speed = smbios_cpu_get_max_speed_mhz();
95
96 /* TODO: Are "Enhanced Virtualization" (by EL2) and "Power/Performance Control" supported? */
97 characteristics |= PROCESSOR_64BIT_CAPABLE;
98 characteristics |= BIT(5); /* Execute Protection */
99
100 if (t->core_count > 1)
101 characteristics |= PROCESSOR_MULTI_CORE;
102 if (t->thread_count > 1)
103 characteristics |= BIT(4); /* BIT4: Hardware Thread */
104 if (smccc_supports_arch_soc_id())
105 characteristics |= BIT(9); /* Arm64 SoC ID */
106
107 t->processor_characteristics = characteristics | smbios_processor_characteristics();
108
109 cpu_voltage = smbios_cpu_get_voltage();
110 if (cpu_voltage > 0)
111 t->voltage = 0x80 | cpu_voltage;
112
113 const int len = smbios_full_table_len(&t->header, t->eos);
114 *current += len;
115 return len;
116}
117
118int smbios_write_type7_cache_parameters(unsigned long *current,
119 int *handle,
120 int *max_struct_size,
121 struct smbios_type4 *type4)
122{
123 enum cache_level level = CACHE_L1;
124 int h;
125 int len = 0;
126
127 while (1) {
128 enum smbios_cache_type type;
129 struct cache_info info;
130
131 const u8 cache_type = cpu_get_cache_type(level);
132 /* No more caches in the system */
133 if (!cache_type)
134 break;
135
136 switch (cache_type) {
137 case CACHE_INSTRUCTION:
138 type = SMBIOS_CACHE_TYPE_INSTRUCTION;
139 cpu_get_cache_info(level, cache_type, &info);
140 break;
141 case CACHE_DATA:
142 type = SMBIOS_CACHE_TYPE_DATA;
143 cpu_get_cache_info(level, cache_type, &info);
144 break;
145 case CACHE_SEPARATE:
146 type = SMBIOS_CACHE_TYPE_DATA;
147 cpu_get_cache_info(level, CACHE_DATA, &info);
148 h = (*handle)++;
149 update_max(len, *max_struct_size, smbios_write_type7(current, h,
150 level, smbios_cache_sram_type(), smbios_cache_associativity(info.associativity),
151 type, info.size, info.size));
152
153 type = SMBIOS_CACHE_TYPE_INSTRUCTION;
154 cpu_get_cache_info(level, CACHE_INSTRUCTION, &info);
155 break;
156 case CACHE_UNIFIED:
157 type = SMBIOS_CACHE_TYPE_UNIFIED;
158 cpu_get_cache_info(level, cache_type, &info);
159 break;
160 default:
161 type = SMBIOS_CACHE_TYPE_UNKNOWN;
162 info.size = info.associativity = 0;
163 break;
164 }
165
166 h = (*handle)++;
167 update_max(len, *max_struct_size, smbios_write_type7(current, h,
168 level, smbios_cache_sram_type(), smbios_cache_associativity(info.associativity),
169 type, info.size, info.size));
170
171 if (type4) {
172 switch (level) {
173 case 1:
174 type4->l1_cache_handle = h;
175 break;
176 case 2:
177 type4->l2_cache_handle = h;
178 break;
179 case 3:
180 type4->l3_cache_handle = h;
181 break;
182 default:
183 break;
184 }
185 }
186
187 level++;
188 }
189
190 return len;
191}