• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <arch/vga.h>
4 #include <cbmem.h>
5 #include <console/console.h>
6 #include <cpu/x86/lapic_def.h>
7 #include <device/pci.h>
8 #include <device/pci_ids.h>
9 #include <soc/acpi.h>
10 #include <soc/chip_common.h>
11 #include <soc/iomap.h>
12 #include <soc/pci_devs.h>
13 #include <soc/ramstage.h>
14 #include <soc/util.h>
15 #include <fsp/util.h>
16 #include <security/intel/txt/txt_platform.h>
17 #include <security/intel/txt/txt.h>
18 #include <soc/config.h>
19 #include <soc/numa.h>
20 #include <soc/soc_util.h>
21 #include <stdint.h>
22 
23 struct proximity_domains pds = {
24 	.num_pds = 0,
25 	.pds = NULL,
26 };
27 
28 struct map_entry {
29 	uint32_t    reg;
30 	int         is_64_bit;
31 	int         is_limit;
32 	int         mask_bits;
33 	const char *description;
34 };
35 
36 enum {
37 	TOHM_REG,
38 	MMIOL_REG,
39 	MMCFG_BASE_REG,
40 	MMCFG_LIMIT_REG,
41 	TOLM_REG,
42 	/* NCMEM and ME ranges are mutually exclusive */
43 	NCMEM_BASE_REG,
44 	NCMEM_LIMIT_REG,
45 	ME_BASE_REG,
46 	ME_LIMIT_REG,
47 	TSEG_BASE_REG,
48 	TSEG_LIMIT_REG,
49 	VTDBAR_REG,
50 	/* Must be last. */
51 	NUM_MAP_ENTRIES
52 };
53 
vtd_probe_bar_size(struct device * dev)54 size_t vtd_probe_bar_size(struct device *dev)
55 {
56 	uint32_t id = pci_read_config32(dev, PCI_VENDOR_ID);
57 	assert(id == (PCI_VID_INTEL | (MMAP_VTD_CFG_REG_DEVID << 16)));
58 
59 	uint32_t val = pci_read_config32(dev, VTD_BAR_CSR);
60 	pci_write_config32(dev, VTD_BAR_CSR, (uint32_t)(-4 * KiB));
61 	size_t size = (~(pci_read_config32(dev, VTD_BAR_CSR) & ((uint32_t)(-4 * KiB)))) + 1;
62 	assert(size != 0);
63 	pci_write_config32(dev, VTD_BAR_CSR, val);
64 
65 	return size;
66 }
67 
68 static struct map_entry memory_map[NUM_MAP_ENTRIES] = {
69 		[TOHM_REG] = MAP_ENTRY_LIMIT_64(VTD_TOHM_CSR, 26, "TOHM"),
70 		[MMIOL_REG] = MAP_ENTRY_BASE_32(VTD_MMIOL_CSR, "MMIOL"),
71 		[MMCFG_BASE_REG] = MAP_ENTRY_BASE_64(VTD_MMCFG_BASE_CSR, "MMCFG_BASE"),
72 		[MMCFG_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_MMCFG_LIMIT_CSR, 26, "MMCFG_LIMIT"),
73 		[TOLM_REG] = MAP_ENTRY_LIMIT_32(VTD_TOLM_CSR, 26, "TOLM"),
74 #if CONFIG(SOC_INTEL_HAS_NCMEM)
75 		[NCMEM_BASE_REG] = MAP_ENTRY_BASE_64(VTD_NCMEM_BASE_CSR, "NCMEM_BASE"),
76 		[NCMEM_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_NCMEM_LIMIT_CSR, 19, "NCMEM_LIMIT"),
77 #else
78 		[ME_BASE_REG] = MAP_ENTRY_BASE_64(VTD_ME_BASE_CSR, "ME_BASE"),
79 		[ME_LIMIT_REG] = MAP_ENTRY_LIMIT_64(VTD_ME_LIMIT_CSR, 19, "ME_LIMIT"),
80 #endif
81 		[TSEG_BASE_REG] = MAP_ENTRY_BASE_32(VTD_TSEG_BASE_CSR, "TSEGMB_BASE"),
82 		[TSEG_LIMIT_REG] = MAP_ENTRY_LIMIT_32(VTD_TSEG_LIMIT_CSR, 20, "TSEGMB_LIMIT"),
83 		[VTDBAR_REG] = MAP_ENTRY_BASE_32(VTD_BAR_CSR, "VTD_BAR"),
84 };
85 
read_map_entry(struct device * dev,struct map_entry * entry,uint64_t * result)86 static void read_map_entry(struct device *dev, struct map_entry *entry,
87 	uint64_t *result)
88 {
89 	uint64_t value;
90 	uint64_t mask;
91 
92 	if (!entry->reg) {
93 		*result = 0;
94 		return;
95 	}
96 	if (entry->reg == VTD_BAR_CSR && !(pci_read_config32(dev, entry->reg) & 1)) {
97 		/* VTDBAR is not enabled */
98 		*result = 0;
99 		return;
100 	}
101 
102 	mask = ((1ULL << entry->mask_bits) - 1);
103 	mask = ~mask;
104 
105 	value = 0;
106 
107 	if (entry->is_64_bit) {
108 		value = pci_read_config32(dev, entry->reg + sizeof(uint32_t));
109 		value <<= 32;
110 	}
111 
112 	value |= (uint64_t)pci_read_config32(dev, entry->reg);
113 	value &= mask;
114 
115 	if (entry->is_limit)
116 		value |= ~mask;
117 
118 	*result = value;
119 }
120 
mc_read_map_entries(struct device * dev,uint64_t * values)121 static void mc_read_map_entries(struct device *dev, uint64_t *values)
122 {
123 	int i;
124 	for (i = 0; i < NUM_MAP_ENTRIES; i++)
125 		read_map_entry(dev, &memory_map[i], &values[i]);
126 }
127 
mc_report_map_entries(struct device * dev,uint64_t * values)128 static void mc_report_map_entries(struct device *dev, uint64_t *values)
129 {
130 	int i;
131 	for (i = 0; i < NUM_MAP_ENTRIES; i++) {
132 		if (!memory_map[i].description)
133 			continue;
134 
135 		printk(BIOS_DEBUG, "%s: MC MAP: %s: 0x%llx\n",
136 		       dev_path(dev), memory_map[i].description, values[i]);
137 	}
138 }
139 
configure_dpr(struct device * dev)140 static void configure_dpr(struct device *dev)
141 {
142 	const uintptr_t cbmem_top_mb = ALIGN_UP(cbmem_top(), MiB) / MiB;
143 	union dpr_register dpr = { .raw = pci_read_config32(dev, VTD_LTDPR) };
144 
145 	/* The DPR lock bit has to be set sufficiently early. It looks like
146 	 * it cannot be set anymore after FSP-S.
147 	 */
148 	dpr.lock = 1;
149 	dpr.epm = 1;
150 	dpr.size = dpr.top - cbmem_top_mb;
151 	pci_write_config32(dev, VTD_LTDPR, dpr.raw);
152 }
153 
154 /*
155  * Host Memory Map:
156  *
157  * +--------------------------+ TOCM (2 pow 46 - 1)
158  * |     Reserved             |
159  * +--------------------------+
160  * |     MMIOH (relocatable)  |
161  * +--------------------------+
162  * |     PCISeg               |
163  * +--------------------------+ TOHM
164  * |    High DRAM Memory      |
165  * +--------------------------+ 4GiB (0x100000000)
166  * +--------------------------+ 0xFFFF_FFFF
167  * |     Firmware             |
168  * +--------------------------+ 0xFF00_0000
169  * |     Reserved             |
170  * +--------------------------+ 0xFEF0_0000
171  * |     Local xAPIC          |
172  * +--------------------------+ 0xFEE0_0000
173  * |     HPET/LT/TPM/Others   |
174  * +--------------------------+ 0xFED0_0000
175  * |     I/O xAPIC            |
176  * +--------------------------+ 0xFEC0_0000
177  * |     Reserved             |
178  * +--------------------------+ 0xFEB8_0000
179  * |     Reserved             |
180  * +--------------------------+ 0xFEB0_0000
181  * |     Reserved             |
182  * +--------------------------+ 0xFE00_0000
183  * |     MMIOL (relocatable)  |
184  * |     P2SB PCR cfg BAR     | (0xfd000000 - 0xfdffffff
185  * |     BAR space            | [mem 0x90000000-0xfcffffff] available for PCI devices
186  * +--------------------------+ 0x9000_0000
187  * |PCIe MMCFG (relocatable)  | CONFIG_ECAM_MMCONF_BASE_ADDRESS 64 or 256MB
188  * |                          | (0x80000000 - 0x8fffffff, 0x40000)
189  * +--------------------------+ TOLM
190  * |     MEseg (relocatable)  | 32, 64, 128 or 256 MB (0x78000000 - 0x7fffffff, 0x20000)
191  * +--------------------------+
192  * |     Tseg (relocatable)   | N x 8MB (0x70000000 - 0x77ffffff, 0x20000)
193  * +--------------------------+
194  * |     DPR                  |
195  * +--------------------------+ 1M aligned DPR base
196  * |     Unused memory        |
197  * +--------------------------+ cbmem_top
198  * |     Reserved - CBMEM     | (0x6fffe000 - 0x6fffffff, 0x2000)
199  * +--------------------------+
200  * |     Reserved - FSP       | (0x6fbfe000 - 0x6fffdfff, 0x400000)
201  * +--------------------------+ top_of_ram (0x6fbfdfff)
202  * |     Low DRAM Memory      |
203  * +--------------------------+ FFFFF (1MB)
204  * |     E & F segments       |
205  * +--------------------------+ E0000
206  * |     C & D segments       |
207  * +--------------------------+ C0000
208  * |     VGA & SMM Memory     |
209  * +--------------------------+ A0000
210  * |    Conventional Memory   |
211  * |      (DOS Range)         |
212  * +--------------------------+ 0
213  */
214 
mc_add_dram_resources(struct device * dev,int * res_count)215 static void mc_add_dram_resources(struct device *dev, int *res_count)
216 {
217 	const struct resource *res;
218 	uint64_t mc_values[NUM_MAP_ENTRIES];
219 	uint64_t top_of_ram;
220 	int index = *res_count;
221 	struct range_entry fsp_mem;
222 
223 	/* Read in the MAP registers and report their values. */
224 	mc_read_map_entries(dev, &mc_values[0]);
225 	mc_report_map_entries(dev, &mc_values[0]);
226 
227 	if (mc_values[VTDBAR_REG]) {
228 		res = mmio_range(dev, VTD_BAR_CSR, mc_values[VTDBAR_REG],
229 				vtd_probe_bar_size(dev));
230 		LOG_RESOURCE("vtd_bar", dev, res);
231 	}
232 
233 	/* Only add dram resources once. */
234 	if (dev->upstream->secondary != 0 || dev->upstream->segment_group != 0)
235 		return;
236 
237 	/* Conventional Memory (DOS region, 0x0 to 0x9FFFF) */
238 	res = ram_from_to(dev, index++, 0, 0xa0000);
239 	LOG_RESOURCE("legacy_ram", dev, res);
240 
241 	/* 1MB -> top_of_ram */
242 	fsp_find_reserved_memory(&fsp_mem);
243 	top_of_ram = range_entry_base(&fsp_mem) - 1;
244 	res = ram_from_to(dev, index++, 1 * MiB, top_of_ram);
245 	LOG_RESOURCE("low_ram", dev, res);
246 
247 	/* top_of_ram -> cbmem_top */
248 	res = ram_from_to(dev, index++, top_of_ram, cbmem_top());
249 	LOG_RESOURCE("cbmem_ram", dev, res);
250 
251 	/* Mark TSEG/SMM region as reserved */
252 	res = reserved_ram_from_to(dev, index++, mc_values[TSEG_BASE_REG],
253 				   mc_values[TSEG_LIMIT_REG] + 1);
254 	LOG_RESOURCE("mmio_tseg", dev, res);
255 
256 	/* Reserve DPR region */
257 	union dpr_register dpr = { .raw = pci_read_config32(dev, VTD_LTDPR) };
258 	if (dpr.size) {
259 		/*
260 		 * cbmem_top -> DPR base:
261 		 * DPR has a 1M granularity so it's possible if cbmem_top is not 1M
262 		 * aligned that some memory does not get marked as assigned.
263 		 */
264 		res = reserved_ram_from_to(dev, index++, cbmem_top(),
265 			(dpr.top - dpr.size) * MiB);
266 		LOG_RESOURCE("unused_dram", dev, res);
267 
268 		/* DPR base -> DPR top */
269 		res = reserved_ram_from_to(dev, index++, (dpr.top - dpr.size) * MiB,
270 					   dpr.top * MiB);
271 		LOG_RESOURCE("dpr", dev, res);
272 	}
273 
274 	/* Mark TSEG/SMM region as reserved */
275 	res = reserved_ram_from_to(dev, index++, mc_values[TSEG_BASE_REG],
276 				   mc_values[TSEG_LIMIT_REG] + 1);
277 	LOG_RESOURCE("mmio_tseg", dev, res);
278 
279 	/* Mark region between TSEG - TOLM (eg. MESEG) as reserved */
280 	res = reserved_ram_from_to(dev, index++, mc_values[TSEG_LIMIT_REG] + 1,
281 				   mc_values[TOLM_REG]);
282 	LOG_RESOURCE("mmio_tolm", dev, res);
283 
284 	if (CONFIG(SOC_INTEL_HAS_CXL)) {
285 		/* 4GiB -> CXL Memory */
286 		uint32_t gi_mem_size;
287 		gi_mem_size = get_generic_initiator_mem_size(); /* unit: 64MB */
288 		/*
289 		 * Memory layout when there is CXL HDM (Host-managed Device Memory):
290 		 * --------------  <- TOHM
291 		 * CXL memory regions (pds global variable records the base/size of them)
292 		 * Processor attached high memory
293 		 * --------------  <- 0x100000000 (4GB)
294 		 */
295 		res = upper_ram_end(dev, index++,
296 			mc_values[TOHM_REG] - ((uint64_t)gi_mem_size << 26) + 1);
297 		LOG_RESOURCE("high_ram", dev, res);
298 
299 		/* CXL Memory */
300 		uint8_t i;
301 		for (i = 0; i < pds.num_pds; i++) {
302 			if (pds.pds[i].pd_type != PD_TYPE_GENERIC_INITIATOR)
303 				continue;
304 
305 			unsigned long flags = IORESOURCE_CACHEABLE;
306 			int cxl_mode = get_cxl_mode();
307 			if (cxl_mode == XEONSP_CXL_SP_MEM)
308 				flags |= IORESOURCE_SOFT_RESERVE;
309 			else
310 				flags |= IORESOURCE_STORED;
311 
312 			res = fixed_mem_range_flags(dev, index++,
313 				(uint64_t)pds.pds[i].base << 26,
314 				(uint64_t)pds.pds[i].size << 26, flags);
315 			if (cxl_mode == XEONSP_CXL_SP_MEM)
316 				LOG_RESOURCE("specific_purpose_memory", dev, res);
317 			else
318 				LOG_RESOURCE("CXL_memory", dev, res);
319 		}
320 	} else {
321 		/* 4GiB -> TOHM */
322 		res = upper_ram_end(dev, index++, mc_values[TOHM_REG] + 1);
323 		LOG_RESOURCE("high_ram", dev, res);
324 	}
325 
326 	/* add MMIO CFG resource */
327 	res = mmio_from_to(dev, index++, mc_values[MMCFG_BASE_REG],
328 			   mc_values[MMCFG_LIMIT_REG] + 1);
329 	LOG_RESOURCE("mmiocfg_res", dev, res);
330 
331 	/* add Local APIC resource */
332 	res = mmio_range(dev, index++, LAPIC_DEFAULT_BASE, 0x00001000);
333 	LOG_RESOURCE("apic_res", dev, res);
334 
335 	/*
336 	 * Add legacy region as reserved - 0xa000 - 1MB
337 	 * Reserve everything between A segment and 1MB:
338 	 *
339 	 * 0xa0000 - 0xbffff: legacy VGA
340 	 * 0xc0000 - 0xfffff: RAM
341 	 */
342 	res = mmio_range(dev, index++, VGA_MMIO_BASE, VGA_MMIO_SIZE);
343 	LOG_RESOURCE("legacy_mmio", dev, res);
344 
345 	res = reserved_ram_from_to(dev, index++, 0xc0000, 1 * MiB);
346 	LOG_RESOURCE("legacy_write_protect", dev, res);
347 
348 	*res_count = index;
349 }
350 
mmapvtd_read_resources(struct device * dev)351 static void mmapvtd_read_resources(struct device *dev)
352 {
353 	int index = 0;
354 
355 	/* Read standard PCI resources. */
356 	pci_dev_read_resources(dev);
357 
358 	/* set up DPR */
359 	configure_dpr(dev);
360 
361 	/* Calculate and add DRAM resources. */
362 	mc_add_dram_resources(dev, &index);
363 }
364 
mmapvtd_init(struct device * dev)365 static void mmapvtd_init(struct device *dev)
366 {
367 }
368 
369 static struct device_operations mmapvtd_ops = {
370 	.read_resources    = mmapvtd_read_resources,
371 	.set_resources     = pci_dev_set_resources,
372 	.enable_resources  = pci_dev_enable_resources,
373 	.init              = mmapvtd_init,
374 	.ops_pci           = &soc_pci_ops,
375 };
376 
377 static const unsigned short mmapvtd_ids[] = {
378 	MMAP_VTD_CFG_REG_DEVID, /* Memory Map/Intel® VT-d Configuration Registers */
379 	0
380 };
381 
382 static const struct pci_driver mmapvtd_driver __pci_driver = {
383 	.ops      = &mmapvtd_ops,
384 	.vendor   = PCI_VID_INTEL,
385 	.devices  = mmapvtd_ids
386 };
387 
388 #if !CONFIG(SOC_INTEL_MMAPVTD_ONLY_FOR_DPR)
vtd_read_resources(struct device * dev)389 static void vtd_read_resources(struct device *dev)
390 {
391 	pci_dev_read_resources(dev);
392 
393 	configure_dpr(dev);
394 }
395 
396 static struct device_operations vtd_ops = {
397 	.read_resources    = vtd_read_resources,
398 	.set_resources     = pci_dev_set_resources,
399 	.enable_resources  = pci_dev_enable_resources,
400 	.ops_pci           = &soc_pci_ops,
401 };
402 
403 /* VTD devices on other stacks */
404 static const struct pci_driver vtd_driver __pci_driver = {
405 	.ops      = &vtd_ops,
406 	.vendor   = PCI_VID_INTEL,
407 	.device   = MMAP_VTD_STACK_CFG_REG_DEVID,
408 };
409 #endif
410 
dmi3_init(struct device * dev)411 static void dmi3_init(struct device *dev)
412 {
413 	if (CONFIG(INTEL_TXT) && skip_intel_txt_lockdown())
414 		return;
415 	/* Disable error injection */
416 	pci_or_config16(dev, ERRINJCON, 1 << 0);
417 
418 	/*
419 	 * DMIRCBAR registers are not TXT lockable, but the BAR enable
420 	 * bit is. TXT requires that DMIRCBAR be disabled for security.
421 	 */
422 	pci_and_config32(dev, DMIRCBAR, ~(1 << 0));
423 }
424 
425 static struct device_operations dmi3_ops = {
426 	.read_resources		= pci_dev_read_resources,
427 	.set_resources		= pci_dev_set_resources,
428 	.enable_resources	= pci_dev_enable_resources,
429 	.init			= dmi3_init,
430 	.ops_pci		= &soc_pci_ops,
431 };
432 
433 static const struct pci_driver dmi3_driver __pci_driver = {
434 	.ops		= &dmi3_ops,
435 	.vendor		= PCI_VID_INTEL,
436 	.device		= DMI3_DEVID,
437 };
438 
iio_dfx_global_init(struct device * dev)439 static void iio_dfx_global_init(struct device *dev)
440 {
441 	if (CONFIG(INTEL_TXT) && skip_intel_txt_lockdown())
442 		return;
443 
444 	uint16_t reg16;
445 	pci_or_config16(dev, IIO_DFX_LCK_CTL, 0x3ff);
446 	reg16 = pci_read_config16(dev, IIO_DFX_TSWCTL0);
447 	reg16 &= ~(1 << 4); // allow ib mmio cfg
448 	reg16 &= ~(1 << 5); // ignore acs p2p ma lpbk
449 	reg16 |= (1 << 3); // me disable
450 	pci_write_config16(dev, IIO_DFX_TSWCTL0, reg16);
451 }
452 
453 static const unsigned short iio_dfx_global_ids[] = {
454 	0x202d,
455 	0x203d,
456 	0
457 };
458 
459 static struct device_operations iio_dfx_global_ops = {
460 	.read_resources		= pci_dev_read_resources,
461 	.set_resources		= pci_dev_set_resources,
462 	.enable_resources	= pci_dev_enable_resources,
463 	.init			= iio_dfx_global_init,
464 	.ops_pci		= &soc_pci_ops,
465 };
466 
467 static const struct pci_driver iio_dfx_global_driver __pci_driver = {
468 	.ops		= &iio_dfx_global_ops,
469 	.vendor		= PCI_VID_INTEL,
470 	.devices	= iio_dfx_global_ids,
471 };
472