blob: 9ee977f2aca517a18b07f8d29b488c8cb59162d3 [file] [log] [blame]
Matt Papageorgea21eae02019-11-13 17:00:12 -06001/* SPDX-License-Identifier: GPL-2.0-only */
2
Jason Glenesk276e8652020-12-10 04:22:56 -08003#include <acpi/acpi_crat.h>
Jason Glenesk1916f892020-07-24 02:51:30 -07004#include <acpi/acpi_ivrs.h>
Elyes Haouasf743e0c2022-10-31 13:46:00 +01005#include <acpi/acpi.h>
Felix Held245adca2021-05-04 20:01:46 +02006#include <amdblocks/acpi.h>
Felix Helddd2f3fa2021-02-08 22:23:54 +01007#include <amdblocks/cpu.h>
Felix Helddba3fe72021-02-13 01:05:56 +01008#include <amdblocks/data_fabric.h>
Felix Held604ffa62021-02-12 00:43:20 +01009#include <amdblocks/ioapic.h>
Elyes Haouasf743e0c2022-10-31 13:46:00 +010010#include <cpu/amd/cpuid.h>
Elyes Haouasf743e0c2022-10-31 13:46:00 +010011#include <cpu/cpu.h>
12#include <device/device.h>
Elyes Haouas8823ba12022-12-05 08:48:50 +010013#include <device/mmio.h>
Elyes Haouasf743e0c2022-10-31 13:46:00 +010014#include <device/pci_def.h>
15#include <device/pci_ops.h>
16#include <FspGuids.h>
17#include <soc/acpi.h>
Jason Glenesk276e8652020-12-10 04:22:56 -080018#include <soc/data_fabric.h>
Jason Glenesk1916f892020-07-24 02:51:30 -070019#include <soc/pci_devs.h>
Elyes Haouasf743e0c2022-10-31 13:46:00 +010020#include <stdint.h>
Matt Papageorgea21eae02019-11-13 17:00:12 -060021
Jason Glenesk276e8652020-12-10 04:22:56 -080022static unsigned long gen_crat_hsa_entry(struct acpi_crat_header *crat, unsigned long current)
23{
24 struct crat_hsa_processing_unit *hsa_entry = (struct crat_hsa_processing_unit *)current;
25 memset(hsa_entry, 0, sizeof(struct crat_hsa_processing_unit));
26
27 hsa_entry->flags = CRAT_HSA_PR_FLAG_EN | CRAT_HSA_PR_FLAG_CPU_PRES;
28 hsa_entry->wave_front_size = 4;
29 hsa_entry->num_cpu_cores = get_cpu_count();
30 hsa_entry->length = sizeof(struct crat_hsa_processing_unit);
31 crat->total_entries++;
32
33 current += hsa_entry->length;
34 return current;
35}
36
37static unsigned long create_crat_memory_entry(uint32_t domain, uint64_t region_base,
38 uint64_t region_size, unsigned long current)
39{
40 struct crat_memory *mem_affinity = (struct crat_memory *)current;
41 memset(mem_affinity, 0, sizeof(struct crat_memory));
42
43 mem_affinity->type = CRAT_MEMORY_TYPE;
44 mem_affinity->length = sizeof(struct crat_memory);
45 mem_affinity->proximity_domain = 0;
46 mem_affinity->base_address_low = region_base & 0xffffffff;
47 mem_affinity->base_address_high = (region_base >> 32) & 0xffffffff;
48 mem_affinity->length_low = region_size & 0xffffffff;
49 mem_affinity->length_high = (region_size >> 32) & 0xffffffff;
50 mem_affinity->flags = CRAT_MEM_FLAG_EN;
51 mem_affinity->width = 64;
52
53 current += mem_affinity->length;
54 return current;
55}
56
57static unsigned long gen_crat_memory_entries(struct acpi_crat_header *crat,
58 unsigned long current)
59{
60 uint32_t dram_base_reg, dram_limit_reg, dram_hole_ctl;
61 uint64_t memory_length, memory_base, hole_base, size_below_hole;
62 size_t new_entries = 0;
63
64 for (size_t dram_map_idx = 0; dram_map_idx < PICASSO_NUM_DRAM_REG;
65 dram_map_idx++) {
66 dram_base_reg =
Felix Held18a3c232023-08-03 00:10:03 +020067 data_fabric_read32(DF_DRAM_BASE(dram_map_idx), IOMS0_FABRIC_ID);
Jason Glenesk276e8652020-12-10 04:22:56 -080068
69 if (dram_base_reg & DRAM_BASE_REG_VALID) {
Felix Held18a3c232023-08-03 00:10:03 +020070 dram_limit_reg = data_fabric_read32(DF_DRAM_LIMIT(dram_map_idx),
Jason Glenesk276e8652020-12-10 04:22:56 -080071 IOMS0_FABRIC_ID);
72 memory_length =
73 ((dram_limit_reg & DRAM_LIMIT_ADDR) >> DRAM_LIMIT_ADDR_SHFT) + 1
74 - ((dram_base_reg & DRAM_BASE_ADDR) >> DRAM_BASE_ADDR_SHFT);
75 memory_length = memory_length << 28;
Felix Held7a92e382021-02-16 00:30:15 +010076 memory_base = (uint64_t)(dram_base_reg & DRAM_BASE_ADDR)
Jason Glenesk276e8652020-12-10 04:22:56 -080077 << (28 - DRAM_BASE_ADDR_SHFT);
78
79 if (memory_base == 0) {
80 current =
81 create_crat_memory_entry(0, 0ull, 0xa0000ull, current);
Felix Held6ebcdf32021-10-12 21:39:27 +020082 memory_base = 1 * MiB;
Jason Glenesk276e8652020-12-10 04:22:56 -080083 memory_length = memory_base;
84 new_entries++;
85 }
86
87 if (dram_base_reg & DRAM_BASE_HOLE_EN) {
Felix Heldb25bf342023-08-03 00:57:44 +020088 dram_hole_ctl = data_fabric_read32(DF_DRAM_HOLE_CTL,
Jason Glenesk276e8652020-12-10 04:22:56 -080089 IOMS0_FABRIC_ID);
90 hole_base = (dram_hole_ctl & DRAM_HOLE_CTL_BASE);
91 size_below_hole = hole_base - memory_base;
92 current = create_crat_memory_entry(0, memory_base,
93 size_below_hole, current);
Felix Held7a92e382021-02-16 00:30:15 +010094 memory_length = (uint64_t)(((dram_limit_reg & DRAM_LIMIT_ADDR)
Jason Glenesk276e8652020-12-10 04:22:56 -080095 >> DRAM_LIMIT_ADDR_SHFT)
96 + 1 - 0x10)
97 << 28;
98 memory_base = 0x100000000;
99 new_entries++;
100 }
101
102 current = create_crat_memory_entry(0, memory_base, memory_length,
103 current);
104 new_entries++;
105 }
106 }
107 crat->total_entries += new_entries;
108 return current;
109}
110
111static unsigned long add_crat_cache_entry(struct crat_cache **cache_affinity,
112 unsigned long current)
113{
114 *cache_affinity = (struct crat_cache *)current;
115 memset(*cache_affinity, 0, sizeof(struct crat_cache));
116
117 (*cache_affinity)->type = CRAT_CACHE_TYPE;
118 (*cache_affinity)->length = sizeof(struct crat_cache);
119 (*cache_affinity)->flags = CRAT_CACHE_FLAG_EN | CRAT_CACHE_FLAG_CPU_CACHE;
120
121 current += sizeof(struct crat_cache);
122 return current;
123}
124
125static uint8_t get_associativity(uint32_t encoded_associativity)
126{
127 uint8_t associativity = 0;
128
129 switch (encoded_associativity) {
130 case 0:
131 case 1:
132 case 2:
133 case 3:
134 case 4:
135 return encoded_associativity;
136 case 5:
137 associativity = 6;
138 break;
139 case 6:
140 associativity = 8;
141 break;
142 case 8:
143 associativity = 16;
144 break;
145 case 0xA:
146 associativity = 32;
147 break;
148 case 0xB:
149 associativity = 48;
150 break;
151 case 0xC:
152 associativity = 64;
153 break;
154 case 0xD:
155 associativity = 96;
156 break;
157 case 0xE:
158 associativity = 128;
159 break;
160 case 0xF:
161 associativity = 0xFF;
162 break;
163 default:
164 return 0;
165 }
166
167 return associativity;
168}
169
170static unsigned long gen_crat_cache_entry(struct acpi_crat_header *crat, unsigned long current)
171{
172 size_t total_num_threads, num_threads_sharing0, num_threads_sharing1,
173 num_threads_sharing2, num_threads_sharing3, thread, new_entries;
174 struct cpuid_result cache_props0, cache_props1, cache_props2, cache_props3;
175 uint8_t sibling_mask = 0;
176 uint32_t l1_data_cache_ids, l1_inst_cache_ids, l2_cache_ids, l3_cache_ids;
177 struct crat_cache *cache_affinity = NULL;
178
179 total_num_threads = get_cpu_count();
180
181 cache_props0 = cpuid_ext(CPUID_CACHE_PROPS, CACHE_PROPS_0);
182 cache_props1 = cpuid_ext(CPUID_CACHE_PROPS, CACHE_PROPS_1);
183 cache_props2 = cpuid_ext(CPUID_CACHE_PROPS, CACHE_PROPS_2);
184 cache_props3 = cpuid_ext(CPUID_CACHE_PROPS, CACHE_PROPS_3);
185
186 l1_data_cache_ids = cpuid_ecx(CPUID_L1_TLB_CACHE_IDS);
187 l1_inst_cache_ids = cpuid_edx(CPUID_L1_TLB_CACHE_IDS);
188 l2_cache_ids = cpuid_ecx(CPUID_L2_L3_CACHE_L2_TLB_IDS);
189 l3_cache_ids = cpuid_edx(CPUID_L2_L3_CACHE_L2_TLB_IDS);
190
191 num_threads_sharing0 =
192 ((cache_props0.eax & NUM_SHARE_CACHE_MASK) >> NUM_SHARE_CACHE_SHFT) + 1;
193 num_threads_sharing1 =
194 ((cache_props1.eax & NUM_SHARE_CACHE_MASK) >> NUM_SHARE_CACHE_SHFT) + 1;
195 num_threads_sharing2 =
196 ((cache_props2.eax & NUM_SHARE_CACHE_MASK) >> NUM_SHARE_CACHE_SHFT) + 1;
197 num_threads_sharing3 =
198 ((cache_props3.eax & NUM_SHARE_CACHE_MASK) >> NUM_SHARE_CACHE_SHFT) + 1;
199
200 new_entries = 0;
201 for (thread = 0; thread < total_num_threads; thread++) {
202 /* L1 data cache */
203 if (thread % num_threads_sharing0 == 0) {
204 current = add_crat_cache_entry(&cache_affinity, current);
205 new_entries++;
206
207 cache_affinity->flags |= CRAT_CACHE_FLAG_DATA_CACHE;
208 cache_affinity->proc_id_low = thread;
209 sibling_mask = 1;
210 for (size_t sibling = 1; sibling < num_threads_sharing0; sibling++)
211 sibling_mask = (sibling_mask << 1) + 1;
212 cache_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
213 cache_affinity->cache_properties =
214 (cache_props0.edx & CACHE_INCLUSIVE_MASK) ? 2 : 0;
215 cache_affinity->cache_size =
216 (l1_data_cache_ids & L1_DC_SIZE_MASK) >> L1_DC_SIZE_SHFT;
217 cache_affinity->cache_level = CRAT_L1_CACHE;
218 cache_affinity->lines_per_tag =
219 (l1_data_cache_ids & L1_DC_LINE_TAG_MASK)
220 >> L1_DC_LINE_TAG_SHFT;
221 cache_affinity->cache_line_size =
222 (l1_data_cache_ids & L1_DC_LINE_SIZE_MASK)
223 >> L1_DC_LINE_SIZE_SHFT;
224 cache_affinity->associativity =
225 (l1_data_cache_ids & L1_DC_ASSOC_MASK) >> L1_DC_ASSOC_SHFT;
226 cache_affinity->cache_latency = 1;
227 }
228
229 /* L1 instruction cache */
230 if (thread % num_threads_sharing1 == 0) {
231 current = add_crat_cache_entry(&cache_affinity, current);
232 new_entries++;
233
234 cache_affinity->flags |= CRAT_CACHE_FLAG_INSTR_CACHE;
235 cache_affinity->proc_id_low = thread;
236 sibling_mask = 1;
237 for (size_t sibling = 1; sibling < num_threads_sharing1; sibling++)
238 sibling_mask = (sibling_mask << 1) + 1;
239 cache_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
240 cache_affinity->cache_properties =
241 (cache_props1.edx & CACHE_INCLUSIVE_MASK) ? 2 : 0;
242 cache_affinity->cache_size =
243 (l1_inst_cache_ids & L1_IC_SIZE_MASK) >> L1_IC_SIZE_SHFT;
244 cache_affinity->cache_level = CRAT_L1_CACHE;
245 cache_affinity->lines_per_tag =
246 (l1_inst_cache_ids & L1_IC_LINE_TAG_MASK)
247 >> L1_IC_LINE_TAG_SHFT;
248 cache_affinity->cache_line_size =
249 (l1_inst_cache_ids & L1_IC_LINE_SIZE_MASK)
250 >> L1_IC_LINE_SIZE_SHFT;
251 cache_affinity->associativity =
252 (l1_inst_cache_ids & L1_IC_ASSOC_MASK) >> L1_IC_ASSOC_SHFT;
253 cache_affinity->cache_latency = 1;
254 }
255
256 /* L2 cache */
257 if (thread % num_threads_sharing2 == 0) {
258 current = add_crat_cache_entry(&cache_affinity, current);
259 new_entries++;
260
261 cache_affinity->flags |=
262 CRAT_CACHE_FLAG_DATA_CACHE | CRAT_CACHE_FLAG_INSTR_CACHE;
263 cache_affinity->proc_id_low = thread;
264 sibling_mask = 1;
265 for (size_t sibling = 1; sibling < num_threads_sharing2; sibling++)
266 sibling_mask = (sibling_mask << 1) + 1;
267 cache_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
268 cache_affinity->cache_properties =
269 (cache_props2.edx & CACHE_INCLUSIVE_MASK) ? 2 : 0;
270 cache_affinity->cache_size =
271 (l2_cache_ids & L2_DC_SIZE_MASK) >> L2_DC_SIZE_SHFT;
272 cache_affinity->cache_level = CRAT_L2_CACHE;
273 cache_affinity->lines_per_tag =
274 (l2_cache_ids & L2_DC_LINE_TAG_MASK) >> L2_DC_LINE_TAG_SHFT;
275 cache_affinity->cache_line_size =
276 (l2_cache_ids & L2_DC_LINE_SIZE_MASK) >> L2_DC_LINE_SIZE_SHFT;
277 cache_affinity->associativity = get_associativity(
278 (l2_cache_ids & L2_DC_ASSOC_MASK) >> L2_DC_ASSOC_SHFT);
279 cache_affinity->cache_latency = 1;
280 }
281
282 /* L3 cache */
283 if (thread % num_threads_sharing3 == 0) {
284 current = add_crat_cache_entry(&cache_affinity, current);
285 new_entries++;
286
287 cache_affinity->flags |=
288 CRAT_CACHE_FLAG_DATA_CACHE | CRAT_CACHE_FLAG_INSTR_CACHE;
289 cache_affinity->proc_id_low = thread;
290 sibling_mask = 1;
291 for (size_t sibling = 1; sibling < num_threads_sharing3; sibling++)
292 sibling_mask = (sibling_mask << 1) + 1;
293 cache_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
294 cache_affinity->cache_properties =
295 (cache_props0.edx & CACHE_INCLUSIVE_MASK) ? 2 : 0;
296 cache_affinity->cache_size =
297 ((l3_cache_ids & L3_DC_SIZE_MASK) >> L3_DC_SIZE_SHFT) * 512;
298 cache_affinity->cache_level = CRAT_L3_CACHE;
299 cache_affinity->lines_per_tag =
300 (l3_cache_ids & L3_DC_LINE_TAG_MASK) >> L3_DC_LINE_TAG_SHFT;
301 cache_affinity->cache_line_size =
302 (l3_cache_ids & L3_DC_LINE_SIZE_MASK) >> L3_DC_LINE_SIZE_SHFT;
303 cache_affinity->associativity = get_associativity(
304 (l3_cache_ids & L3_DC_ASSOC_MASK) >> L3_DC_ASSOC_SHFT);
305 cache_affinity->cache_latency = 1;
306 }
307 }
308 crat->total_entries += new_entries;
309 return current;
310}
311
312static uint8_t get_tlb_size(enum tlb_type type, struct crat_tlb *crat_tlb_entry,
313 uint16_t raw_assoc_size)
314{
315 uint8_t tlbsize;
316
317 if (raw_assoc_size >= 256) {
318 tlbsize = (uint8_t)(raw_assoc_size / 256);
319
320 if (type == tlb_2m)
321 crat_tlb_entry->flags |= CRAT_TLB_FLAG_2MB_BASE_256;
322 else if (type == tlb_4k)
323 crat_tlb_entry->flags |= CRAT_TLB_FLAG_4K_BASE_256;
324 else if (type == tlb_1g)
325 crat_tlb_entry->flags |= CRAT_TLB_FLAG_1GB_BASE_256;
326 } else {
327 tlbsize = (uint8_t)(raw_assoc_size);
328 }
329 return tlbsize;
330}
331
332static unsigned long add_crat_tlb_entry(struct crat_tlb **tlb_affinity, unsigned long current)
333{
334 *tlb_affinity = (struct crat_tlb *)current;
335 memset(*tlb_affinity, 0, sizeof(struct crat_tlb));
336
337 (*tlb_affinity)->type = CRAT_TLB_TYPE;
338 (*tlb_affinity)->length = sizeof(struct crat_tlb);
339 (*tlb_affinity)->flags = CRAT_TLB_FLAG_EN | CRAT_TLB_FLAG_CPU_TLB;
340
341 current += sizeof(struct crat_tlb);
342 return current;
343}
344
345static unsigned long gen_crat_tlb_entry(struct acpi_crat_header *crat, unsigned long current)
346{
347 size_t total_num_threads, num_threads_sharing0, num_threads_sharing1,
348 num_threads_sharing2, thread, new_entries;
349 struct cpuid_result cache_props0, cache_props1, cache_props2;
350 uint8_t sibling_mask = 0;
351 uint32_t l1_tlb_2M4M_ids, l1_tlb_4K_ids, l2_tlb_2M4M_ids, l2_tlb_4K_ids, l1_tlb_1G_ids,
352 l2_tlb_1G_ids;
353 struct crat_tlb *tlb_affinity = NULL;
354
355 total_num_threads = get_cpu_count();
356 cache_props0 = cpuid_ext(CPUID_CACHE_PROPS, CACHE_PROPS_0);
357 cache_props1 = cpuid_ext(CPUID_CACHE_PROPS, CACHE_PROPS_1);
358 cache_props2 = cpuid_ext(CPUID_CACHE_PROPS, CACHE_PROPS_2);
359
360 l1_tlb_2M4M_ids = cpuid_eax(CPUID_L1_TLB_CACHE_IDS);
361 l2_tlb_2M4M_ids = cpuid_eax(CPUID_L2_L3_CACHE_L2_TLB_IDS);
362 l1_tlb_4K_ids = cpuid_ebx(CPUID_L1_TLB_CACHE_IDS);
363 l2_tlb_4K_ids = cpuid_ebx(CPUID_L2_L3_CACHE_L2_TLB_IDS);
364 l1_tlb_1G_ids = cpuid_eax(CPUID_TLB_L1L2_1G_IDS);
365 l2_tlb_1G_ids = cpuid_ebx(CPUID_TLB_L1L2_1G_IDS);
366
367 num_threads_sharing0 =
368 ((cache_props0.eax & NUM_SHARE_CACHE_MASK) >> NUM_SHARE_CACHE_SHFT) + 1;
369 num_threads_sharing1 =
370 ((cache_props1.eax & NUM_SHARE_CACHE_MASK) >> NUM_SHARE_CACHE_SHFT) + 1;
371 num_threads_sharing2 =
372 ((cache_props2.eax & NUM_SHARE_CACHE_MASK) >> NUM_SHARE_CACHE_SHFT) + 1;
373
374 new_entries = 0;
375 for (thread = 0; thread < total_num_threads; thread++) {
376
377 /* L1 data TLB */
378 if (thread % num_threads_sharing0 == 0) {
379 current = add_crat_tlb_entry(&tlb_affinity, current);
380 new_entries++;
381
382 tlb_affinity->flags |= CRAT_TLB_FLAG_DATA_TLB;
383 tlb_affinity->proc_id_low = thread;
384 sibling_mask = 1;
385 for (size_t sibling = 1; sibling < num_threads_sharing0; sibling++)
386 sibling_mask = (sibling_mask << 1) + 1;
387 tlb_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
388 tlb_affinity->tlb_level = CRAT_L1_CACHE;
389
390 tlb_affinity->data_tlb_2mb_assoc =
391 (l1_tlb_2M4M_ids & L1_DAT_TLB_2M4M_ASSOC_MASK)
392 >> L1_DAT_TLB_2M4M_ASSOC_SHFT;
393 tlb_affinity->data_tlb_2mb_size =
394 get_tlb_size(tlb_2m, tlb_affinity,
395 (l1_tlb_2M4M_ids & L1_DAT_TLB_2M4M_SIZE_MASK)
396 >> L1_DAT_TLB_2M4M_SIZE_SHFT);
397
398 tlb_affinity->data_tlb_4k_assoc =
399 (l1_tlb_4K_ids & L1_DAT_TLB_4K_ASSOC_MASK)
400 >> L1_DAT_TLB_4K_ASSOC_SHFT;
401 tlb_affinity->data_tlb_4k_size =
402 get_tlb_size(tlb_4k, tlb_affinity,
403 (l1_tlb_4K_ids & L1_DAT_TLB_4K_SIZE_MASK)
404 >> L1_DAT_TLB_4K_SIZE_SHFT);
405
406 tlb_affinity->data_tlb_1g_assoc =
407 (l1_tlb_1G_ids & L1_DAT_TLB_1G_ASSOC_MASK)
408 >> L1_DAT_TLB_1G_ASSOC_SHFT;
409 tlb_affinity->data_tlb_1g_size =
410 get_tlb_size(tlb_1g, tlb_affinity,
411 (l1_tlb_1G_ids & L1_DAT_TLB_1G_SIZE_MASK)
412 >> L1_DAT_TLB_1G_SIZE_SHFT);
413 }
414
415 /* L1 instruction TLB */
416 if (thread % num_threads_sharing1 == 0) {
417 current = add_crat_tlb_entry(&tlb_affinity, current);
418 new_entries++;
419
420 tlb_affinity->flags |= CRAT_TLB_FLAG_INSTR_TLB;
421 tlb_affinity->proc_id_low = thread;
422 sibling_mask = 1;
423 for (size_t sibling = 1; sibling < num_threads_sharing1; sibling++)
424 sibling_mask = (sibling_mask << 1) + 1;
425 tlb_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
426 tlb_affinity->tlb_level = CRAT_L1_CACHE;
427 tlb_affinity->instr_tlb_2mb_assoc =
428 (l1_tlb_2M4M_ids & L1_INST_TLB_2M4M_ASSOC_MASK)
429 >> L1_INST_TLB_2M4M_ASSOC_SHFT;
430 tlb_affinity->instr_tlb_2mb_size =
431 get_tlb_size(tlb_2m, tlb_affinity,
432 (l1_tlb_2M4M_ids & L1_INST_TLB_2M4M_SIZE_MASK)
433 >> L1_INST_TLB_2M4M_SIZE_SHFT);
434
435 tlb_affinity->instr_tlb_4k_assoc =
436 (l1_tlb_4K_ids & L1_INST_TLB_4K_ASSOC_MASK)
437 >> L1_INST_TLB_4K_ASSOC_SHFT;
438 tlb_affinity->instr_tlb_4k_size =
439 get_tlb_size(tlb_4k, tlb_affinity,
440 (l1_tlb_4K_ids & L1_INST_TLB_4K_SIZE_MASK)
441 >> L1_INST_TLB_4K_SIZE_SHFT);
442
443 tlb_affinity->instr_tlb_1g_assoc =
444 (l1_tlb_1G_ids & L1_INST_TLB_1G_ASSOC_MASK)
445 >> L1_INST_TLB_1G_ASSOC_SHFT;
446 tlb_affinity->instr_tlb_1g_size =
447 get_tlb_size(tlb_1g, tlb_affinity,
448 (l1_tlb_1G_ids & L1_INST_TLB_1G_SIZE_MASK)
449 >> L1_INST_TLB_1G_SIZE_SHFT);
450 }
451
452 /* L2 Data TLB */
453 if (thread % num_threads_sharing2 == 0) {
454 current = add_crat_tlb_entry(&tlb_affinity, current);
455 new_entries++;
456
457 tlb_affinity->flags |= CRAT_TLB_FLAG_DATA_TLB;
458 tlb_affinity->proc_id_low = thread;
459 sibling_mask = 1;
460 for (size_t sibling = 1; sibling < num_threads_sharing2; sibling++)
461 sibling_mask = (sibling_mask << 1) + 1;
462 tlb_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
463 tlb_affinity->tlb_level = CRAT_L2_CACHE;
464 tlb_affinity->data_tlb_2mb_assoc =
465 (l2_tlb_2M4M_ids & L2_DAT_TLB_2M4M_ASSOC_MASK)
466 >> L2_DAT_TLB_2M4M_ASSOC_SHFT;
467 tlb_affinity->data_tlb_2mb_size =
468 get_tlb_size(tlb_2m, tlb_affinity,
469 (l2_tlb_2M4M_ids & L2_DAT_TLB_2M4M_SIZE_MASK)
470 >> L2_DAT_TLB_2M4M_SIZE_SHFT);
471
472 tlb_affinity->data_tlb_4k_assoc =
473 get_associativity((l2_tlb_4K_ids & L2_DAT_TLB_2M4M_ASSOC_MASK)
474 >> L2_DAT_TLB_4K_ASSOC_SHFT);
475 tlb_affinity->data_tlb_4k_size =
476 get_tlb_size(tlb_4k, tlb_affinity,
477 (l2_tlb_2M4M_ids & L2_DAT_TLB_4K_SIZE_MASK)
478 >> L2_DAT_TLB_4K_SIZE_SHFT);
479
480 tlb_affinity->data_tlb_1g_assoc =
481 get_associativity((l2_tlb_1G_ids & L2_DAT_TLB_1G_ASSOC_MASK)
482 >> L2_DAT_TLB_1G_ASSOC_SHFT);
483 tlb_affinity->data_tlb_1g_size =
484 get_tlb_size(tlb_1g, tlb_affinity,
485 (l2_tlb_1G_ids & L2_DAT_TLB_1G_SIZE_MASK)
486 >> L2_DAT_TLB_1G_SIZE_SHFT);
487 }
488
489 /* L2 Instruction TLB */
490 if (thread % num_threads_sharing2 == 0) {
491 current = add_crat_tlb_entry(&tlb_affinity, current);
492 new_entries++;
493
494 tlb_affinity->flags |= CRAT_TLB_FLAG_INSTR_TLB;
495 tlb_affinity->proc_id_low = thread;
496 sibling_mask = 1;
497 for (size_t sibling = 1; sibling < num_threads_sharing2; sibling++)
498 sibling_mask = (sibling_mask << 1) + 1;
499 tlb_affinity->sibling_map[thread / 8] = sibling_mask << (thread % 8);
500 tlb_affinity->tlb_level = CRAT_L2_CACHE;
501 tlb_affinity->instr_tlb_2mb_assoc = get_associativity(
502 (l2_tlb_2M4M_ids & L2_INST_TLB_2M4M_ASSOC_MASK)
503 >> L2_INST_TLB_2M4M_ASSOC_SHFT);
504 tlb_affinity->instr_tlb_2mb_size =
505 get_tlb_size(tlb_2m, tlb_affinity,
506 (l2_tlb_2M4M_ids & L2_INST_TLB_2M4M_SIZE_MASK)
507 >> L2_INST_TLB_2M4M_SIZE_SHFT);
508
509 tlb_affinity->instr_tlb_4k_assoc =
510 get_associativity((l2_tlb_4K_ids & L2_INST_TLB_4K_ASSOC_MASK)
511 >> L2_INST_TLB_4K_ASSOC_SHFT);
512 tlb_affinity->instr_tlb_4k_size =
513 get_tlb_size(tlb_4k, tlb_affinity,
514 (l2_tlb_4K_ids & L2_INST_TLB_4K_SIZE_MASK)
515 >> L2_INST_TLB_4K_SIZE_SHFT);
516
517 tlb_affinity->instr_tlb_1g_assoc =
518 get_associativity((l2_tlb_1G_ids & L2_INST_TLB_1G_ASSOC_MASK)
519 >> L2_INST_TLB_1G_ASSOC_SHFT);
520 tlb_affinity->instr_tlb_1g_size =
521 get_tlb_size(tlb_1g, tlb_affinity,
522 (l2_tlb_1G_ids & L2_INST_TLB_1G_SIZE_MASK)
523 >> L2_INST_TLB_1G_SIZE_SHFT);
524 }
525 }
526
527 crat->total_entries += new_entries;
528 return current;
529}
530
531static unsigned long acpi_fill_crat(struct acpi_crat_header *crat, unsigned long current)
532{
533 current = gen_crat_hsa_entry(crat, current);
534 current = gen_crat_memory_entries(crat, current);
535 current = gen_crat_cache_entry(crat, current);
536 current = gen_crat_tlb_entry(crat, current);
537 crat->num_nodes++;
538
539 return current;
540}
541
Matt Papageorgea21eae02019-11-13 17:00:12 -0600542uintptr_t agesa_write_acpi_tables(const struct device *device, uintptr_t current,
543 acpi_rsdp_t *rsdp)
544{
Jason Glenesk1916f892020-07-24 02:51:30 -0700545 acpi_ivrs_t *ivrs;
Jason Glenesk276e8652020-12-10 04:22:56 -0800546 struct acpi_crat_header *crat;
Jason Glenesk1916f892020-07-24 02:51:30 -0700547
Jason Glenesk276e8652020-12-10 04:22:56 -0800548 /* CRAT */
Felix Heldf03706a2023-01-17 00:37:13 +0100549 current = acpi_align_current(current);
Jason Glenesk276e8652020-12-10 04:22:56 -0800550 crat = (struct acpi_crat_header *)current;
551 acpi_create_crat(crat, acpi_fill_crat);
552 current += crat->header.length;
553 acpi_add_table(rsdp, crat);
Matt Papageorgea21eae02019-11-13 17:00:12 -0600554
Felix Heldafc49782021-05-04 21:17:50 +0200555 /* add ALIB SSDT from HOB */
Felix Held8f1e0042023-01-17 00:39:06 +0100556 current = acpi_align_current(current);
Felix Held245adca2021-05-04 20:01:46 +0200557 current = add_agesa_fsp_acpi_table(AMD_FSP_ACPI_ALIB_HOB_GUID, "ALIB", rsdp, current);
Jason Glenesk1916f892020-07-24 02:51:30 -0700558
559 /* IVRS */
Felix Heldf03706a2023-01-17 00:37:13 +0100560 current = acpi_align_current(current);
Elyes Haouas55d0f402022-07-16 09:53:05 +0200561 ivrs = (acpi_ivrs_t *)current;
Jason Glenesk1916f892020-07-24 02:51:30 -0700562 acpi_create_ivrs(ivrs, acpi_fill_ivrs);
563 current += ivrs->header.length;
564 acpi_add_table(rsdp, ivrs);
Matt Papageorgea21eae02019-11-13 17:00:12 -0600565
566 /* Add SRAT, MSCT, SLIT if needed in the future */
567
568 return current;
569}