summaryrefslogtreecommitdiff
path: root/src/northbridge
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge')
-rw-r--r--src/northbridge/intel/haswell/memmap.c45
-rw-r--r--src/northbridge/intel/haswell/northbridge.c25
-rw-r--r--src/northbridge/intel/haswell/registers/host_bridge.h3
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