forked from kernelslacker/x86info
-
Notifications
You must be signed in to change notification settings - Fork 1
/
mtrr.c
210 lines (170 loc) · 4.28 KB
/
mtrr.c
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
* Licensed under the terms of the GNU GPL License version 2.
*
* MTRR register dumping.
* TODO : decode the registers too.
*/
#include <stdio.h>
#ifdef __linux__
#include <asm/mtrr.h>
#endif
#include <x86info.h>
#define IA32_MTRRCAP_WC (1 << 10)
#define IA32_MTRRCAP_FIX (1 << 8)
#define IA32_MTRRCAP_VCNT 0xFF
#define IA32_MTRR_DEFTYPE_E 0x800
#define IA32_MTRR_DEFTYPE_FE 0x400
#define IA32_MTRR_DEFTYPE_TYPE 0xFF
#define IA32_PHYBASE_TYPE 0XFF
#define IA32_PHYMASK_VALID (1 << 11)
static unsigned int max_phy_addr = 0;
#ifndef MTRR_NUM_TYPES
#define MTRR_NUM_TYPES 8
#endif
static const char * mtrr_types[MTRR_NUM_TYPES] =
{
"uncacheable",
"write-combining",
"?",
"?",
"write-through",
"write-protect",
"write-back",
};
static void decode_address(unsigned long long val)
{
switch (max_phy_addr) {
case 40:
printf("0x%07x ", (unsigned int) ((val >> 12) & 0xFFFFFFF));
break;
case 36:
default:
printf("0x%06x ", (unsigned int) ((val >> 12) & 0xFFFFFF));
break;
}
}
static void set_max_phy_addr(struct cpudata *cpu)
{
unsigned int value;
if (!max_phy_addr) {
cpuid(cpu->number, 0x80000008, &value, NULL, NULL, NULL);
max_phy_addr = value & 0xFF;
}
}
static int mtrr_value(int cpu, int msr, unsigned long long *val)
{
if (read_msr(cpu, msr, val) == 1)
return 1;
else
return 0;
}
static void dump_mtrr(int cpu, int msr)
{
unsigned long long val = 0;
if (read_msr(cpu, msr, &val) == 1)
printf("0x%016llx\n", val);
}
static void decode_mtrrcap(int cpu, int msr)
{
unsigned long long val;
int ret;
ret = mtrr_value(cpu, msr, &val);
if (ret) {
printf("0x%016llx ", val);
printf("wc:%d ",
!! ((unsigned int) val & IA32_MTRRCAP_WC));
printf("fix:%d ",
!! ((unsigned int) val & IA32_MTRRCAP_FIX));
printf("vcnt:%d\n",
(unsigned int) val & IA32_MTRRCAP_VCNT);
}
}
static void decode_mtrr_deftype(int cpu, int msr)
{
unsigned long long val;
int ret;
u8 type;
ret = mtrr_value(cpu,msr,&val);
if (ret) {
printf("0x%016llx ", val);
printf("(fixed-range flag:%d ",
!! ((unsigned int) val & (1 << 10)));
printf("enable flag:%d ",
!! ((unsigned int) val & (1 << 11)));
type = val & IA32_MTRR_DEFTYPE_TYPE;
printf("default type:0x%02x (%s))\n", type, mtrr_types[type]);
}
}
static void decode_mtrr_physbase(int cpu, int msr)
{
unsigned long long val;
int ret;
u8 type;
ret = mtrr_value(cpu, msr, &val);
if (ret) {
printf("0x%016llx ", val);
printf("(physbase:");
decode_address(val);
type = (unsigned int) val & IA32_PHYBASE_TYPE;
printf("type: 0x%02x (%s))\n", type, mtrr_types[type]);
}
}
static void decode_mtrr_physmask(int cpu, int msr)
{
unsigned long long val;
int ret;
ret = mtrr_value(cpu,msr,&val);
if (ret) {
printf("0x%016llx ", val);
printf("(physmask:");
decode_address(val);
printf("valid:%d)\n",
!! ((int) val & IA32_PHYMASK_VALID));
}
}
void dump_mtrrs(struct cpudata *cpu)
{
unsigned long long val = 0;
unsigned int i;
if (!(cpu->flags_edx & (X86_FEATURE_MTRR)))
return;
/*
* If MTRR registers are not accessible like in some
* virtualization systems then return
*/
if (!read_msr(cpu->number, 0xfe, &val))
return;
printf("MTRR registers:\n");
printf("MTRRcap (0xfe): ");
decode_mtrrcap(cpu->number, 0xfe);
set_max_phy_addr(cpu);
for (i = 0; i < 16; i+=2) {
printf("MTRRphysBase%u (0x%x): ", i / 2, (unsigned int) 0x200 + i);
decode_mtrr_physbase(cpu->number, 0x200 + i);
printf("MTRRphysMask%u (0x%x): ", i/2, (unsigned int) 0x201 + i);
decode_mtrr_physmask(cpu->number, 0x201 + i);
}
printf("MTRRfix64K_00000 (0x250): ");
dump_mtrr (cpu->number, 0x250);
printf("MTRRfix16K_80000 (0x258): ");
dump_mtrr (cpu->number, 0x258);
printf("MTRRfix16K_A0000 (0x259): ");
dump_mtrr (cpu->number, 0x259);
printf("MTRRfix4K_C8000 (0x269): ");
dump_mtrr (cpu->number, 0x269);
printf("MTRRfix4K_D0000 0x26a: ");
dump_mtrr (cpu->number, 0x26a);
printf("MTRRfix4K_D8000 0x26b: ");
dump_mtrr (cpu->number, 0x26b);
printf("MTRRfix4K_E0000 0x26c: ");
dump_mtrr (cpu->number, 0x26c);
printf("MTRRfix4K_E8000 0x26d: ");
dump_mtrr (cpu->number, 0x26d);
printf("MTRRfix4K_F0000 0x26e: ");
dump_mtrr (cpu->number, 0x26e);
printf("MTRRfix4K_F8000 0x26f: ");
dump_mtrr (cpu->number, 0x26f);
printf("MTRRdefType (0x2ff): ");
decode_mtrr_deftype(cpu->number, 0x2ff);
printf("\n");
}