summaryrefslogtreecommitdiff
path: root/src/soc/intel/skylake
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/skylake')
-rw-r--r--src/soc/intel/skylake/include/soc/msr.h4
-rw-r--r--src/soc/intel/skylake/include/soc/systemagent.h6
-rw-r--r--src/soc/intel/skylake/memmap.c86
-rw-r--r--src/soc/intel/skylake/smmrelocate.c4
-rw-r--r--src/soc/intel/skylake/systemagent.c45
5 files changed, 94 insertions, 51 deletions
diff --git a/src/soc/intel/skylake/include/soc/msr.h b/src/soc/intel/skylake/include/soc/msr.h
index 390375703e..4239b36996 100644
--- a/src/soc/intel/skylake/include/soc/msr.h
+++ b/src/soc/intel/skylake/include/soc/msr.h
@@ -54,8 +54,8 @@
#define IA32_PLATFORM_DCA_CAP 0x1f8
#define MSR_POWER_CTL 0x1fc
#define MSR_LT_LOCK_MEMORY 0x2e7
-#define UNCORE_EMRR_PHYS_BASE_MSR 0x2f4
-#define UNCORE_EMRR_PHYS_MASK_MSR 0x2f5
+#define UNCORE_PRMRR_PHYS_BASE_MSR 0x2f4
+#define UNCORE_PRMRR_PHYS_MASK_MSR 0x2f5
#define IA32_MC0_STATUS 0x401
#define SMM_FEATURE_CONTROL_MSR 0x4e0
#define SMM_CPU_SAVE_EN (1 << 1)
diff --git a/src/soc/intel/skylake/include/soc/systemagent.h b/src/soc/intel/skylake/include/soc/systemagent.h
index 6bb5c66d2a..59221c7754 100644
--- a/src/soc/intel/skylake/include/soc/systemagent.h
+++ b/src/soc/intel/skylake/include/soc/systemagent.h
@@ -120,7 +120,13 @@
/* Data is passed through bits 31:0 of the data register. */
#define BIOS_MAILBOX_DATA 0x5da0
+/* CPU Trace reserved memory size */
+#define TRACE_MEMORY_SIZE 0x8000000 /* 128MiB */
+
/* System Agent identification */
u8 systemagent_revision(void);
+/* Top of 32bit usable memory */
+u32 top_of_32bit_ram(void);
+
#endif
diff --git a/src/soc/intel/skylake/memmap.c b/src/soc/intel/skylake/memmap.c
index 494b259455..0dc46a9c8c 100644
--- a/src/soc/intel/skylake/memmap.c
+++ b/src/soc/intel/skylake/memmap.c
@@ -20,7 +20,11 @@
#include <arch/io.h>
#include <cbmem.h>
+#include <chip.h>
+#include <console/console.h>
+#include <device/device.h>
#include <device/pci.h>
+#include <soc/msr.h>
#include <soc/pci_devs.h>
#include <soc/romstage.h>
#include <soc/smm.h>
@@ -108,6 +112,71 @@ int smm_subregion(int sub, void **start, size_t *size)
return 0;
}
+/*
+ * Host Memory Map:
+ *
+ * +--------------------------+ TOUUD
+ * | |
+ * +--------------------------+ 4GiB
+ * | PCI Address Space |
+ * +--------------------------+ TOLUD (also maps into MC address space)
+ * | iGD |
+ * +--------------------------+ BDSM
+ * | GTT |
+ * +--------------------------+ BGSM
+ * | TSEG |
+ * +--------------------------+ TSEGMB
+ * | DMA Protected Region |
+ * +--------------------------+ DPR
+ * | PRM (C6DRAM/SGX) |
+ * +--------------------------+ PRMRR
+ * | Trace Memory |
+ * +--------------------------+ top_of_ram
+ * | Reserved - FSP/CBMEM |
+ * +--------------------------+ TOLUM
+ * | Usage DRAM |
+ * +--------------------------+ 0
+ *
+ * Some of the base registers above can be equal making the size of those
+ * regions 0. The reason is because the memory controller internally subtracts
+ * the base registers from each other to determine sizes of the regions. In
+ * other words, the memory map is in a fixed order no matter what.
+ */
+
+u32 top_of_32bit_ram(void)
+{
+ msr_t prmrr_base;
+ u32 top_of_ram;
+ const struct device *dev;
+ const struct soc_intel_skylake_config *config;
+
+ /*
+ * Check if Tseg has been initialized, we will use this as a flag
+ * to check if the MRC is done, and only then continue to read the
+ * PRMMR_BASE MSR. The system hangs if PRMRR_BASE MSR is read before
+ * PRMRR_MASK MSR lock bit is set.
+ */
+ if (smm_region_start() == 0)
+ return 0;
+
+ dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_ROOT, 0));
+ config = dev->chip_info;
+
+ /*
+ * On Skylake, cbmem_top is offset down from PRMRR_BASE by reserved
+ * memory (128MiB) for CPU trace if enabled, then reserved memory (4KB)
+ * for PTT if enabled. PTT is in fact not used on Skylake platforms.
+ * Refer to Fsp Integration Guide for the memory mapping layout.
+ */
+ prmrr_base = rdmsr(UNCORE_PRMRR_PHYS_BASE_MSR);
+ top_of_ram = prmrr_base.lo;
+
+ if (config->ProbelessTrace)
+ top_of_ram -= TRACE_MEMORY_SIZE;
+
+ return top_of_ram;
+}
+
void *cbmem_top(void)
{
/*
@@ -117,7 +186,7 @@ void *cbmem_top(void)
* | (TSEG) |
* +-------------------------+ SMM base (aligned)
* | |
- * | Chipset Reserved Memory | Length: Multiple of CONFIG_TSEG_SIZE
+ * | Chipset Reserved Memory |
* | |
* +-------------------------+ top_of_ram (aligned)
* | |
@@ -137,19 +206,6 @@ void *cbmem_top(void)
* | |
* +-------------------------+
*/
-
- uintptr_t top_of_ram = smm_region_start();
-
- /*
- * Subtract DMA Protected Range size if enabled and align to a multiple
- * of TSEG size.
- */
- u32 dpr = pci_read_config32(SA_DEV_ROOT, DPR);
- if (dpr & DPR_EPM) {
- top_of_ram -= (dpr & DPR_SIZE_MASK) << 16;
- top_of_ram = ALIGN_DOWN(top_of_ram, mmap_region_granluarity());
- }
-
- return (void *)top_of_ram;
+ return (void *)top_of_32bit_ram();
}
diff --git a/src/soc/intel/skylake/smmrelocate.c b/src/soc/intel/skylake/smmrelocate.c
index 2f75c2eebf..4b6f1c4b60 100644
--- a/src/soc/intel/skylake/smmrelocate.c
+++ b/src/soc/intel/skylake/smmrelocate.c
@@ -54,8 +54,8 @@ static inline void write_uncore_emrr(struct smm_relocation_params *relo_params)
"Writing UNCORE_EMRR. base = 0x%08x, mask=0x%08x\n",
relo_params->uncore_emrr_base.lo,
relo_params->uncore_emrr_mask.lo);
- wrmsr(UNCORE_EMRR_PHYS_BASE_MSR, relo_params->uncore_emrr_base);
- wrmsr(UNCORE_EMRR_PHYS_MASK_MSR, relo_params->uncore_emrr_mask);
+ wrmsr(UNCORE_PRMRR_PHYS_BASE_MSR, relo_params->uncore_emrr_base);
+ wrmsr(UNCORE_PRMRR_PHYS_MASK_MSR, relo_params->uncore_emrr_mask);
}
static void update_save_state(int cpu,
diff --git a/src/soc/intel/skylake/systemagent.c b/src/soc/intel/skylake/systemagent.c
index a1bcfdcf71..1fe330480e 100644
--- a/src/soc/intel/skylake/systemagent.c
+++ b/src/soc/intel/skylake/systemagent.c
@@ -163,33 +163,6 @@ static void mc_add_fixed_mmio_resources(device_t dev)
}
}
-/*
- * Host Memory Map:
- *
- * +--------------------------+ TOUUD
- * | |
- * +--------------------------+ 4GiB
- * | PCI Address Space |
- * +--------------------------+ TOLUD (also maps into MC address space)
- * | iGD |
- * +--------------------------+ BDSM
- * | GTT |
- * +--------------------------+ BGSM
- * | TSEG |
- * +--------------------------+ TSEGMB
- * | DMA Protected Region |
- * +--------------------------+ DPR
- * | Reserved - FSP |
- * +--------------------------+ RSVFSP
- * | Usage DRAM |
- * +--------------------------+ 0
- *
- * Some of the base registers above can be equal making the size of those
- * regions 0. The reason is because the memory controller internally subtracts
- * the base registers from each other to determine sizes of the regions. In
- * other words, the memory map is in a fixed order no matter what.
- */
-
struct map_entry {
int reg;
int is_64_bit;
@@ -313,8 +286,9 @@ static void mc_add_dram_resources(device_t dev)
/*
* These are the host memory ranges that should be added:
* - 0 -> 0xa0000: cacheable
- * - 0xc0000 -> TSEG : cacheable
- * - TESG -> BGSM: cacheable with standard MTRRs and reserved
+ * - 0xc0000 -> top_of_ram : cacheable
+ * - top_of_ram -> TSEG - DPR: uncacheable
+ * - TESG - DPR -> BGSM: cacheable with standard MTRRs and reserved
* - BGSM -> TOLUD: not cacheable with standard MTRRs and reserved
* - 4GiB -> TOUUD: cacheable
*
@@ -347,12 +321,19 @@ static void mc_add_dram_resources(device_t dev)
size_k = (0xa0000 >> 10) - base_k;
ram_resource(dev, index++, base_k, size_k);
- /* 0xc0000 -> TSEG - DPR */
+ /* 0xc0000 -> top_of_ram */
base_k = 0xc0000 >> 10;
- size_k = (unsigned long)(mc_values[TSEG_REG] >> 10) - base_k;
- size_k -= dpr_size >> 10;
+ size_k = (top_of_32bit_ram() >> 10) - base_k;
ram_resource(dev, index++, base_k, size_k);
+ /* top_of_ram -> TSEG - DPR */
+ resource = new_resource(dev, index++);
+ resource->base = top_of_32bit_ram();
+ resource->size = mc_values[TSEG_REG] - dpr_size - resource->base;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
+ IORESOURCE_STORED | IORESOURCE_RESERVE |
+ IORESOURCE_ASSIGNED;
+
/* TSEG - DPR -> BGSM */
resource = new_resource(dev, index++);
resource->base = mc_values[TSEG_REG] - dpr_size;