blob: 60a7070408fcc5ba822953418fa3b6739adaa6d0 [file] [log] [blame]
Lee Leahyb0005132015-05-12 18:19:47 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Google Inc.
Subrata Banikf506cf02017-10-19 16:35:21 +05305 * Copyright (C) 2015-2017 Intel Corporation.
Lee Leahyb0005132015-05-12 18:19:47 -07006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Lee Leahyb0005132015-05-12 18:19:47 -070015 */
16
Subrata Banik7387e042017-09-21 19:22:22 +053017#include <arch/ebda.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020018#include <device/mmio.h>
Lee Leahyb0005132015-05-12 18:19:47 -070019#include <cbmem.h>
Rizwan Qureshi188e3702015-07-23 17:40:32 +053020#include <chip.h>
Subrata Banikf5fe3592017-08-22 17:58:02 +053021#include <console/console.h>
Rizwan Qureshi188e3702015-07-23 17:40:32 +053022#include <device/device.h>
Lee Leahyb0005132015-05-12 18:19:47 -070023#include <device/pci.h>
Subrata Banikece173c2017-12-14 18:18:34 +053024#include <fsp/memmap.h>
Subrata Banik7387e042017-09-21 19:22:22 +053025#include <intelblocks/ebda.h>
Subrata Banikf5fe3592017-08-22 17:58:02 +053026#include <intelblocks/systemagent.h>
Rizwan Qureshi188e3702015-07-23 17:40:32 +053027#include <soc/msr.h>
Lee Leahyb0005132015-05-12 18:19:47 -070028#include <soc/pci_devs.h>
29#include <soc/systemagent.h>
Aaron Durbina0429b62015-08-05 14:33:37 -050030#include <stdlib.h>
Lee Leahyb0005132015-05-12 18:19:47 -070031
Lee Leahye0918bb2016-01-29 14:28:43 -080032size_t mmap_region_granularity(void)
Lee Leahy1d14b3e2015-05-12 18:23:27 -070033{
Julius Wernercd49cce2019-03-05 16:53:33 -080034 if (CONFIG(HAVE_SMI_HANDLER))
Lee Leahy1d14b3e2015-05-12 18:23:27 -070035 /* Align to TSEG size when SMM is in use */
36 if (CONFIG_SMM_TSEG_SIZE != 0)
37 return CONFIG_SMM_TSEG_SIZE;
38
39 /* Make it 8MiB by default. */
Aaron Durbina0429b62015-08-05 14:33:37 -050040 return 8*MiB;
Lee Leahy1d14b3e2015-05-12 18:23:27 -070041}
42
Lee Leahy1d14b3e2015-05-12 18:23:27 -070043void smm_region(void **start, size_t *size)
44{
Subrata Banikce9653f2017-08-30 16:33:17 +053045 *start = (void *)sa_get_tseg_base();
46 *size = sa_get_tseg_size();
Lee Leahyb0005132015-05-12 18:19:47 -070047}
48
Aaron Durbinc43d4172015-08-05 14:51:48 -050049/*
50 * Subregions within SMM
51 * +-------------------------+ BGSM
52 * | IED | IED_REGION_SIZE
53 * +-------------------------+
54 * | External Stage Cache | SMM_RESERVED_SIZE
55 * +-------------------------+
56 * | code and data |
57 * | (TSEG) |
58 * +-------------------------+ TSEG
59 */
60int smm_subregion(int sub, void **start, size_t *size)
61{
62 uintptr_t sub_base;
63 size_t sub_size;
Subrata Banikce9653f2017-08-30 16:33:17 +053064 void *smm_base;
Aaron Durbinc43d4172015-08-05 14:51:48 -050065 const size_t ied_size = CONFIG_IED_REGION_SIZE;
66 const size_t cache_size = CONFIG_SMM_RESERVED_SIZE;
67
Subrata Banikce9653f2017-08-30 16:33:17 +053068 smm_region(&smm_base, &sub_size);
69 sub_base = (uintptr_t)smm_base;
Aaron Durbinc43d4172015-08-05 14:51:48 -050070
71 switch (sub) {
72 case SMM_SUBREGION_HANDLER:
73 /* Handler starts at the base of TSEG. */
74 sub_size -= ied_size;
75 sub_size -= cache_size;
76 break;
77 case SMM_SUBREGION_CACHE:
78 /* External cache is in the middle of TSEG. */
79 sub_base += sub_size - (ied_size + cache_size);
80 sub_size = cache_size;
81 break;
82 case SMM_SUBREGION_CHIPSET:
83 /* IED is at the top. */
84 sub_base += sub_size - ied_size;
85 sub_size = ied_size;
86 break;
87 default:
88 return -1;
89 }
90
91 *start = (void *)sub_base;
92 *size = sub_size;
93
94 return 0;
95}
96
Subrata Banikf5fe3592017-08-22 17:58:02 +053097static bool is_ptt_enable(void)
98{
99 if ((read32((void *)PTT_TXT_BASE_ADDRESS) & PTT_PRESENT) ==
100 PTT_PRESENT)
101 return true;
102
103 return false;
104}
105
Subrata Banik82ef3642017-09-17 13:36:19 +0530106/* Calculate PTT size */
107static size_t get_ptt_size(void)
108{
109 /* Allocate 4KB for PTT if enabled */
110 return is_ptt_enable() ? 4*KiB : 0;
111}
112
113/* Calculate Trace Hub size */
114static size_t get_tracehub_size(uintptr_t dram_base,
115 const struct soc_intel_skylake_config *config)
116{
117 uintptr_t tracehub_base = dram_base;
118 size_t tracehub_size = 0;
119
120 if (!config->ProbelessTrace)
121 return 0;
122
123 /* GDXC MOT */
124 tracehub_base -= GDXC_MOT_MEMORY_SIZE;
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100125 /* Round down to natural boundary according to PSMI size */
Subrata Banik82ef3642017-09-17 13:36:19 +0530126 tracehub_base = ALIGN_DOWN(tracehub_base, PSMI_BUFFER_AREA_SIZE);
127 /* GDXC IOT */
128 tracehub_base -= GDXC_IOT_MEMORY_SIZE;
129 /* PSMI buffer area */
130 tracehub_base -= PSMI_BUFFER_AREA_SIZE;
131
132 /* Tracehub Area Size */
133 tracehub_size = dram_base - tracehub_base;
134
135 return tracehub_size;
136}
137
138/* Calculate PRMRR size based on user input PRMRR size and alignment */
139static size_t get_prmrr_size(uintptr_t dram_base,
140 const struct soc_intel_skylake_config *config)
141{
142 uintptr_t prmrr_base = dram_base;
143 size_t prmrr_size;
144
Julius Wernercd49cce2019-03-05 16:53:33 -0800145 if (CONFIG(PLATFORM_USES_FSP1_1))
Subrata Banik82ef3642017-09-17 13:36:19 +0530146 prmrr_size = 1*MiB;
147 else
148 prmrr_size = config->PrmrrSize;
149
150 if (!prmrr_size)
151 return 0;
152
153 /*
154 * PRMRR Sizes that are > 1MB and < 32MB are
155 * not supported and will fail out.
156 */
157 if ((prmrr_size > 1*MiB) && (prmrr_size < 32*MiB))
158 die("PRMRR Sizes that are > 1MB and < 32MB are not"
159 "supported!\n");
160
161 prmrr_base -= prmrr_size;
162 if (prmrr_size >= 32*MiB)
163 prmrr_base = ALIGN_DOWN(prmrr_base, 128*MiB);
164
165 /* PRMRR Area Size */
166 prmrr_size = dram_base - prmrr_base;
167
168 return prmrr_size;
169}
170
171/* Calculate Intel Traditional Memory size based on GSM, DSM, TSEG and DPR. */
172static size_t calculate_traditional_mem_size(uintptr_t dram_base,
173 const struct device *dev)
174{
175 uintptr_t traditional_mem_base = dram_base;
176 size_t traditional_mem_size;
177
178 if (dev->enabled) {
179 /* Read BDSM from Host Bridge */
180 traditional_mem_base -= sa_get_dsm_size();
181
182 /* Read BGSM from Host Bridge */
183 traditional_mem_base -= sa_get_gsm_size();
184 }
185 /* Get TSEG size */
186 traditional_mem_base -= sa_get_tseg_size();
187
188 /* Get DPR size */
Julius Wernercd49cce2019-03-05 16:53:33 -0800189 if (CONFIG(SA_ENABLE_DPR))
Subrata Banik82ef3642017-09-17 13:36:19 +0530190 traditional_mem_base -= sa_get_dpr_size();
191
192 /* Traditional Area Size */
193 traditional_mem_size = dram_base - traditional_mem_base;
194
195 return traditional_mem_size;
196}
197
198/*
199 * Calculate Intel Reserved Memory size based on
200 * PRMRR size, Trace Hub config and PTT selection.
201 */
202static size_t calculate_reserved_mem_size(uintptr_t dram_base,
203 const struct device *dev)
204{
205 uintptr_t reserve_mem_base = dram_base;
206 size_t reserve_mem_size;
207 const struct soc_intel_skylake_config *config;
208
209 config = dev->chip_info;
210
211 /* Get PRMRR size */
212 reserve_mem_base -= get_prmrr_size(reserve_mem_base, config);
213
214 /* Get Tracehub size */
215 reserve_mem_base -= get_tracehub_size(reserve_mem_base, config);
216
217 /* Get PTT size */
218 reserve_mem_base -= get_ptt_size();
219
220 /* Traditional Area Size */
221 reserve_mem_size = dram_base - reserve_mem_base;
222
223 return reserve_mem_size;
224}
225
Rizwan Qureshi188e3702015-07-23 17:40:32 +0530226/*
227 * Host Memory Map:
228 *
229 * +--------------------------+ TOUUD
230 * | |
231 * +--------------------------+ 4GiB
232 * | PCI Address Space |
233 * +--------------------------+ TOLUD (also maps into MC address space)
234 * | iGD |
235 * +--------------------------+ BDSM
236 * | GTT |
237 * +--------------------------+ BGSM
238 * | TSEG |
239 * +--------------------------+ TSEGMB
240 * | DMA Protected Region |
241 * +--------------------------+ DPR
242 * | PRM (C6DRAM/SGX) |
243 * +--------------------------+ PRMRR
244 * | Trace Memory |
Subrata Banikf5fe3592017-08-22 17:58:02 +0530245 * +--------------------------+ Probless Trace
246 * | PTT |
Rizwan Qureshi188e3702015-07-23 17:40:32 +0530247 * +--------------------------+ top_of_ram
248 * | Reserved - FSP/CBMEM |
249 * +--------------------------+ TOLUM
250 * | Usage DRAM |
251 * +--------------------------+ 0
252 *
253 * Some of the base registers above can be equal making the size of those
254 * regions 0. The reason is because the memory controller internally subtracts
255 * the base registers from each other to determine sizes of the regions. In
256 * other words, the memory map is in a fixed order no matter what.
257 */
Subrata Banikfdddc462017-09-21 20:23:41 +0530258static uintptr_t calculate_dram_base(size_t *reserved_mem_size)
Subrata Banikf5fe3592017-08-22 17:58:02 +0530259{
Subrata Banik82ef3642017-09-17 13:36:19 +0530260 uintptr_t dram_base;
Subrata Banikf5fe3592017-08-22 17:58:02 +0530261 const struct device *dev;
Rizwan Qureshi188e3702015-07-23 17:40:32 +0530262
Subrata Banikf5fe3592017-08-22 17:58:02 +0530263 dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_IGD, 0));
Subrata Banikb92ad0b2017-09-05 18:44:15 +0530264 if (!dev)
Subrata Banik82ef3642017-09-17 13:36:19 +0530265 die("ERROR - IGD device not found!");
Subrata Banikf5fe3592017-08-22 17:58:02 +0530266
267 /* Read TOLUD from Host Bridge offset */
268 dram_base = sa_get_tolud_base();
269
Subrata Banik82ef3642017-09-17 13:36:19 +0530270 /* Get Intel Traditional Memory Range Size */
271 dram_base -= calculate_traditional_mem_size(dram_base, dev);
Subrata Banikf5fe3592017-08-22 17:58:02 +0530272
Subrata Banik82ef3642017-09-17 13:36:19 +0530273 /* Get Intel Reserved Memory Range Size */
Subrata Banikfdddc462017-09-21 20:23:41 +0530274 *reserved_mem_size = calculate_reserved_mem_size(dram_base, dev);
275
276 dram_base -= *reserved_mem_size;
Subrata Banikf5fe3592017-08-22 17:58:02 +0530277
278 return dram_base;
279}
280
Subrata Banikfdddc462017-09-21 20:23:41 +0530281/*
282 * SoC implementation
283 *
284 * SoC call to summarize all Intel Reserve MMIO size and report to SA
285 */
286size_t soc_reserved_mmio_size(void)
287{
Subrata Banikf506cf02017-10-19 16:35:21 +0530288 struct ebda_config cfg;
Subrata Banikfdddc462017-09-21 20:23:41 +0530289
Subrata Banikf506cf02017-10-19 16:35:21 +0530290 retrieve_ebda_object(&cfg);
Subrata Banikfdddc462017-09-21 20:23:41 +0530291
292 /* Get Intel Reserved Memory Range Size */
Subrata Banikf506cf02017-10-19 16:35:21 +0530293 return cfg.reserved_mem_size;
Subrata Banikfdddc462017-09-21 20:23:41 +0530294}
295
Subrata Banik7387e042017-09-21 19:22:22 +0530296/* Fill up memory layout information */
297void fill_soc_memmap_ebda(struct ebda_config *cfg)
298{
Subrata Banikfdddc462017-09-21 20:23:41 +0530299 size_t chipset_mem_size;
300
301 cfg->tolum_base = calculate_dram_base(&chipset_mem_size);
Subrata Banikf506cf02017-10-19 16:35:21 +0530302 cfg->reserved_mem_size = chipset_mem_size;
Subrata Banik7387e042017-09-21 19:22:22 +0530303}
304
305void cbmem_top_init(void)
306{
307 /* Fill up EBDA area */
308 fill_ebda_area();
309}
310
Subrata Banik82ef3642017-09-17 13:36:19 +0530311/*
312 * +-------------------------+ Top of RAM (aligned)
313 * | System Management Mode |
314 * | code and data | Length: CONFIG_TSEG_SIZE
315 * | (TSEG) |
316 * +-------------------------+ SMM base (aligned)
317 * | |
318 * | Chipset Reserved Memory |
319 * | |
320 * +-------------------------+ top_of_ram (aligned)
321 * | |
322 * | CBMEM Root |
323 * | |
324 * +-------------------------+
325 * | |
326 * | FSP Reserved Memory |
327 * | |
328 * +-------------------------+
329 * | |
330 * | Various CBMEM Entries |
331 * | |
332 * +-------------------------+ top_of_stack (8 byte aligned)
333 * | |
334 * | stack (CBMEM Entry) |
335 * | |
336 * +-------------------------+
337 */
338void *cbmem_top(void)
Rizwan Qureshi188e3702015-07-23 17:40:32 +0530339{
Subrata Banik7387e042017-09-21 19:22:22 +0530340 struct ebda_config ebda_cfg;
Subrata Banik7387e042017-09-21 19:22:22 +0530341
Rizwan Qureshi188e3702015-07-23 17:40:32 +0530342 /*
343 * Check if Tseg has been initialized, we will use this as a flag
344 * to check if the MRC is done, and only then continue to read the
345 * PRMMR_BASE MSR. The system hangs if PRMRR_BASE MSR is read before
346 * PRMRR_MASK MSR lock bit is set.
347 */
Subrata Banikce9653f2017-08-30 16:33:17 +0530348 if (sa_get_tseg_base() == 0)
Subrata Banik82ef3642017-09-17 13:36:19 +0530349 return NULL;
Rizwan Qureshi188e3702015-07-23 17:40:32 +0530350
Arthur Heymansac312c62018-04-09 23:14:22 +0200351 retrieve_ebda_object(&ebda_cfg);
Subrata Banik7387e042017-09-21 19:22:22 +0530352
Arthur Heymansac312c62018-04-09 23:14:22 +0200353 return (void *)(uintptr_t)ebda_cfg.tolum_base;
Lee Leahyb0005132015-05-12 18:19:47 -0700354}