x86: Sort the MTRR table
[platform/kernel/u-boot.git] / arch / x86 / cpu / mtrr.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2014 Google, Inc
4  *
5  * Memory Type Range Regsters - these are used to tell the CPU whether
6  * memory is cacheable and if so the cache write mode to use.
7  *
8  * These can speed up booting. See the mtrr command.
9  *
10  * Reference: Intel Architecture Software Developer's Manual, Volume 3:
11  * System Programming
12  */
13
14 /*
15  * Note that any console output (e.g. debug()) in this file will likely fail
16  * since the MTRR registers are sometimes in flux.
17  */
18
19 #include <common.h>
20 #include <cpu_func.h>
21 #include <log.h>
22 #include <sort.h>
23 #include <asm/cache.h>
24 #include <asm/io.h>
25 #include <asm/mp.h>
26 #include <asm/msr.h>
27 #include <asm/mtrr.h>
28
29 DECLARE_GLOBAL_DATA_PTR;
30
31 /* Prepare to adjust MTRRs */
32 void mtrr_open(struct mtrr_state *state, bool do_caches)
33 {
34         if (!gd->arch.has_mtrr)
35                 return;
36
37         if (do_caches) {
38                 state->enable_cache = dcache_status();
39
40                 if (state->enable_cache)
41                         disable_caches();
42         }
43         state->deftype = native_read_msr(MTRR_DEF_TYPE_MSR);
44         wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype & ~MTRR_DEF_TYPE_EN);
45 }
46
47 /* Clean up after adjusting MTRRs, and enable them */
48 void mtrr_close(struct mtrr_state *state, bool do_caches)
49 {
50         if (!gd->arch.has_mtrr)
51                 return;
52
53         wrmsrl(MTRR_DEF_TYPE_MSR, state->deftype | MTRR_DEF_TYPE_EN);
54         if (do_caches && state->enable_cache)
55                 enable_caches();
56 }
57
58 static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size)
59 {
60         u64 mask;
61
62         wrmsrl(MTRR_PHYS_BASE_MSR(reg), start | type);
63         mask = ~(size - 1);
64         mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
65         wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask | MTRR_PHYS_MASK_VALID);
66 }
67
68 void mtrr_read_all(struct mtrr_info *info)
69 {
70         int i;
71
72         for (i = 0; i < MTRR_COUNT; i++) {
73                 info->mtrr[i].base = native_read_msr(MTRR_PHYS_BASE_MSR(i));
74                 info->mtrr[i].mask = native_read_msr(MTRR_PHYS_MASK_MSR(i));
75         }
76 }
77
78 void mtrr_write_all(struct mtrr_info *info)
79 {
80         struct mtrr_state state;
81         int i;
82
83         for (i = 0; i < MTRR_COUNT; i++) {
84                 mtrr_open(&state, true);
85                 wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base);
86                 wrmsrl(MTRR_PHYS_MASK_MSR(i), info->mtrr[i].mask);
87                 mtrr_close(&state, true);
88         }
89 }
90
91 static void write_mtrrs(void *arg)
92 {
93         struct mtrr_info *info = arg;
94
95         mtrr_write_all(info);
96 }
97
98 static void read_mtrrs(void *arg)
99 {
100         struct mtrr_info *info = arg;
101
102         mtrr_read_all(info);
103 }
104
105 /**
106  * mtrr_copy_to_aps() - Copy the MTRRs from the boot CPU to other CPUs
107  *
108  * @return 0 on success, -ve on failure
109  */
110 static int mtrr_copy_to_aps(void)
111 {
112         struct mtrr_info info;
113         int ret;
114
115         ret = mp_run_on_cpus(MP_SELECT_BSP, read_mtrrs, &info);
116         if (ret == -ENXIO)
117                 return 0;
118         else if (ret)
119                 return log_msg_ret("bsp", ret);
120
121         ret = mp_run_on_cpus(MP_SELECT_APS, write_mtrrs, &info);
122         if (ret)
123                 return log_msg_ret("bsp", ret);
124
125         return 0;
126 }
127
128 static int h_comp_mtrr(const void *p1, const void *p2)
129 {
130         const struct mtrr_request *req1 = p1;
131         const struct mtrr_request *req2 = p2;
132
133         s64 diff = req1->start - req2->start;
134
135         return diff < 0 ? -1 : diff > 0 ? 1 : 0;
136 }
137
138 int mtrr_commit(bool do_caches)
139 {
140         struct mtrr_request *req = gd->arch.mtrr_req;
141         struct mtrr_state state;
142         int ret;
143         int i;
144
145         debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr,
146               gd->arch.mtrr_req_count);
147         if (!gd->arch.has_mtrr)
148                 return -ENOSYS;
149
150         debug("open\n");
151         mtrr_open(&state, do_caches);
152         debug("open done\n");
153         qsort(req, gd->arch.mtrr_req_count, sizeof(*req), h_comp_mtrr);
154         for (i = 0; i < gd->arch.mtrr_req_count; i++, req++)
155                 set_var_mtrr(i, req->type, req->start, req->size);
156
157         /* Clear the ones that are unused */
158         debug("clear\n");
159         for (; i < MTRR_COUNT; i++)
160                 wrmsrl(MTRR_PHYS_MASK_MSR(i), 0);
161         debug("close\n");
162         mtrr_close(&state, do_caches);
163         debug("mtrr done\n");
164
165         if (gd->flags & GD_FLG_RELOC) {
166                 ret = mtrr_copy_to_aps();
167                 if (ret)
168                         return log_msg_ret("copy", ret);
169         }
170
171         return 0;
172 }
173
174 int mtrr_add_request(int type, uint64_t start, uint64_t size)
175 {
176         struct mtrr_request *req;
177         uint64_t mask;
178
179         debug("%s: count=%d\n", __func__, gd->arch.mtrr_req_count);
180         if (!gd->arch.has_mtrr)
181                 return -ENOSYS;
182
183         if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
184                 return -ENOSPC;
185         req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
186         req->type = type;
187         req->start = start;
188         req->size = size;
189         debug("%d: type=%d, %08llx  %08llx\n", gd->arch.mtrr_req_count - 1,
190               req->type, req->start, req->size);
191         mask = ~(req->size - 1);
192         mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
193         mask |= MTRR_PHYS_MASK_VALID;
194         debug("   %016llx %016llx\n", req->start | req->type, mask);
195
196         return 0;
197 }
198
199 static int get_var_mtrr_count(void)
200 {
201         return msr_read(MSR_MTRR_CAP_MSR).lo & MSR_MTRR_CAP_VCNT;
202 }
203
204 static int get_free_var_mtrr(void)
205 {
206         struct msr_t maskm;
207         int vcnt;
208         int i;
209
210         vcnt = get_var_mtrr_count();
211
212         /* Identify the first var mtrr which is not valid */
213         for (i = 0; i < vcnt; i++) {
214                 maskm = msr_read(MTRR_PHYS_MASK_MSR(i));
215                 if ((maskm.lo & MTRR_PHYS_MASK_VALID) == 0)
216                         return i;
217         }
218
219         /* No free var mtrr */
220         return -ENOSPC;
221 }
222
223 int mtrr_set_next_var(uint type, uint64_t start, uint64_t size)
224 {
225         int mtrr;
226
227         mtrr = get_free_var_mtrr();
228         if (mtrr < 0)
229                 return mtrr;
230
231         set_var_mtrr(mtrr, type, start, size);
232         debug("MTRR %x: start=%x, size=%x\n", mtrr, (uint)start, (uint)size);
233
234         return 0;
235 }
236
237 /** enum mtrr_opcode - supported operations for mtrr_do_oper() */
238 enum mtrr_opcode {
239         MTRR_OP_SET,
240         MTRR_OP_SET_VALID,
241 };
242
243 /**
244  * struct mtrr_oper - An MTRR operation to perform on a CPU
245  *
246  * @opcode: Indicates operation to perform
247  * @reg: MTRR reg number to select (0-7, -1 = all)
248  * @valid: Valid value to write for MTRR_OP_SET_VALID
249  * @base: Base value to write for MTRR_OP_SET
250  * @mask: Mask value to write for MTRR_OP_SET
251  */
252 struct mtrr_oper {
253         enum mtrr_opcode opcode;
254         int reg;
255         bool valid;
256         u64 base;
257         u64 mask;
258 };
259
260 static void mtrr_do_oper(void *arg)
261 {
262         struct mtrr_oper *oper = arg;
263         u64 mask;
264
265         switch (oper->opcode) {
266         case MTRR_OP_SET_VALID:
267                 mask = native_read_msr(MTRR_PHYS_MASK_MSR(oper->reg));
268                 if (oper->valid)
269                         mask |= MTRR_PHYS_MASK_VALID;
270                 else
271                         mask &= ~MTRR_PHYS_MASK_VALID;
272                 wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), mask);
273                 break;
274         case MTRR_OP_SET:
275                 wrmsrl(MTRR_PHYS_BASE_MSR(oper->reg), oper->base);
276                 wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), oper->mask);
277                 break;
278         }
279 }
280
281 static int mtrr_start_op(int cpu_select, struct mtrr_oper *oper)
282 {
283         struct mtrr_state state;
284         int ret;
285
286         mtrr_open(&state, true);
287         ret = mp_run_on_cpus(cpu_select, mtrr_do_oper, oper);
288         mtrr_close(&state, true);
289         if (ret)
290                 return log_msg_ret("run", ret);
291
292         return 0;
293 }
294
295 int mtrr_set_valid(int cpu_select, int reg, bool valid)
296 {
297         struct mtrr_oper oper;
298
299         oper.opcode = MTRR_OP_SET_VALID;
300         oper.reg = reg;
301         oper.valid = valid;
302
303         return mtrr_start_op(cpu_select, &oper);
304 }
305
306 int mtrr_set(int cpu_select, int reg, u64 base, u64 mask)
307 {
308         struct mtrr_oper oper;
309
310         oper.opcode = MTRR_OP_SET;
311         oper.reg = reg;
312         oper.base = base;
313         oper.mask = mask;
314
315         return mtrr_start_op(cpu_select, &oper);
316 }