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>
This commit is contained in:
parent
11334729c9
commit
4b290b7b6f
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue