xref: /openbmc/linux/arch/x86/kvm/mtrr.c (revision 86fd52701cfae760711fb02a03c1ab8c80ea72f3)
1ff53604bSXiao Guangrong /*
2ff53604bSXiao Guangrong  * vMTRR implementation
3ff53604bSXiao Guangrong  *
4ff53604bSXiao Guangrong  * Copyright (C) 2006 Qumranet, Inc.
5ff53604bSXiao Guangrong  * Copyright 2010 Red Hat, Inc. and/or its affiliates.
6ff53604bSXiao Guangrong  * Copyright(C) 2015 Intel Corporation.
7ff53604bSXiao Guangrong  *
8ff53604bSXiao Guangrong  * Authors:
9ff53604bSXiao Guangrong  *   Yaniv Kamay  <yaniv@qumranet.com>
10ff53604bSXiao Guangrong  *   Avi Kivity   <avi@qumranet.com>
11ff53604bSXiao Guangrong  *   Marcelo Tosatti <mtosatti@redhat.com>
12ff53604bSXiao Guangrong  *   Paolo Bonzini <pbonzini@redhat.com>
13ff53604bSXiao Guangrong  *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
14ff53604bSXiao Guangrong  *
15ff53604bSXiao Guangrong  * This work is licensed under the terms of the GNU GPL, version 2.  See
16ff53604bSXiao Guangrong  * the COPYING file in the top-level directory.
17ff53604bSXiao Guangrong  */
18ff53604bSXiao Guangrong 
19ff53604bSXiao Guangrong #include <linux/kvm_host.h>
20ff53604bSXiao Guangrong #include <asm/mtrr.h>
21ff53604bSXiao Guangrong 
22ff53604bSXiao Guangrong #include "cpuid.h"
23ff53604bSXiao Guangrong #include "mmu.h"
24ff53604bSXiao Guangrong 
2510fac2dcSXiao Guangrong #define IA32_MTRR_DEF_TYPE_E		(1ULL << 11)
2610fac2dcSXiao Guangrong #define IA32_MTRR_DEF_TYPE_FE		(1ULL << 10)
2710fac2dcSXiao Guangrong #define IA32_MTRR_DEF_TYPE_TYPE_MASK	(0xff)
2810fac2dcSXiao Guangrong 
29ff53604bSXiao Guangrong static bool msr_mtrr_valid(unsigned msr)
30ff53604bSXiao Guangrong {
31ff53604bSXiao Guangrong 	switch (msr) {
32ff53604bSXiao Guangrong 	case 0x200 ... 0x200 + 2 * KVM_NR_VAR_MTRR - 1:
33ff53604bSXiao Guangrong 	case MSR_MTRRfix64K_00000:
34ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_80000:
35ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_A0000:
36ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_C0000:
37ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_C8000:
38ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_D0000:
39ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_D8000:
40ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_E0000:
41ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_E8000:
42ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_F0000:
43ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_F8000:
44ff53604bSXiao Guangrong 	case MSR_MTRRdefType:
45ff53604bSXiao Guangrong 	case MSR_IA32_CR_PAT:
46ff53604bSXiao Guangrong 		return true;
47ff53604bSXiao Guangrong 	case 0x2f8:
48ff53604bSXiao Guangrong 		return true;
49ff53604bSXiao Guangrong 	}
50ff53604bSXiao Guangrong 	return false;
51ff53604bSXiao Guangrong }
52ff53604bSXiao Guangrong 
53ff53604bSXiao Guangrong static bool valid_pat_type(unsigned t)
54ff53604bSXiao Guangrong {
55ff53604bSXiao Guangrong 	return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */
56ff53604bSXiao Guangrong }
57ff53604bSXiao Guangrong 
58ff53604bSXiao Guangrong static bool valid_mtrr_type(unsigned t)
59ff53604bSXiao Guangrong {
60ff53604bSXiao Guangrong 	return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */
61ff53604bSXiao Guangrong }
62ff53604bSXiao Guangrong 
63ff53604bSXiao Guangrong bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
64ff53604bSXiao Guangrong {
65ff53604bSXiao Guangrong 	int i;
66ff53604bSXiao Guangrong 	u64 mask;
67ff53604bSXiao Guangrong 
68ff53604bSXiao Guangrong 	if (!msr_mtrr_valid(msr))
69ff53604bSXiao Guangrong 		return false;
70ff53604bSXiao Guangrong 
71ff53604bSXiao Guangrong 	if (msr == MSR_IA32_CR_PAT) {
72ff53604bSXiao Guangrong 		for (i = 0; i < 8; i++)
73ff53604bSXiao Guangrong 			if (!valid_pat_type((data >> (i * 8)) & 0xff))
74ff53604bSXiao Guangrong 				return false;
75ff53604bSXiao Guangrong 		return true;
76ff53604bSXiao Guangrong 	} else if (msr == MSR_MTRRdefType) {
77ff53604bSXiao Guangrong 		if (data & ~0xcff)
78ff53604bSXiao Guangrong 			return false;
79ff53604bSXiao Guangrong 		return valid_mtrr_type(data & 0xff);
80ff53604bSXiao Guangrong 	} else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) {
81ff53604bSXiao Guangrong 		for (i = 0; i < 8 ; i++)
82ff53604bSXiao Guangrong 			if (!valid_mtrr_type((data >> (i * 8)) & 0xff))
83ff53604bSXiao Guangrong 				return false;
84ff53604bSXiao Guangrong 		return true;
85ff53604bSXiao Guangrong 	}
86ff53604bSXiao Guangrong 
87ff53604bSXiao Guangrong 	/* variable MTRRs */
88ff53604bSXiao Guangrong 	WARN_ON(!(msr >= 0x200 && msr < 0x200 + 2 * KVM_NR_VAR_MTRR));
89ff53604bSXiao Guangrong 
90ff53604bSXiao Guangrong 	mask = (~0ULL) << cpuid_maxphyaddr(vcpu);
91ff53604bSXiao Guangrong 	if ((msr & 1) == 0) {
92ff53604bSXiao Guangrong 		/* MTRR base */
93ff53604bSXiao Guangrong 		if (!valid_mtrr_type(data & 0xff))
94ff53604bSXiao Guangrong 			return false;
95ff53604bSXiao Guangrong 		mask |= 0xf00;
96ff53604bSXiao Guangrong 	} else
97ff53604bSXiao Guangrong 		/* MTRR mask */
98ff53604bSXiao Guangrong 		mask |= 0x7ff;
99ff53604bSXiao Guangrong 	if (data & mask) {
100ff53604bSXiao Guangrong 		kvm_inject_gp(vcpu, 0);
101ff53604bSXiao Guangrong 		return false;
102ff53604bSXiao Guangrong 	}
103ff53604bSXiao Guangrong 
104ff53604bSXiao Guangrong 	return true;
105ff53604bSXiao Guangrong }
106ff53604bSXiao Guangrong EXPORT_SYMBOL_GPL(kvm_mtrr_valid);
107ff53604bSXiao Guangrong 
10810fac2dcSXiao Guangrong static bool mtrr_is_enabled(struct kvm_mtrr *mtrr_state)
10910fac2dcSXiao Guangrong {
11010fac2dcSXiao Guangrong 	return !!(mtrr_state->deftype & IA32_MTRR_DEF_TYPE_E);
11110fac2dcSXiao Guangrong }
11210fac2dcSXiao Guangrong 
11310fac2dcSXiao Guangrong static bool fixed_mtrr_is_enabled(struct kvm_mtrr *mtrr_state)
11410fac2dcSXiao Guangrong {
11510fac2dcSXiao Guangrong 	return !!(mtrr_state->deftype & IA32_MTRR_DEF_TYPE_FE);
11610fac2dcSXiao Guangrong }
11710fac2dcSXiao Guangrong 
11810fac2dcSXiao Guangrong static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state)
11910fac2dcSXiao Guangrong {
12010fac2dcSXiao Guangrong 	return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK;
12110fac2dcSXiao Guangrong }
12210fac2dcSXiao Guangrong 
123ff53604bSXiao Guangrong static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
124ff53604bSXiao Guangrong {
12570109e7dSXiao Guangrong 	struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state;
126ff53604bSXiao Guangrong 	gfn_t start, end, mask;
127ff53604bSXiao Guangrong 	int index;
128ff53604bSXiao Guangrong 	bool is_fixed = true;
129ff53604bSXiao Guangrong 
130ff53604bSXiao Guangrong 	if (msr == MSR_IA32_CR_PAT || !tdp_enabled ||
131ff53604bSXiao Guangrong 	      !kvm_arch_has_noncoherent_dma(vcpu->kvm))
132ff53604bSXiao Guangrong 		return;
133ff53604bSXiao Guangrong 
13410fac2dcSXiao Guangrong 	if (!mtrr_is_enabled(mtrr_state) && msr != MSR_MTRRdefType)
135ff53604bSXiao Guangrong 		return;
136ff53604bSXiao Guangrong 
137ff53604bSXiao Guangrong 	switch (msr) {
138ff53604bSXiao Guangrong 	case MSR_MTRRfix64K_00000:
139ff53604bSXiao Guangrong 		start = 0x0;
140ff53604bSXiao Guangrong 		end = 0x80000;
141ff53604bSXiao Guangrong 		break;
142ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_80000:
143ff53604bSXiao Guangrong 		start = 0x80000;
144ff53604bSXiao Guangrong 		end = 0xa0000;
145ff53604bSXiao Guangrong 		break;
146ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_A0000:
147ff53604bSXiao Guangrong 		start = 0xa0000;
148ff53604bSXiao Guangrong 		end = 0xc0000;
149ff53604bSXiao Guangrong 		break;
150ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000:
151ff53604bSXiao Guangrong 		index = msr - MSR_MTRRfix4K_C0000;
152ff53604bSXiao Guangrong 		start = 0xc0000 + index * (32 << 10);
153ff53604bSXiao Guangrong 		end = start + (32 << 10);
154ff53604bSXiao Guangrong 		break;
155ff53604bSXiao Guangrong 	case MSR_MTRRdefType:
156ff53604bSXiao Guangrong 		is_fixed = false;
157ff53604bSXiao Guangrong 		start = 0x0;
158ff53604bSXiao Guangrong 		end = ~0ULL;
159ff53604bSXiao Guangrong 		break;
160ff53604bSXiao Guangrong 	default:
161ff53604bSXiao Guangrong 		/* variable range MTRRs. */
162ff53604bSXiao Guangrong 		is_fixed = false;
163ff53604bSXiao Guangrong 		index = (msr - 0x200) / 2;
164*86fd5270SXiao Guangrong 		start = mtrr_state->var_ranges[index].base & PAGE_MASK;
165*86fd5270SXiao Guangrong 		mask = mtrr_state->var_ranges[index].mask & PAGE_MASK;
166ff53604bSXiao Guangrong 		mask |= ~0ULL << cpuid_maxphyaddr(vcpu);
167ff53604bSXiao Guangrong 
168ff53604bSXiao Guangrong 		end = ((start & mask) | ~mask) + 1;
169ff53604bSXiao Guangrong 	}
170ff53604bSXiao Guangrong 
17110fac2dcSXiao Guangrong 	if (is_fixed && !fixed_mtrr_is_enabled(mtrr_state))
172ff53604bSXiao Guangrong 		return;
173ff53604bSXiao Guangrong 
174ff53604bSXiao Guangrong 	kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end));
175ff53604bSXiao Guangrong }
176ff53604bSXiao Guangrong 
177ff53604bSXiao Guangrong int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
178ff53604bSXiao Guangrong {
179ff53604bSXiao Guangrong 	u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
180ff53604bSXiao Guangrong 
181ff53604bSXiao Guangrong 	if (!kvm_mtrr_valid(vcpu, msr, data))
182ff53604bSXiao Guangrong 		return 1;
183ff53604bSXiao Guangrong 
18410fac2dcSXiao Guangrong 	if (msr == MSR_MTRRdefType)
18510fac2dcSXiao Guangrong 		vcpu->arch.mtrr_state.deftype = data;
18610fac2dcSXiao Guangrong 	else if (msr == MSR_MTRRfix64K_00000)
187ff53604bSXiao Guangrong 		p[0] = data;
188ff53604bSXiao Guangrong 	else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000)
189ff53604bSXiao Guangrong 		p[1 + msr - MSR_MTRRfix16K_80000] = data;
190ff53604bSXiao Guangrong 	else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000)
191ff53604bSXiao Guangrong 		p[3 + msr - MSR_MTRRfix4K_C0000] = data;
192ff53604bSXiao Guangrong 	else if (msr == MSR_IA32_CR_PAT)
193ff53604bSXiao Guangrong 		vcpu->arch.pat = data;
194ff53604bSXiao Guangrong 	else {	/* Variable MTRRs */
195ff53604bSXiao Guangrong 		int idx, is_mtrr_mask;
196ff53604bSXiao Guangrong 
197ff53604bSXiao Guangrong 		idx = (msr - 0x200) / 2;
198ff53604bSXiao Guangrong 		is_mtrr_mask = msr - 0x200 - 2 * idx;
199ff53604bSXiao Guangrong 		if (!is_mtrr_mask)
200*86fd5270SXiao Guangrong 			vcpu->arch.mtrr_state.var_ranges[idx].base = data;
201ff53604bSXiao Guangrong 		else
202*86fd5270SXiao Guangrong 			vcpu->arch.mtrr_state.var_ranges[idx].mask = data;
203ff53604bSXiao Guangrong 	}
204ff53604bSXiao Guangrong 
205ff53604bSXiao Guangrong 	update_mtrr(vcpu, msr);
206ff53604bSXiao Guangrong 	return 0;
207ff53604bSXiao Guangrong }
208ff53604bSXiao Guangrong 
209ff53604bSXiao Guangrong int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
210ff53604bSXiao Guangrong {
211ff53604bSXiao Guangrong 	u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
212ff53604bSXiao Guangrong 
213eb839917SXiao Guangrong 	/* MSR_MTRRcap is a readonly MSR. */
214eb839917SXiao Guangrong 	if (msr == MSR_MTRRcap) {
215eb839917SXiao Guangrong 		/*
216eb839917SXiao Guangrong 		 * SMRR = 0
217eb839917SXiao Guangrong 		 * WC = 1
218eb839917SXiao Guangrong 		 * FIX = 1
219eb839917SXiao Guangrong 		 * VCNT = KVM_NR_VAR_MTRR
220eb839917SXiao Guangrong 		 */
221eb839917SXiao Guangrong 		*pdata = 0x500 | KVM_NR_VAR_MTRR;
222eb839917SXiao Guangrong 		return 0;
223eb839917SXiao Guangrong 	}
224eb839917SXiao Guangrong 
225ff53604bSXiao Guangrong 	if (!msr_mtrr_valid(msr))
226ff53604bSXiao Guangrong 		return 1;
227ff53604bSXiao Guangrong 
228ff53604bSXiao Guangrong 	if (msr == MSR_MTRRdefType)
22910fac2dcSXiao Guangrong 		*pdata = vcpu->arch.mtrr_state.deftype;
230ff53604bSXiao Guangrong 	else if (msr == MSR_MTRRfix64K_00000)
231ff53604bSXiao Guangrong 		*pdata = p[0];
232ff53604bSXiao Guangrong 	else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000)
233ff53604bSXiao Guangrong 		*pdata = p[1 + msr - MSR_MTRRfix16K_80000];
234ff53604bSXiao Guangrong 	else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000)
235ff53604bSXiao Guangrong 		*pdata = p[3 + msr - MSR_MTRRfix4K_C0000];
236ff53604bSXiao Guangrong 	else if (msr == MSR_IA32_CR_PAT)
237ff53604bSXiao Guangrong 		*pdata = vcpu->arch.pat;
238ff53604bSXiao Guangrong 	else {	/* Variable MTRRs */
239ff53604bSXiao Guangrong 		int idx, is_mtrr_mask;
240ff53604bSXiao Guangrong 
241ff53604bSXiao Guangrong 		idx = (msr - 0x200) / 2;
242ff53604bSXiao Guangrong 		is_mtrr_mask = msr - 0x200 - 2 * idx;
243ff53604bSXiao Guangrong 		if (!is_mtrr_mask)
244*86fd5270SXiao Guangrong 			*pdata = vcpu->arch.mtrr_state.var_ranges[idx].base;
245ff53604bSXiao Guangrong 		else
246*86fd5270SXiao Guangrong 			*pdata = vcpu->arch.mtrr_state.var_ranges[idx].mask;
247ff53604bSXiao Guangrong 	}
248ff53604bSXiao Guangrong 
249ff53604bSXiao Guangrong 	return 0;
250ff53604bSXiao Guangrong }
251ff53604bSXiao Guangrong 
252ff53604bSXiao Guangrong /*
253ff53604bSXiao Guangrong  * The function is based on mtrr_type_lookup() in
254ff53604bSXiao Guangrong  * arch/x86/kernel/cpu/mtrr/generic.c
255ff53604bSXiao Guangrong  */
25670109e7dSXiao Guangrong static int get_mtrr_type(struct kvm_mtrr *mtrr_state,
257ff53604bSXiao Guangrong 			 u64 start, u64 end)
258ff53604bSXiao Guangrong {
259ff53604bSXiao Guangrong 	u64 base, mask;
260ff53604bSXiao Guangrong 	u8 prev_match, curr_match;
261ff53604bSXiao Guangrong 	int i, num_var_ranges = KVM_NR_VAR_MTRR;
262ff53604bSXiao Guangrong 
263ff53604bSXiao Guangrong 	/* MTRR is completely disabled, use UC for all of physical memory. */
26410fac2dcSXiao Guangrong 	if (!mtrr_is_enabled(mtrr_state))
265ff53604bSXiao Guangrong 		return MTRR_TYPE_UNCACHABLE;
266ff53604bSXiao Guangrong 
267ff53604bSXiao Guangrong 	/* Make end inclusive end, instead of exclusive */
268ff53604bSXiao Guangrong 	end--;
269ff53604bSXiao Guangrong 
270ff53604bSXiao Guangrong 	/* Look in fixed ranges. Just return the type as per start */
27110fac2dcSXiao Guangrong 	if (fixed_mtrr_is_enabled(mtrr_state) && (start < 0x100000)) {
272ff53604bSXiao Guangrong 		int idx;
273ff53604bSXiao Guangrong 
274ff53604bSXiao Guangrong 		if (start < 0x80000) {
275ff53604bSXiao Guangrong 			idx = 0;
276ff53604bSXiao Guangrong 			idx += (start >> 16);
277ff53604bSXiao Guangrong 			return mtrr_state->fixed_ranges[idx];
278ff53604bSXiao Guangrong 		} else if (start < 0xC0000) {
279ff53604bSXiao Guangrong 			idx = 1 * 8;
280ff53604bSXiao Guangrong 			idx += ((start - 0x80000) >> 14);
281ff53604bSXiao Guangrong 			return mtrr_state->fixed_ranges[idx];
282ff53604bSXiao Guangrong 		} else if (start < 0x1000000) {
283ff53604bSXiao Guangrong 			idx = 3 * 8;
284ff53604bSXiao Guangrong 			idx += ((start - 0xC0000) >> 12);
285ff53604bSXiao Guangrong 			return mtrr_state->fixed_ranges[idx];
286ff53604bSXiao Guangrong 		}
287ff53604bSXiao Guangrong 	}
288ff53604bSXiao Guangrong 
289ff53604bSXiao Guangrong 	/*
290ff53604bSXiao Guangrong 	 * Look in variable ranges
291ff53604bSXiao Guangrong 	 * Look of multiple ranges matching this address and pick type
292ff53604bSXiao Guangrong 	 * as per MTRR precedence
293ff53604bSXiao Guangrong 	 */
294ff53604bSXiao Guangrong 	prev_match = 0xFF;
295ff53604bSXiao Guangrong 	for (i = 0; i < num_var_ranges; ++i) {
296ff53604bSXiao Guangrong 		unsigned short start_state, end_state;
297ff53604bSXiao Guangrong 
298*86fd5270SXiao Guangrong 		if (!(mtrr_state->var_ranges[i].mask & (1 << 11)))
299ff53604bSXiao Guangrong 			continue;
300ff53604bSXiao Guangrong 
301*86fd5270SXiao Guangrong 		base = mtrr_state->var_ranges[i].base & PAGE_MASK;
302*86fd5270SXiao Guangrong 		mask = mtrr_state->var_ranges[i].mask & PAGE_MASK;
303ff53604bSXiao Guangrong 
304ff53604bSXiao Guangrong 		start_state = ((start & mask) == (base & mask));
305ff53604bSXiao Guangrong 		end_state = ((end & mask) == (base & mask));
306ff53604bSXiao Guangrong 		if (start_state != end_state)
307ff53604bSXiao Guangrong 			return 0xFE;
308ff53604bSXiao Guangrong 
309ff53604bSXiao Guangrong 		if ((start & mask) != (base & mask))
310ff53604bSXiao Guangrong 			continue;
311ff53604bSXiao Guangrong 
312*86fd5270SXiao Guangrong 		curr_match = mtrr_state->var_ranges[i].base & 0xff;
313ff53604bSXiao Guangrong 		if (prev_match == 0xFF) {
314ff53604bSXiao Guangrong 			prev_match = curr_match;
315ff53604bSXiao Guangrong 			continue;
316ff53604bSXiao Guangrong 		}
317ff53604bSXiao Guangrong 
318ff53604bSXiao Guangrong 		if (prev_match == MTRR_TYPE_UNCACHABLE ||
319ff53604bSXiao Guangrong 		    curr_match == MTRR_TYPE_UNCACHABLE)
320ff53604bSXiao Guangrong 			return MTRR_TYPE_UNCACHABLE;
321ff53604bSXiao Guangrong 
322ff53604bSXiao Guangrong 		if ((prev_match == MTRR_TYPE_WRBACK &&
323ff53604bSXiao Guangrong 		     curr_match == MTRR_TYPE_WRTHROUGH) ||
324ff53604bSXiao Guangrong 		    (prev_match == MTRR_TYPE_WRTHROUGH &&
325ff53604bSXiao Guangrong 		     curr_match == MTRR_TYPE_WRBACK)) {
326ff53604bSXiao Guangrong 			prev_match = MTRR_TYPE_WRTHROUGH;
327ff53604bSXiao Guangrong 			curr_match = MTRR_TYPE_WRTHROUGH;
328ff53604bSXiao Guangrong 		}
329ff53604bSXiao Guangrong 
330ff53604bSXiao Guangrong 		if (prev_match != curr_match)
331ff53604bSXiao Guangrong 			return MTRR_TYPE_UNCACHABLE;
332ff53604bSXiao Guangrong 	}
333ff53604bSXiao Guangrong 
334ff53604bSXiao Guangrong 	if (prev_match != 0xFF)
335ff53604bSXiao Guangrong 		return prev_match;
336ff53604bSXiao Guangrong 
33710fac2dcSXiao Guangrong 	return mtrr_default_type(mtrr_state);
338ff53604bSXiao Guangrong }
339ff53604bSXiao Guangrong 
340ff53604bSXiao Guangrong u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
341ff53604bSXiao Guangrong {
342ff53604bSXiao Guangrong 	u8 mtrr;
343ff53604bSXiao Guangrong 
344ff53604bSXiao Guangrong 	mtrr = get_mtrr_type(&vcpu->arch.mtrr_state, gfn << PAGE_SHIFT,
345ff53604bSXiao Guangrong 			     (gfn << PAGE_SHIFT) + PAGE_SIZE);
346ff53604bSXiao Guangrong 	if (mtrr == 0xfe || mtrr == 0xff)
347ff53604bSXiao Guangrong 		mtrr = MTRR_TYPE_WRBACK;
348ff53604bSXiao Guangrong 	return mtrr;
349ff53604bSXiao Guangrong }
350ff53604bSXiao Guangrong EXPORT_SYMBOL_GPL(kvm_mtrr_get_guest_memory_type);
351