Commit | Line | Data |
---|---|---|
ff53604b XG |
1 | /* |
2 | * vMTRR implementation | |
3 | * | |
4 | * Copyright (C) 2006 Qumranet, Inc. | |
5 | * Copyright 2010 Red Hat, Inc. and/or its affiliates. | |
6 | * Copyright(C) 2015 Intel Corporation. | |
7 | * | |
8 | * Authors: | |
9 | * Yaniv Kamay <yaniv@qumranet.com> | |
10 | * Avi Kivity <avi@qumranet.com> | |
11 | * Marcelo Tosatti <mtosatti@redhat.com> | |
12 | * Paolo Bonzini <pbonzini@redhat.com> | |
13 | * Xiao Guangrong <guangrong.xiao@linux.intel.com> | |
14 | * | |
15 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
16 | * the COPYING file in the top-level directory. | |
17 | */ | |
18 | ||
19 | #include <linux/kvm_host.h> | |
20 | #include <asm/mtrr.h> | |
21 | ||
22 | #include "cpuid.h" | |
23 | #include "mmu.h" | |
24 | ||
10fac2dc XG |
25 | #define IA32_MTRR_DEF_TYPE_E (1ULL << 11) |
26 | #define IA32_MTRR_DEF_TYPE_FE (1ULL << 10) | |
27 | #define IA32_MTRR_DEF_TYPE_TYPE_MASK (0xff) | |
28 | ||
ff53604b XG |
29 | static bool msr_mtrr_valid(unsigned msr) |
30 | { | |
31 | switch (msr) { | |
32 | case 0x200 ... 0x200 + 2 * KVM_NR_VAR_MTRR - 1: | |
33 | case MSR_MTRRfix64K_00000: | |
34 | case MSR_MTRRfix16K_80000: | |
35 | case MSR_MTRRfix16K_A0000: | |
36 | case MSR_MTRRfix4K_C0000: | |
37 | case MSR_MTRRfix4K_C8000: | |
38 | case MSR_MTRRfix4K_D0000: | |
39 | case MSR_MTRRfix4K_D8000: | |
40 | case MSR_MTRRfix4K_E0000: | |
41 | case MSR_MTRRfix4K_E8000: | |
42 | case MSR_MTRRfix4K_F0000: | |
43 | case MSR_MTRRfix4K_F8000: | |
44 | case MSR_MTRRdefType: | |
45 | case MSR_IA32_CR_PAT: | |
46 | return true; | |
47 | case 0x2f8: | |
48 | return true; | |
49 | } | |
50 | return false; | |
51 | } | |
52 | ||
53 | static bool valid_pat_type(unsigned t) | |
54 | { | |
55 | return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */ | |
56 | } | |
57 | ||
58 | static bool valid_mtrr_type(unsigned t) | |
59 | { | |
60 | return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */ | |
61 | } | |
62 | ||
63 | bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |
64 | { | |
65 | int i; | |
66 | u64 mask; | |
67 | ||
68 | if (!msr_mtrr_valid(msr)) | |
69 | return false; | |
70 | ||
71 | if (msr == MSR_IA32_CR_PAT) { | |
72 | for (i = 0; i < 8; i++) | |
73 | if (!valid_pat_type((data >> (i * 8)) & 0xff)) | |
74 | return false; | |
75 | return true; | |
76 | } else if (msr == MSR_MTRRdefType) { | |
77 | if (data & ~0xcff) | |
78 | return false; | |
79 | return valid_mtrr_type(data & 0xff); | |
80 | } else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) { | |
81 | for (i = 0; i < 8 ; i++) | |
82 | if (!valid_mtrr_type((data >> (i * 8)) & 0xff)) | |
83 | return false; | |
84 | return true; | |
85 | } | |
86 | ||
87 | /* variable MTRRs */ | |
88 | WARN_ON(!(msr >= 0x200 && msr < 0x200 + 2 * KVM_NR_VAR_MTRR)); | |
89 | ||
90 | mask = (~0ULL) << cpuid_maxphyaddr(vcpu); | |
91 | if ((msr & 1) == 0) { | |
92 | /* MTRR base */ | |
93 | if (!valid_mtrr_type(data & 0xff)) | |
94 | return false; | |
95 | mask |= 0xf00; | |
96 | } else | |
97 | /* MTRR mask */ | |
98 | mask |= 0x7ff; | |
99 | if (data & mask) { | |
100 | kvm_inject_gp(vcpu, 0); | |
101 | return false; | |
102 | } | |
103 | ||
104 | return true; | |
105 | } | |
106 | EXPORT_SYMBOL_GPL(kvm_mtrr_valid); | |
107 | ||
10fac2dc XG |
108 | static bool mtrr_is_enabled(struct kvm_mtrr *mtrr_state) |
109 | { | |
110 | return !!(mtrr_state->deftype & IA32_MTRR_DEF_TYPE_E); | |
111 | } | |
112 | ||
113 | static bool fixed_mtrr_is_enabled(struct kvm_mtrr *mtrr_state) | |
114 | { | |
115 | return !!(mtrr_state->deftype & IA32_MTRR_DEF_TYPE_FE); | |
116 | } | |
117 | ||
118 | static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state) | |
119 | { | |
120 | return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK; | |
121 | } | |
122 | ||
ff53604b XG |
123 | static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr) |
124 | { | |
70109e7d | 125 | struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state; |
ff53604b XG |
126 | gfn_t start, end, mask; |
127 | int index; | |
128 | bool is_fixed = true; | |
129 | ||
130 | if (msr == MSR_IA32_CR_PAT || !tdp_enabled || | |
131 | !kvm_arch_has_noncoherent_dma(vcpu->kvm)) | |
132 | return; | |
133 | ||
10fac2dc | 134 | if (!mtrr_is_enabled(mtrr_state) && msr != MSR_MTRRdefType) |
ff53604b XG |
135 | return; |
136 | ||
137 | switch (msr) { | |
138 | case MSR_MTRRfix64K_00000: | |
139 | start = 0x0; | |
140 | end = 0x80000; | |
141 | break; | |
142 | case MSR_MTRRfix16K_80000: | |
143 | start = 0x80000; | |
144 | end = 0xa0000; | |
145 | break; | |
146 | case MSR_MTRRfix16K_A0000: | |
147 | start = 0xa0000; | |
148 | end = 0xc0000; | |
149 | break; | |
150 | case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000: | |
151 | index = msr - MSR_MTRRfix4K_C0000; | |
152 | start = 0xc0000 + index * (32 << 10); | |
153 | end = start + (32 << 10); | |
154 | break; | |
155 | case MSR_MTRRdefType: | |
156 | is_fixed = false; | |
157 | start = 0x0; | |
158 | end = ~0ULL; | |
159 | break; | |
160 | default: | |
161 | /* variable range MTRRs. */ | |
162 | is_fixed = false; | |
163 | index = (msr - 0x200) / 2; | |
86fd5270 XG |
164 | start = mtrr_state->var_ranges[index].base & PAGE_MASK; |
165 | mask = mtrr_state->var_ranges[index].mask & PAGE_MASK; | |
ff53604b XG |
166 | mask |= ~0ULL << cpuid_maxphyaddr(vcpu); |
167 | ||
168 | end = ((start & mask) | ~mask) + 1; | |
169 | } | |
170 | ||
10fac2dc | 171 | if (is_fixed && !fixed_mtrr_is_enabled(mtrr_state)) |
ff53604b XG |
172 | return; |
173 | ||
174 | kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end)); | |
175 | } | |
176 | ||
177 | int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |
178 | { | |
179 | u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges; | |
180 | ||
181 | if (!kvm_mtrr_valid(vcpu, msr, data)) | |
182 | return 1; | |
183 | ||
10fac2dc XG |
184 | if (msr == MSR_MTRRdefType) |
185 | vcpu->arch.mtrr_state.deftype = data; | |
186 | else if (msr == MSR_MTRRfix64K_00000) | |
ff53604b XG |
187 | p[0] = data; |
188 | else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000) | |
189 | p[1 + msr - MSR_MTRRfix16K_80000] = data; | |
190 | else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000) | |
191 | p[3 + msr - MSR_MTRRfix4K_C0000] = data; | |
192 | else if (msr == MSR_IA32_CR_PAT) | |
193 | vcpu->arch.pat = data; | |
194 | else { /* Variable MTRRs */ | |
195 | int idx, is_mtrr_mask; | |
ff53604b XG |
196 | |
197 | idx = (msr - 0x200) / 2; | |
198 | is_mtrr_mask = msr - 0x200 - 2 * idx; | |
199 | if (!is_mtrr_mask) | |
86fd5270 | 200 | vcpu->arch.mtrr_state.var_ranges[idx].base = data; |
ff53604b | 201 | else |
86fd5270 | 202 | vcpu->arch.mtrr_state.var_ranges[idx].mask = data; |
ff53604b XG |
203 | } |
204 | ||
205 | update_mtrr(vcpu, msr); | |
206 | return 0; | |
207 | } | |
208 | ||
209 | int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |
210 | { | |
211 | u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges; | |
212 | ||
eb839917 XG |
213 | /* MSR_MTRRcap is a readonly MSR. */ |
214 | if (msr == MSR_MTRRcap) { | |
215 | /* | |
216 | * SMRR = 0 | |
217 | * WC = 1 | |
218 | * FIX = 1 | |
219 | * VCNT = KVM_NR_VAR_MTRR | |
220 | */ | |
221 | *pdata = 0x500 | KVM_NR_VAR_MTRR; | |
222 | return 0; | |
223 | } | |
224 | ||
ff53604b XG |
225 | if (!msr_mtrr_valid(msr)) |
226 | return 1; | |
227 | ||
228 | if (msr == MSR_MTRRdefType) | |
10fac2dc | 229 | *pdata = vcpu->arch.mtrr_state.deftype; |
ff53604b XG |
230 | else if (msr == MSR_MTRRfix64K_00000) |
231 | *pdata = p[0]; | |
232 | else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000) | |
233 | *pdata = p[1 + msr - MSR_MTRRfix16K_80000]; | |
234 | else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000) | |
235 | *pdata = p[3 + msr - MSR_MTRRfix4K_C0000]; | |
236 | else if (msr == MSR_IA32_CR_PAT) | |
237 | *pdata = vcpu->arch.pat; | |
238 | else { /* Variable MTRRs */ | |
239 | int idx, is_mtrr_mask; | |
ff53604b XG |
240 | |
241 | idx = (msr - 0x200) / 2; | |
242 | is_mtrr_mask = msr - 0x200 - 2 * idx; | |
243 | if (!is_mtrr_mask) | |
86fd5270 | 244 | *pdata = vcpu->arch.mtrr_state.var_ranges[idx].base; |
ff53604b | 245 | else |
86fd5270 | 246 | *pdata = vcpu->arch.mtrr_state.var_ranges[idx].mask; |
ff53604b XG |
247 | } |
248 | ||
249 | return 0; | |
250 | } | |
251 | ||
3f3f78b6 | 252 | u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn) |
ff53604b | 253 | { |
3f3f78b6 XG |
254 | struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state; |
255 | u64 base, mask, start; | |
256 | int i, num_var_ranges, type; | |
257 | const int wt_wb_mask = (1 << MTRR_TYPE_WRBACK) | |
258 | | (1 << MTRR_TYPE_WRTHROUGH); | |
259 | ||
260 | start = gfn_to_gpa(gfn); | |
261 | num_var_ranges = KVM_NR_VAR_MTRR; | |
262 | type = -1; | |
ff53604b XG |
263 | |
264 | /* MTRR is completely disabled, use UC for all of physical memory. */ | |
10fac2dc | 265 | if (!mtrr_is_enabled(mtrr_state)) |
ff53604b XG |
266 | return MTRR_TYPE_UNCACHABLE; |
267 | ||
ff53604b | 268 | /* Look in fixed ranges. Just return the type as per start */ |
10fac2dc | 269 | if (fixed_mtrr_is_enabled(mtrr_state) && (start < 0x100000)) { |
ff53604b XG |
270 | int idx; |
271 | ||
272 | if (start < 0x80000) { | |
273 | idx = 0; | |
274 | idx += (start >> 16); | |
275 | return mtrr_state->fixed_ranges[idx]; | |
276 | } else if (start < 0xC0000) { | |
277 | idx = 1 * 8; | |
278 | idx += ((start - 0x80000) >> 14); | |
279 | return mtrr_state->fixed_ranges[idx]; | |
280 | } else if (start < 0x1000000) { | |
281 | idx = 3 * 8; | |
282 | idx += ((start - 0xC0000) >> 12); | |
283 | return mtrr_state->fixed_ranges[idx]; | |
284 | } | |
285 | } | |
286 | ||
287 | /* | |
288 | * Look in variable ranges | |
289 | * Look of multiple ranges matching this address and pick type | |
290 | * as per MTRR precedence | |
291 | */ | |
ff53604b | 292 | for (i = 0; i < num_var_ranges; ++i) { |
3f3f78b6 | 293 | int curr_type; |
ff53604b | 294 | |
86fd5270 | 295 | if (!(mtrr_state->var_ranges[i].mask & (1 << 11))) |
ff53604b XG |
296 | continue; |
297 | ||
86fd5270 XG |
298 | base = mtrr_state->var_ranges[i].base & PAGE_MASK; |
299 | mask = mtrr_state->var_ranges[i].mask & PAGE_MASK; | |
ff53604b | 300 | |
ff53604b XG |
301 | if ((start & mask) != (base & mask)) |
302 | continue; | |
303 | ||
3f3f78b6 XG |
304 | /* |
305 | * Please refer to Intel SDM Volume 3: 11.11.4.1 MTRR | |
306 | * Precedences. | |
307 | */ | |
308 | ||
309 | curr_type = mtrr_state->var_ranges[i].base & 0xff; | |
310 | if (type == -1) { | |
311 | type = curr_type; | |
ff53604b XG |
312 | continue; |
313 | } | |
314 | ||
3f3f78b6 XG |
315 | /* |
316 | * If two or more variable memory ranges match and the | |
317 | * memory types are identical, then that memory type is | |
318 | * used. | |
319 | */ | |
320 | if (type == curr_type) | |
321 | continue; | |
322 | ||
323 | /* | |
324 | * If two or more variable memory ranges match and one of | |
325 | * the memory types is UC, the UC memory type used. | |
326 | */ | |
327 | if (curr_type == MTRR_TYPE_UNCACHABLE) | |
ff53604b XG |
328 | return MTRR_TYPE_UNCACHABLE; |
329 | ||
3f3f78b6 XG |
330 | /* |
331 | * If two or more variable memory ranges match and the | |
332 | * memory types are WT and WB, the WT memory type is used. | |
333 | */ | |
334 | if (((1 << type) & wt_wb_mask) && | |
335 | ((1 << curr_type) & wt_wb_mask)) { | |
336 | type = MTRR_TYPE_WRTHROUGH; | |
337 | continue; | |
ff53604b XG |
338 | } |
339 | ||
3f3f78b6 XG |
340 | /* |
341 | * For overlaps not defined by the above rules, processor | |
342 | * behavior is undefined. | |
343 | */ | |
344 | ||
345 | /* We use WB for this undefined behavior. :( */ | |
346 | return MTRR_TYPE_WRBACK; | |
ff53604b XG |
347 | } |
348 | ||
3f3f78b6 XG |
349 | if (type != -1) |
350 | return type; | |
ff53604b | 351 | |
10fac2dc | 352 | return mtrr_default_type(mtrr_state); |
ff53604b | 353 | } |
ff53604b | 354 | EXPORT_SYMBOL_GPL(kvm_mtrr_get_guest_memory_type); |