aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/northbridge/intel/sandybridge/memmap.c35
-rw-r--r--src/northbridge/intel/sandybridge/northbridge.c12
2 files changed, 43 insertions, 4 deletions
diff --git a/src/northbridge/intel/sandybridge/memmap.c b/src/northbridge/intel/sandybridge/memmap.c
index 7f46d6663e..f667544c68 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 @@ static size_t northbridge_get_tseg_size(void)
return CONFIG_SMM_TSEG_SIZE;
}
-void *cbmem_top_chipset(void)
+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)
{
- /* If DPR is disabled, base of TSEG is top of usable DRAM */
- uintptr_t top_of_ram = northbridge_get_tseg_base();
+ /*
+ * 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();
- return (void *)top_of_ram;
+ 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)
+{
+ 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 bd4d1078da..f04c4f5e7f 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 @@ static void mc_read_resources(struct device *dev)
{
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 @@ static void mc_read_resources(struct device *dev)
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 */