blob: 71921de9e3c47bc19de560d95e2262d76f8d1478 [file] [log] [blame]
Subrata Banik3ad00d02022-03-30 23:44:52 +05301/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <cpu/cpu.h>
4#include <cpu/x86/mtrr.h>
5#include <cpu/x86/msr.h>
6#include <console/console.h>
7
8/* Get first available variable MTRR.
9 * Returns var# if available, else returns -1.
10 */
11int get_free_var_mtrr(void)
12{
13 msr_t maskm;
14 int vcnt;
15 int i;
16
17 vcnt = get_var_mtrr_count();
18
19 /* Identify the first var mtrr which is not valid. */
20 for (i = 0; i < vcnt; i++) {
21 maskm = rdmsr(MTRR_PHYS_MASK(i));
22 if ((maskm.lo & MTRR_PHYS_MASK_VALID) == 0)
23 return i;
24 }
25
26 /* No free var mtrr. */
27 return -1;
28}
29
30void set_var_mtrr(
31 unsigned int reg, unsigned int base, unsigned int size, unsigned int type)
32{
33 /* Bit 32-35 of MTRRphysMask should be set to 1 */
34 /* FIXME: It only support 4G less range */
35 msr_t basem, maskm;
36
37 if (!IS_POWER_OF_2(size))
38 printk(BIOS_ERR, "MTRR Error: size %#x is not a power of two\n", size);
39 if (size < 4 * KiB)
40 printk(BIOS_ERR, "MTRR Error: size %#x smaller than 4KiB\n", size);
41 if (base % size != 0)
42 printk(BIOS_ERR, "MTRR Error: base %#x must be aligned to size %#x\n", base,
43 size);
44
45 basem.lo = base | type;
46 basem.hi = 0;
47 wrmsr(MTRR_PHYS_BASE(reg), basem);
48 maskm.lo = ~(size - 1) | MTRR_PHYS_MASK_VALID;
49 maskm.hi = (1 << (cpu_phys_address_size() - 32)) - 1;
50 wrmsr(MTRR_PHYS_MASK(reg), maskm);
51}
52
53void clear_all_var_mtrr(void)
54{
55 msr_t mtrr = {0, 0};
56 int vcnt;
57 int i;
58
59 vcnt = get_var_mtrr_count();
60
61 for (i = 0; i < vcnt; i++) {
62 wrmsr(MTRR_PHYS_MASK(i), mtrr);
63 wrmsr(MTRR_PHYS_BASE(i), mtrr);
64 }
65}