summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2020-09-24 23:38:53 +0200
committerPhilipp Deppenwiese <zaolin.daisuki@gmail.com>2020-10-15 08:31:54 +0000
commit4b290b7b6f763f369b78cb83054e6ad65d83c4a3 (patch)
tree34f691a8b73a7864c0cb28b3309f265cf026b08e
parent11334729c9aa3f09b3e01a491a2d007a0aea7201 (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>
-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