aboutsummaryrefslogtreecommitdiff
path: root/src/soc/intel/icelake/memmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/icelake/memmap.c')
-rw-r--r--src/soc/intel/icelake/memmap.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/src/soc/intel/icelake/memmap.c b/src/soc/intel/icelake/memmap.c
new file mode 100644
index 0000000000..027b8b0ffa
--- /dev/null
+++ b/src/soc/intel/icelake/memmap.c
@@ -0,0 +1,312 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/ebda.h>
+#include <arch/io.h>
+#include <cbmem.h>
+#include <chip.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <fsp/util.h>
+#include <intelblocks/ebda.h>
+#include <intelblocks/systemagent.h>
+#include <soc/pci_devs.h>
+#include <soc/smm.h>
+#include <soc/systemagent.h>
+#include <stdlib.h>
+
+void smm_region(void **start, size_t *size)
+{
+ *start = (void *)sa_get_tseg_base();
+ *size = sa_get_tseg_size();
+}
+
+/*
+ * Subregions within SMM
+ * +-------------------------+ BGSM
+ * | IED | IED_REGION_SIZE
+ * +-------------------------+
+ * | External Stage Cache | SMM_RESERVED_SIZE
+ * +-------------------------+
+ * | code and data |
+ * | (TSEG) |
+ * +-------------------------+ TSEG
+ */
+int smm_subregion(int sub, void **start, size_t *size)
+{
+ uintptr_t sub_base;
+ size_t sub_size;
+ void *smm_base;
+ const size_t ied_size = CONFIG_IED_REGION_SIZE;
+ const size_t cache_size = CONFIG_SMM_RESERVED_SIZE;
+
+ smm_region(&smm_base, &sub_size);
+ sub_base = (uintptr_t)smm_base;
+
+ switch (sub) {
+ case SMM_SUBREGION_HANDLER:
+ /* Handler starts at the base of TSEG. */
+ sub_size -= ied_size;
+ sub_size -= cache_size;
+ break;
+ case SMM_SUBREGION_CACHE:
+ /* External cache is in the middle of TSEG. */
+ sub_base += sub_size - (ied_size + cache_size);
+ sub_size = cache_size;
+ break;
+ case SMM_SUBREGION_CHIPSET:
+ /* IED is at the top. */
+ sub_base += sub_size - ied_size;
+ sub_size = ied_size;
+ break;
+ default:
+ return -1;
+ }
+
+ *start = (void *)sub_base;
+ *size = sub_size;
+
+ return 0;
+}
+
+/* Calculate ME Stolen size */
+static size_t get_imr_size(void)
+{
+ size_t imr_size;
+
+ /* ME stolen memory */
+ imr_size = MCHBAR32(IMRLIMIT) - MCHBAR32(IMRBASE);
+
+ return imr_size;
+}
+
+/* Calculate PRMRR size based on user input PRMRR size and alignment */
+static size_t get_prmrr_size(uintptr_t dram_base,
+ const struct soc_intel_icelake_config *config)
+{
+ uintptr_t prmrr_base = dram_base;
+ size_t prmrr_size;
+
+ prmrr_size = config->PrmrrSize;
+
+ /* Allocate PRMRR memory for C6DRAM */
+ if (!prmrr_size) {
+ if (config->enable_c6dram)
+ prmrr_size = 1*MiB;
+ else
+ return 0;
+ }
+
+ /*
+ * PRMRR Sizes that are > 1MB and < 32MB are
+ * not supported and will fail out.
+ */
+ if ((prmrr_size > 1*MiB) && (prmrr_size < 32*MiB))
+ die("PRMRR Sizes that are > 1MB and < 32MB are not"
+ "supported!\n");
+
+ prmrr_base -= prmrr_size;
+ if (prmrr_size >= 32*MiB)
+ prmrr_base = ALIGN_DOWN(prmrr_base, 128*MiB);
+ else
+ prmrr_base = ALIGN_DOWN(prmrr_base, 16*MiB);
+ /* PRMRR Area Size */
+ prmrr_size = dram_base - prmrr_base;
+
+ return prmrr_size;
+}
+
+/* Calculate Intel Traditional Memory size based on GSM, DSM, TSEG and DPR. */
+static size_t calculate_traditional_mem_size(uintptr_t dram_base,
+ const struct device *dev)
+{
+ uintptr_t traditional_mem_base = dram_base;
+ size_t traditional_mem_size;
+
+ if (dev->enabled) {
+ /* Read BDSM from Host Bridge */
+ traditional_mem_base -= sa_get_dsm_size();
+
+ /* Read BGSM from Host Bridge */
+ traditional_mem_base -= sa_get_gsm_size();
+ }
+ /* Get TSEG size */
+ traditional_mem_base -= sa_get_tseg_size();
+
+ /* Get DPR size */
+ if (IS_ENABLED(CONFIG_SA_ENABLE_DPR))
+ traditional_mem_base -= sa_get_dpr_size();
+
+ /* Traditional Area Size */
+ traditional_mem_size = dram_base - traditional_mem_base;
+
+ return traditional_mem_size;
+}
+
+/*
+ * Calculate Intel Reserved Memory size based on
+ * PRMRR size, Me stolen memory and PTT selection.
+ */
+static size_t calculate_reserved_mem_size(uintptr_t dram_base,
+ const struct device *dev)
+{
+ uintptr_t reserve_mem_base = dram_base;
+ size_t reserve_mem_size;
+ const struct soc_intel_icelake_config *config;
+
+ config = dev->chip_info;
+
+ /* Get PRMRR size */
+ reserve_mem_base -= get_prmrr_size(reserve_mem_base, config);
+
+ /* Get Tracehub size */
+ reserve_mem_base -= get_imr_size();
+
+ /* Traditional Area Size */
+ reserve_mem_size = dram_base - reserve_mem_base;
+
+ return reserve_mem_size;
+}
+
+/*
+ * 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
+ * | ME Stolen Memory |
+ * +--------------------------+ ME Stolen
+ * | PTT |
+ * +--------------------------+ 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.
+ */
+static uintptr_t calculate_dram_base(size_t *reserved_mem_size)
+{
+ uintptr_t dram_base;
+ const struct device *dev;
+
+ dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_IGD, 0));
+ if (!dev)
+ die("ERROR - IGD device not found!");
+
+ /* Read TOLUD from Host Bridge offset */
+ dram_base = sa_get_tolud_base();
+
+ /* Get Intel Traditional Memory Range Size */
+ dram_base -= calculate_traditional_mem_size(dram_base, dev);
+
+ /* Get Intel Reserved Memory Range Size */
+ *reserved_mem_size = calculate_reserved_mem_size(dram_base, dev);
+
+ dram_base -= *reserved_mem_size;
+
+ return dram_base;
+}
+
+/*
+ * SoC implementation
+ *
+ * SoC call to summarize all Intel Reserve MMIO size and report to SA
+ */
+size_t soc_reserved_mmio_size(void)
+{
+ struct ebda_config cfg;
+
+ retrieve_ebda_object(&cfg);
+
+ /* Get Intel Reserved Memory Range Size */
+ return cfg.reserved_mem_size;
+}
+
+/* Fill up memory layout information */
+void fill_soc_memmap_ebda(struct ebda_config *cfg)
+{
+ size_t chipset_mem_size;
+
+ cfg->tolum_base = calculate_dram_base(&chipset_mem_size);
+ cfg->reserved_mem_size = chipset_mem_size;
+}
+
+void cbmem_top_init(void)
+{
+ /* Fill up EBDA area */
+ fill_ebda_area();
+}
+
+/*
+ * +-------------------------+ Top of RAM (aligned)
+ * | System Management Mode |
+ * | code and data | Length: CONFIG_TSEG_SIZE
+ * | (TSEG) |
+ * +-------------------------+ SMM base (aligned)
+ * | |
+ * | Chipset Reserved Memory |
+ * | |
+ * +-------------------------+ top_of_ram (aligned)
+ * | |
+ * | CBMEM Root |
+ * | |
+ * +-------------------------+
+ * | |
+ * | FSP Reserved Memory |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Various CBMEM Entries |
+ * | |
+ * +-------------------------+ top_of_stack (8 byte aligned)
+ * | |
+ * | stack (CBMEM Entry) |
+ * | |
+ * +-------------------------+
+ */
+void *cbmem_top(void)
+{
+ struct ebda_config ebda_cfg;
+
+ /*
+ * 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 (sa_get_tseg_base() == 0)
+ return NULL;
+
+ retrieve_ebda_object(&ebda_cfg);
+
+ return (void *)(uintptr_t)ebda_cfg.tolum_base;
+}