1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <commonlib/bsd/helpers.h>
#include <console/console.h>
#include <cpu/x86/mtrr.h>
#include <cpu/amd/mtrr.h>
#include <soc/mtrr.h>
/* Picasso defines 8 Variable MTRRs */
#define MAX_VARIABLE_MTRRS 8
#define SYS_CFG_MTRR_BITS ( \
SYSCFG_MSR_TOM2WB | \
SYSCFG_MSR_TOM2En | \
SYSCFG_MSR_MtrrVarDramEn | \
SYSCFG_MSR_MtrrFixDramModEn | \
SYSCFG_MSR_MtrrFixDramEn \
)
static const unsigned int fixed_mtrr_offsets[] = {
MTRR_FIX_64K_00000,
MTRR_FIX_16K_80000,
MTRR_FIX_16K_A0000,
MTRR_FIX_4K_C0000,
MTRR_FIX_4K_C8000,
MTRR_FIX_4K_D0000,
MTRR_FIX_4K_D8000,
MTRR_FIX_4K_E0000,
MTRR_FIX_4K_E8000,
MTRR_FIX_4K_F0000,
MTRR_FIX_4K_F8000,
};
static int mtrrs_saved;
static msr_t sys_cfg;
static msr_t mtrr_def;
static msr_t mtrr_base[MAX_VARIABLE_MTRRS];
static msr_t mtrr_mask[MAX_VARIABLE_MTRRS];
static msr_t fixed_mtrrs[ARRAY_SIZE(fixed_mtrr_offsets)];
void picasso_save_mtrrs(void)
{
unsigned int i;
int mtrrs;
mtrrs = get_var_mtrr_count();
ASSERT_MSG(mtrrs == MAX_VARIABLE_MTRRS, "Unexpected number of MTRRs\n");
for (i = 0; i < MAX_VARIABLE_MTRRS; ++i) {
mtrr_base[i] = rdmsr(MTRR_PHYS_BASE(i));
mtrr_mask[i] = rdmsr(MTRR_PHYS_MASK(i));
printk(BIOS_DEBUG,
"Saving Variable MTRR %d: Base: 0x%08x 0x%08x, Mask: 0x%08x 0x%08x\n", i,
mtrr_base[i].hi, mtrr_base[i].lo, mtrr_mask[i].hi, mtrr_mask[i].lo);
}
for (i = 0; i < ARRAY_SIZE(fixed_mtrr_offsets); ++i) {
fixed_mtrrs[i] = rdmsr(fixed_mtrr_offsets[i]);
printk(BIOS_DEBUG, "Saving Fixed MTRR %u: 0x%08x 0x%08x\n", i,
fixed_mtrrs[i].hi, fixed_mtrrs[i].lo);
}
mtrr_def = rdmsr(MTRR_DEF_TYPE_MSR);
printk(BIOS_DEBUG, "Saving Default Type MTRR: 0x%08x 0x%08x\n", mtrr_def.hi,
mtrr_def.lo);
sys_cfg = rdmsr(SYSCFG_MSR);
printk(BIOS_DEBUG, "Saving SYS_CFG: 0x%08x 0x%08x\n", mtrr_def.hi, mtrr_def.lo);
mtrrs_saved = 1;
}
static void update_if_changed(unsigned int offset, msr_t expected)
{
msr_t tmp = rdmsr(offset);
if (tmp.lo == expected.lo && tmp.hi == expected.hi)
return;
printk(BIOS_INFO, "MSR %#x was modified: 0x%08x 0x%08x\n", offset, tmp.hi, tmp.lo);
wrmsr(offset, expected);
}
void picasso_restore_mtrrs(void)
{
unsigned int i;
msr_t tmp_sys_cfg;
ASSERT_MSG(mtrrs_saved, "Must save MTRRs before restoring.\n");
for (i = 0; i < MAX_VARIABLE_MTRRS; ++i) {
update_if_changed(MTRR_PHYS_BASE(i), mtrr_base[i]);
update_if_changed(MTRR_PHYS_MASK(i), mtrr_mask[i]);
}
for (i = 0; i < ARRAY_SIZE(fixed_mtrr_offsets); ++i)
update_if_changed(fixed_mtrr_offsets[i], fixed_mtrrs[i]);
update_if_changed(MTRR_DEF_TYPE_MSR, mtrr_def);
tmp_sys_cfg = rdmsr(SYSCFG_MSR);
/* We only care about the MTRR bits in the SYSCFG register */
if ((tmp_sys_cfg.lo & SYS_CFG_MTRR_BITS) != (sys_cfg.lo & SYS_CFG_MTRR_BITS)) {
printk(BIOS_INFO, "SYS_CFG was modified: 0x%08x 0x%08x\n", tmp_sys_cfg.hi,
tmp_sys_cfg.lo);
tmp_sys_cfg.lo &= ~SYS_CFG_MTRR_BITS;
tmp_sys_cfg.lo |= (sys_cfg.lo & SYS_CFG_MTRR_BITS);
wrmsr(SYSCFG_MSR, tmp_sys_cfg);
}
}
|