diff options
author | Angel Pons <th3fanbus@gmail.com> | 2020-09-24 23:38:53 +0200 |
---|---|---|
committer | Philipp Deppenwiese <zaolin.daisuki@gmail.com> | 2020-10-15 08:31:54 +0000 |
commit | 4b290b7b6f763f369b78cb83054e6ad65d83c4a3 (patch) | |
tree | 34f691a8b73a7864c0cb28b3309f265cf026b08e /src | |
parent | 11334729c9aa3f09b3e01a491a2d007a0aea7201 (diff) |
nb/intel/haswell: Account for DPR region in memory map
While MRC.bin does not allocate any memory for DPR by default, it can be
patched to do so. However, the current northbridge code does not account
for DPR and will, among other things, place CBMEM inside it. Even though
this may seem like a good thing, it renders TianoCore unable to boot and
clashes with Intel TXT support (the reason to enable DPR to begin with).
Update memmap.c so that CBMEM top does not fall within DPR. Also, report
DPR as reserved, so that OSes know that the DPR memory is not to be used.
Change-Id: I11f23fd43188f987e35fd61f52587e567496cd78
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/45712
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Diffstat (limited to 'src')
-rw-r--r-- | src/northbridge/intel/haswell/memmap.c | 45 | ||||
-rw-r--r-- | src/northbridge/intel/haswell/northbridge.c | 25 | ||||
-rw-r--r-- | src/northbridge/intel/haswell/registers/host_bridge.h | 3 |
3 files changed, 62 insertions, 11 deletions
diff --git a/src/northbridge/intel/haswell/memmap.c b/src/northbridge/intel/haswell/memmap.c index 807ee2a358..ac36e25999 100644 --- a/src/northbridge/intel/haswell/memmap.c +++ b/src/northbridge/intel/haswell/memmap.c @@ -9,27 +9,56 @@ #include <cpu/x86/smm.h> #include <device/pci_ops.h> #include <cbmem.h> +#include <security/intel/txt/txt_register.h> + #include "haswell.h" -static uintptr_t smm_region_start(void) +static uintptr_t northbridge_get_tseg_base(void) +{ + return ALIGN_DOWN(pci_read_config32(HOST_BRIDGE, TSEG), 1 * MiB); +} + +static size_t northbridge_get_tseg_size(void) +{ + return CONFIG_SMM_TSEG_SIZE; +} + +/* + * Return the topmost memory address below 4 GiB available for general + * use, from software's view of memory. Do not confuse this with TOLUD, + * which applies to the DRAM as viewed by the memory controller itself. + */ +static uintptr_t top_of_low_usable_memory(void) { /* - * Base of TSEG is top of usable DRAM below 4GiB. The register has - * 1 MiB alignment. + * Base of DPR is top of usable DRAM below 4 GiB. However, DPR + * isn't always enabled. Unlike most memory map registers, the + * DPR register stores top of DPR instead of its base address. + * Unless binary-patched, Haswell MRC.bin does not enable DPR. + * Top of DPR is R/O, and mirrored from TSEG base by hardware. */ - uintptr_t tom = pci_read_config32(HOST_BRIDGE, TSEG); - return ALIGN_DOWN(tom, 1 * MiB); + uintptr_t tolum = northbridge_get_tseg_base(); + + const union dpr_register dpr = { + .raw = pci_read_config32(HOST_BRIDGE, DPR), + }; + + /* Subtract DMA Protected Range size if enabled */ + if (dpr.epm) + tolum -= dpr.size * MiB; + + return tolum; } void *cbmem_top_chipset(void) { - return (void *)smm_region_start(); + return (void *)top_of_low_usable_memory(); } void smm_region(uintptr_t *start, size_t *size) { - *start = smm_region_start(); - *size = CONFIG_SMM_TSEG_SIZE; + *start = northbridge_get_tseg_base(); + *size = northbridge_get_tseg_size(); } void fill_postcar_frame(struct postcar_frame *pcf) diff --git a/src/northbridge/intel/haswell/northbridge.c b/src/northbridge/intel/haswell/northbridge.c index e1c26d162c..5619d95728 100644 --- a/src/northbridge/intel/haswell/northbridge.c +++ b/src/northbridge/intel/haswell/northbridge.c @@ -12,6 +12,7 @@ #include <device/pci_ids.h> #include <device/pci_ops.h> #include <boot/tables.h> +#include <security/intel/txt/txt_register.h> #include "chip.h" #include "haswell.h" @@ -162,7 +163,8 @@ static void mc_add_fixed_mmio_resources(struct device *dev) } } -/* Host Memory Map: +/* + * Host Memory Map: * * +--------------------------+ TOUUD * | | @@ -175,6 +177,8 @@ static void mc_add_fixed_mmio_resources(struct device *dev) * +--------------------------+ BGSM * | TSEG | * +--------------------------+ TSEGMB + * | DPR | + * +--------------------------+ (DPR top - DPR size) * | Usage DRAM | * +--------------------------+ 0 * @@ -285,6 +289,12 @@ static void mc_add_dram_resources(struct device *dev, int *resource_cnt) mc_read_map_entries(dev, &mc_values[0]); mc_report_map_entries(dev, &mc_values[0]); + /* The DPR register is special */ + const union dpr_register dpr = { + .raw = pci_read_config32(dev, DPR), + }; + printk(BIOS_DEBUG, "MC MAP: DPR: 0x%x\n", dpr.raw); + /* * These are the host memory ranges that should be added: * - 0 -> 0xa0000: cacheable @@ -318,11 +328,20 @@ static void mc_add_dram_resources(struct device *dev, int *resource_cnt) size_k = (0xa0000 >> 10) - base_k; ram_resource(dev, index++, base_k, size_k); - /* 0xc0000 -> TSEG */ + /* 0xc0000 -> DPR base */ base_k = 0xc0000 >> 10; - size_k = (unsigned long)(mc_values[TSEG_REG] >> 10) - base_k; + size_k = (unsigned long)(mc_values[TSEG_REG] >> 10) - (base_k + dpr.size); ram_resource(dev, index++, base_k, size_k); + /* DPR base -> TSEG */ + if (dpr.size) { + resource = new_resource(dev, index++); + resource->base = (dpr.top - dpr.size) * MiB; + resource->size = dpr.size * MiB; + resource->flags = IORESOURCE_MEM | IORESOURCE_STORED | IORESOURCE_CACHEABLE | + IORESOURCE_RESERVE | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; + } + /* TSEG -> BGSM */ resource = new_resource(dev, index++); resource->base = mc_values[TSEG_REG]; diff --git a/src/northbridge/intel/haswell/registers/host_bridge.h b/src/northbridge/intel/haswell/registers/host_bridge.h index d348fd4a61..7746801804 100644 --- a/src/northbridge/intel/haswell/registers/host_bridge.h +++ b/src/northbridge/intel/haswell/registers/host_bridge.h @@ -25,6 +25,9 @@ #define PAVPC 0x58 #define DPR 0x5c +#define DPR_EPM (1 << 2) +#define DPR_PRS (1 << 1) +#define DPR_SIZE_MASK 0xff0 #define PCIEXBAR 0x60 #define DMIBAR 0x68 |