blob: 8ffda2a57ba3a45d5061fa09a1a86a476a271a33 [file] [log] [blame]
Lijian Zhaoe88fa492017-07-11 12:26:56 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Google Inc.
5 * Copyright (C) 2015-2017 Intel Corporation.
6 *
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.
15 */
Subrata Banik47569cf2017-10-12 17:59:02 +053016
17#include <arch/ebda.h>
Lijian Zhaoe88fa492017-07-11 12:26:56 -070018#include <cbmem.h>
Subrata Banika281c0f2017-08-30 18:29:33 +053019#include <chip.h>
Lijian Zhaoe88fa492017-07-11 12:26:56 -070020#include <console/console.h>
Subrata Banika281c0f2017-08-30 18:29:33 +053021#include <device/device.h>
22#include <device/pci.h>
Lijian Zhaoe88fa492017-07-11 12:26:56 -070023#include <fsp/util.h>
Subrata Banik47569cf2017-10-12 17:59:02 +053024#include <intelblocks/ebda.h>
Subrata Banika281c0f2017-08-30 18:29:33 +053025#include <intelblocks/systemagent.h>
Subrata Banika281c0f2017-08-30 18:29:33 +053026#include <soc/pci_devs.h>
Lijian Zhaof0eb9992017-09-14 14:51:12 -070027#include <soc/smm.h>
Lijian Zhaoe88fa492017-07-11 12:26:56 -070028#include <soc/systemagent.h>
Subrata Banika281c0f2017-08-30 18:29:33 +053029#include <stdlib.h>
Lijian Zhaoe88fa492017-07-11 12:26:56 -070030
Lijian Zhaof0eb9992017-09-14 14:51:12 -070031void smm_region(void **start, size_t *size)
32{
33 *start = (void *)sa_get_tseg_base();
34 *size = sa_get_tseg_size();
35}
36
37/*
38 * Subregions within SMM
39 * +-------------------------+ BGSM
40 * | IED | IED_REGION_SIZE
41 * +-------------------------+
42 * | External Stage Cache | SMM_RESERVED_SIZE
43 * +-------------------------+
44 * | code and data |
45 * | (TSEG) |
46 * +-------------------------+ TSEG
47 */
48int smm_subregion(int sub, void **start, size_t *size)
49{
50 uintptr_t sub_base;
51 size_t sub_size;
52 void *smm_base;
53 const size_t ied_size = CONFIG_IED_REGION_SIZE;
54 const size_t cache_size = CONFIG_SMM_RESERVED_SIZE;
55
56 smm_region(&smm_base, &sub_size);
57 sub_base = (uintptr_t)smm_base;
58
59 switch (sub) {
60 case SMM_SUBREGION_HANDLER:
61 /* Handler starts at the base of TSEG. */
62 sub_size -= ied_size;
63 sub_size -= cache_size;
64 break;
65 case SMM_SUBREGION_CACHE:
66 /* External cache is in the middle of TSEG. */
67 sub_base += sub_size - (ied_size + cache_size);
68 sub_size = cache_size;
69 break;
70 case SMM_SUBREGION_CHIPSET:
71 /* IED is at the top. */
72 sub_base += sub_size - ied_size;
73 sub_size = ied_size;
74 break;
75 default:
76 return -1;
77 }
78
79 *start = (void *)sub_base;
80 *size = sub_size;
81
82 return 0;
83}
84
Subrata Banikd2cadc32017-10-12 16:40:17 +053085/* Calculate ME Stolen size */
86static size_t get_imr_size(void)
87{
88 size_t imr_size;
89
90 /* ME stolen memory */
91 imr_size = MCHBAR32(IMRLIMIT) - MCHBAR32(IMRBASE);
92
93 return imr_size;
94}
95
96/* Calculate PRMRR size based on user input PRMRR size and alignment */
97static size_t get_prmrr_size(uintptr_t dram_base,
98 const struct soc_intel_cannonlake_config *config)
99{
100 uintptr_t prmrr_base = dram_base;
101 size_t prmrr_size;
102
103 prmrr_size = config->PrmrrSize;
104
105 /* Allocate PRMRR memory for C6DRAM */
106 if (!prmrr_size) {
107 if (config->enable_c6dram)
108 prmrr_size = 1*MiB;
109 else
110 return 0;
111 }
112
113 /*
114 * PRMRR Sizes that are > 1MB and < 32MB are
115 * not supported and will fail out.
116 */
117 if ((prmrr_size > 1*MiB) && (prmrr_size < 32*MiB))
118 die("PRMRR Sizes that are > 1MB and < 32MB are not"
119 "supported!\n");
120
121 prmrr_base -= prmrr_size;
122 if (prmrr_size >= 32*MiB)
123 prmrr_base = ALIGN_DOWN(prmrr_base, 128*MiB);
124 else
125 prmrr_base = ALIGN_DOWN(prmrr_base, 16*MiB);
126 /* PRMRR Area Size */
127 prmrr_size = dram_base - prmrr_base;
128
129 return prmrr_size;
130}
131
132/* Calculate Intel Traditional Memory size based on GSM, DSM, TSEG and DPR. */
133static size_t calculate_traditional_mem_size(uintptr_t dram_base,
134 const struct device *dev)
135{
136 uintptr_t traditional_mem_base = dram_base;
137 size_t traditional_mem_size;
138
139 if (dev->enabled) {
140 /* Read BDSM from Host Bridge */
141 traditional_mem_base -= sa_get_dsm_size();
142
143 /* Read BGSM from Host Bridge */
144 traditional_mem_base -= sa_get_gsm_size();
145 }
146 /* Get TSEG size */
147 traditional_mem_base -= sa_get_tseg_size();
148
149 /* Get DPR size */
150 if (IS_ENABLED(CONFIG_SA_ENABLE_DPR))
151 traditional_mem_base -= sa_get_dpr_size();
152
153 /* Traditional Area Size */
154 traditional_mem_size = dram_base - traditional_mem_base;
155
156 return traditional_mem_size;
157}
158
159/*
160 * Calculate Intel Reserved Memory size based on
161 * PRMRR size, Me stolen memory and PTT selection.
162 */
163static size_t calculate_reserved_mem_size(uintptr_t dram_base,
164 const struct device *dev)
165{
166 uintptr_t reserve_mem_base = dram_base;
167 size_t reserve_mem_size;
168 const struct soc_intel_cannonlake_config *config;
169
170 config = dev->chip_info;
171
172 /* Get PRMRR size */
173 reserve_mem_base -= get_prmrr_size(reserve_mem_base, config);
174
175 /* Get Tracehub size */
176 reserve_mem_base -= get_imr_size();
177
Subrata Banikd2cadc32017-10-12 16:40:17 +0530178 /* Traditional Area Size */
179 reserve_mem_size = dram_base - reserve_mem_base;
180
181 return reserve_mem_size;
182}
183
Subrata Banika281c0f2017-08-30 18:29:33 +0530184/*
185 * Host Memory Map:
186 *
187 * +--------------------------+ TOUUD
188 * | |
189 * +--------------------------+ 4GiB
190 * | PCI Address Space |
191 * +--------------------------+ TOLUD (also maps into MC address space)
192 * | iGD |
193 * +--------------------------+ BDSM
194 * | GTT |
195 * +--------------------------+ BGSM
196 * | TSEG |
197 * +--------------------------+ TSEGMB
198 * | DMA Protected Region |
199 * +--------------------------+ DPR
200 * | PRM (C6DRAM/SGX) |
201 * +--------------------------+ PRMRR
202 * | ME Stolen Memory |
203 * +--------------------------+ ME Stolen
204 * | PTT |
205 * +--------------------------+ top_of_ram
206 * | Reserved - FSP/CBMEM |
207 * +--------------------------+ TOLUM
208 * | Usage DRAM |
209 * +--------------------------+ 0
210 *
211 * Some of the base registers above can be equal making the size of those
212 * regions 0. The reason is because the memory controller internally subtracts
213 * the base registers from each other to determine sizes of the regions. In
214 * other words, the memory map is in a fixed order no matter what.
215 */
Subrata Banikd2cadc32017-10-12 16:40:17 +0530216static uintptr_t calculate_dram_base(size_t *reserved_mem_size)
Subrata Banika281c0f2017-08-30 18:29:33 +0530217{
Subrata Banika281c0f2017-08-30 18:29:33 +0530218 uintptr_t dram_base;
Subrata Banikd2cadc32017-10-12 16:40:17 +0530219 const struct device *dev;
Subrata Banika281c0f2017-08-30 18:29:33 +0530220
221 dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_IGD, 0));
Subrata Banikb92ad0b2017-09-05 18:44:15 +0530222 if (!dev)
Subrata Banikd2cadc32017-10-12 16:40:17 +0530223 die("ERROR - IGD device not found!");
Subrata Banika281c0f2017-08-30 18:29:33 +0530224
225 /* Read TOLUD from Host Bridge offset */
226 dram_base = sa_get_tolud_base();
227
Subrata Banikd2cadc32017-10-12 16:40:17 +0530228 /* Get Intel Traditional Memory Range Size */
229 dram_base -= calculate_traditional_mem_size(dram_base, dev);
Subrata Banika281c0f2017-08-30 18:29:33 +0530230
Subrata Banikd2cadc32017-10-12 16:40:17 +0530231 /* Get Intel Reserved Memory Range Size */
232 *reserved_mem_size = calculate_reserved_mem_size(dram_base, dev);
Subrata Banika281c0f2017-08-30 18:29:33 +0530233
Subrata Banikd2cadc32017-10-12 16:40:17 +0530234 dram_base -= *reserved_mem_size;
Subrata Banika281c0f2017-08-30 18:29:33 +0530235
236 return dram_base;
237}
238
Subrata Banikcaca9c72017-10-12 18:03:21 +0530239/*
240 * SoC implementation
241 *
242 * SoC call to summarize all Intel Reserve MMIO size and report to SA
243 */
244size_t soc_reserved_mmio_size(void)
245{
Subrata Baniked169412017-10-19 16:40:14 +0530246 struct ebda_config cfg;
Subrata Banikcaca9c72017-10-12 18:03:21 +0530247
Subrata Baniked169412017-10-19 16:40:14 +0530248 retrieve_ebda_object(&cfg);
Subrata Banikcaca9c72017-10-12 18:03:21 +0530249
250 /* Get Intel Reserved Memory Range Size */
Subrata Baniked169412017-10-19 16:40:14 +0530251 return cfg.reserved_mem_size;
Subrata Banikcaca9c72017-10-12 18:03:21 +0530252}
253
Subrata Banik47569cf2017-10-12 17:59:02 +0530254/* Fill up memory layout information */
255void fill_soc_memmap_ebda(struct ebda_config *cfg)
Lijian Zhaoe88fa492017-07-11 12:26:56 -0700256{
Subrata Banikd2cadc32017-10-12 16:40:17 +0530257 size_t chipset_mem_size;
Lijian Zhaoe88fa492017-07-11 12:26:56 -0700258
Subrata Banik47569cf2017-10-12 17:59:02 +0530259 cfg->tolum_base = calculate_dram_base(&chipset_mem_size);
Subrata Baniked169412017-10-19 16:40:14 +0530260 cfg->reserved_mem_size = chipset_mem_size;
Lijian Zhaoe88fa492017-07-11 12:26:56 -0700261}
262
Subrata Banik47569cf2017-10-12 17:59:02 +0530263void cbmem_top_init(void)
264{
265 /* Fill up EBDA area */
266 fill_ebda_area();
267}
268
269/*
270 * +-------------------------+ Top of RAM (aligned)
271 * | System Management Mode |
272 * | code and data | Length: CONFIG_TSEG_SIZE
273 * | (TSEG) |
274 * +-------------------------+ SMM base (aligned)
275 * | |
276 * | Chipset Reserved Memory |
277 * | |
278 * +-------------------------+ top_of_ram (aligned)
279 * | |
280 * | CBMEM Root |
281 * | |
282 * +-------------------------+
283 * | |
284 * | FSP Reserved Memory |
285 * | |
286 * +-------------------------+
287 * | |
288 * | Various CBMEM Entries |
289 * | |
290 * +-------------------------+ top_of_stack (8 byte aligned)
291 * | |
292 * | stack (CBMEM Entry) |
293 * | |
294 * +-------------------------+
295 */
Lijian Zhaoe88fa492017-07-11 12:26:56 -0700296void *cbmem_top(void)
297{
Subrata Banik47569cf2017-10-12 17:59:02 +0530298 struct ebda_config ebda_cfg;
Subrata Banik47569cf2017-10-12 17:59:02 +0530299
Lijian Zhaoe88fa492017-07-11 12:26:56 -0700300 /*
Subrata Banik47569cf2017-10-12 17:59:02 +0530301 * Check if Tseg has been initialized, we will use this as a flag
302 * to check if the MRC is done, and only then continue to read the
303 * PRMMR_BASE MSR. The system hangs if PRMRR_BASE MSR is read before
304 * PRMRR_MASK MSR lock bit is set.
Lijian Zhaoe88fa492017-07-11 12:26:56 -0700305 */
Subrata Banik47569cf2017-10-12 17:59:02 +0530306 if (sa_get_tseg_base() == 0)
307 return NULL;
308
Arthur Heymansac312c62018-04-09 23:14:22 +0200309 retrieve_ebda_object(&ebda_cfg);
Subrata Banik47569cf2017-10-12 17:59:02 +0530310
Arthur Heymansac312c62018-04-09 23:14:22 +0200311 return (void *)(uintptr_t)ebda_cfg.tolum_base;
Lijian Zhaoe88fa492017-07-11 12:26:56 -0700312}