Felix Held has submitted this change. ( https://review.coreboot.org/c/coreboot/+/59512 )
Change subject: nb/intel/sandybridge: Add support for DPR ......................................................................
nb/intel/sandybridge: Add support for DPR
Include DPR in the memory map calculations if enabled. DPR is required for Intel TXT support.
TEST=Boot Debian 10 and see the DPR memory being reserved in E820 and cbmem logs: "BIOS-e820: [mem 0x000000007fc09000-0x00000000829fffff] reserved" "TSEG base 0x80000000 size 8M" "DPR base 0x7fd00000 size 3M"
Signed-off-by: Michał Żygowski michal.zygowski@3mdeb.com Change-Id: Ia22e49ba58709acfa0afe0921aa71d83cc06c129 Reviewed-on: https://review.coreboot.org/c/coreboot/+/59512 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Arthur Heymans arthur@aheymans.xyz Reviewed-by: Angel Pons th3fanbus@gmail.com --- M src/northbridge/intel/sandybridge/memmap.c M src/northbridge/intel/sandybridge/northbridge.c 2 files changed, 43 insertions(+), 4 deletions(-)
Approvals: build bot (Jenkins): Verified Arthur Heymans: Looks good to me, approved Angel Pons: Looks good to me, approved
diff --git a/src/northbridge/intel/sandybridge/memmap.c b/src/northbridge/intel/sandybridge/memmap.c index 7f46d66..f667544 100644 --- a/src/northbridge/intel/sandybridge/memmap.c +++ b/src/northbridge/intel/sandybridge/memmap.c @@ -10,6 +10,7 @@ #include <cpu/x86/smm.h> #include <program_loading.h> #include "sandybridge.h" +#include <security/intel/txt/txt_platform.h> #include <stddef.h> #include <stdint.h>
@@ -24,12 +25,38 @@ return CONFIG_SMM_TSEG_SIZE; }
+union dpr_register txt_get_chipset_dpr(void) +{ + return (union dpr_register) { .raw = pci_read_config32(HOST_BRIDGE, DPR) }; +} + +/* + * 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 DPR is top of usable DRAM below 4 GiB. However, DPR + * may not always be enabled. Unlike most memory map registers, + * the DPR register stores top of DPR instead of its base address. + * Top of DPR is R/O, and mirrored from TSEG base by hardware. + */ + uintptr_t tolum = northbridge_get_tseg_base(); + + const union dpr_register dpr = txt_get_chipset_dpr(); + + /* Subtract DMA Protected Range size if enabled */ + if (dpr.epm) + tolum -= dpr.size * MiB; + + return tolum; +} + void *cbmem_top_chipset(void) { - /* If DPR is disabled, base of TSEG is top of usable DRAM */ - uintptr_t top_of_ram = northbridge_get_tseg_base(); - - return (void *)top_of_ram; + return (void *)top_of_low_usable_memory(); }
void smm_region(uintptr_t *start, size_t *size) diff --git a/src/northbridge/intel/sandybridge/northbridge.c b/src/northbridge/intel/sandybridge/northbridge.c index bd4d107..f04c4f5 100644 --- a/src/northbridge/intel/sandybridge/northbridge.c +++ b/src/northbridge/intel/sandybridge/northbridge.c @@ -14,6 +14,7 @@ #include "chip.h" #include "sandybridge.h" #include <cpu/intel/smm_reloc.h> +#include <security/intel/txt/txt_platform.h>
/* IGD UMA memory */ static uint64_t uma_memory_base = 0; @@ -85,9 +86,11 @@ { uint64_t tom, me_base, touud; uint32_t tseg_base, uma_size, tolud; + uint32_t dpr_base_k, dpr_size_k; uint16_t ggc; unsigned long long tomk; unsigned long index = 3; + const union dpr_register dpr = txt_get_chipset_dpr();
pci_dev_read_resources(dev);
@@ -184,6 +187,15 @@ uma_memory_size += uma_size * 1024ULL; printk(BIOS_DEBUG, "TSEG base 0x%08x size %uM\n", tseg_base, uma_size >> 10);
+ /* Calculate DMA Protected Region if enabled */ + if (dpr.epm && dpr.size) { + dpr_size_k = dpr.size * MiB / KiB; + tomk -= dpr_size_k; + dpr_base_k = (tseg_base - dpr.size * MiB) / KiB; + reserved_ram_resource(dev, index++, dpr_base_k, dpr_size_k); + printk(BIOS_DEBUG, "DPR base 0x%08x size %uM\n", dpr_base_k * KiB, dpr.size); + } + printk(BIOS_INFO, "Available memory below 4GB: %lluM\n", tomk >> 10);
/* Report the memory regions */