xref: /openbmc/linux/arch/x86/kvm/mtrr.c (revision 70109e7d9d4ac7182786ddf7cd53bc651a157896)
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 
25ff53604bSXiao Guangrong static bool msr_mtrr_valid(unsigned msr)
26ff53604bSXiao Guangrong {
27ff53604bSXiao Guangrong 	switch (msr) {
28ff53604bSXiao Guangrong 	case 0x200 ... 0x200 + 2 * KVM_NR_VAR_MTRR - 1:
29ff53604bSXiao Guangrong 	case MSR_MTRRfix64K_00000:
30ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_80000:
31ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_A0000:
32ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_C0000:
33ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_C8000:
34ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_D0000:
35ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_D8000:
36ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_E0000:
37ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_E8000:
38ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_F0000:
39ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_F8000:
40ff53604bSXiao Guangrong 	case MSR_MTRRdefType:
41ff53604bSXiao Guangrong 	case MSR_IA32_CR_PAT:
42ff53604bSXiao Guangrong 		return true;
43ff53604bSXiao Guangrong 	case 0x2f8:
44ff53604bSXiao Guangrong 		return true;
45ff53604bSXiao Guangrong 	}
46ff53604bSXiao Guangrong 	return false;
47ff53604bSXiao Guangrong }
48ff53604bSXiao Guangrong 
49ff53604bSXiao Guangrong static bool valid_pat_type(unsigned t)
50ff53604bSXiao Guangrong {
51ff53604bSXiao Guangrong 	return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */
52ff53604bSXiao Guangrong }
53ff53604bSXiao Guangrong 
54ff53604bSXiao Guangrong static bool valid_mtrr_type(unsigned t)
55ff53604bSXiao Guangrong {
56ff53604bSXiao Guangrong 	return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */
57ff53604bSXiao Guangrong }
58ff53604bSXiao Guangrong 
59ff53604bSXiao Guangrong bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
60ff53604bSXiao Guangrong {
61ff53604bSXiao Guangrong 	int i;
62ff53604bSXiao Guangrong 	u64 mask;
63ff53604bSXiao Guangrong 
64ff53604bSXiao Guangrong 	if (!msr_mtrr_valid(msr))
65ff53604bSXiao Guangrong 		return false;
66ff53604bSXiao Guangrong 
67ff53604bSXiao Guangrong 	if (msr == MSR_IA32_CR_PAT) {
68ff53604bSXiao Guangrong 		for (i = 0; i < 8; i++)
69ff53604bSXiao Guangrong 			if (!valid_pat_type((data >> (i * 8)) & 0xff))
70ff53604bSXiao Guangrong 				return false;
71ff53604bSXiao Guangrong 		return true;
72ff53604bSXiao Guangrong 	} else if (msr == MSR_MTRRdefType) {
73ff53604bSXiao Guangrong 		if (data & ~0xcff)
74ff53604bSXiao Guangrong 			return false;
75ff53604bSXiao Guangrong 		return valid_mtrr_type(data & 0xff);
76ff53604bSXiao Guangrong 	} else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) {
77ff53604bSXiao Guangrong 		for (i = 0; i < 8 ; i++)
78ff53604bSXiao Guangrong 			if (!valid_mtrr_type((data >> (i * 8)) & 0xff))
79ff53604bSXiao Guangrong 				return false;
80ff53604bSXiao Guangrong 		return true;
81ff53604bSXiao Guangrong 	}
82ff53604bSXiao Guangrong 
83ff53604bSXiao Guangrong 	/* variable MTRRs */
84ff53604bSXiao Guangrong 	WARN_ON(!(msr >= 0x200 && msr < 0x200 + 2 * KVM_NR_VAR_MTRR));
85ff53604bSXiao Guangrong 
86ff53604bSXiao Guangrong 	mask = (~0ULL) << cpuid_maxphyaddr(vcpu);
87ff53604bSXiao Guangrong 	if ((msr & 1) == 0) {
88ff53604bSXiao Guangrong 		/* MTRR base */
89ff53604bSXiao Guangrong 		if (!valid_mtrr_type(data & 0xff))
90ff53604bSXiao Guangrong 			return false;
91ff53604bSXiao Guangrong 		mask |= 0xf00;
92ff53604bSXiao Guangrong 	} else
93ff53604bSXiao Guangrong 		/* MTRR mask */
94ff53604bSXiao Guangrong 		mask |= 0x7ff;
95ff53604bSXiao Guangrong 	if (data & mask) {
96ff53604bSXiao Guangrong 		kvm_inject_gp(vcpu, 0);
97ff53604bSXiao Guangrong 		return false;
98ff53604bSXiao Guangrong 	}
99ff53604bSXiao Guangrong 
100ff53604bSXiao Guangrong 	return true;
101ff53604bSXiao Guangrong }
102ff53604bSXiao Guangrong EXPORT_SYMBOL_GPL(kvm_mtrr_valid);
103ff53604bSXiao Guangrong 
104ff53604bSXiao Guangrong static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
105ff53604bSXiao Guangrong {
106*70109e7dSXiao Guangrong 	struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state;
107ff53604bSXiao Guangrong 	unsigned char mtrr_enabled = mtrr_state->enabled;
108ff53604bSXiao Guangrong 	gfn_t start, end, mask;
109ff53604bSXiao Guangrong 	int index;
110ff53604bSXiao Guangrong 	bool is_fixed = true;
111ff53604bSXiao Guangrong 
112ff53604bSXiao Guangrong 	if (msr == MSR_IA32_CR_PAT || !tdp_enabled ||
113ff53604bSXiao Guangrong 	      !kvm_arch_has_noncoherent_dma(vcpu->kvm))
114ff53604bSXiao Guangrong 		return;
115ff53604bSXiao Guangrong 
116ff53604bSXiao Guangrong 	if (!(mtrr_enabled & 0x2) && msr != MSR_MTRRdefType)
117ff53604bSXiao Guangrong 		return;
118ff53604bSXiao Guangrong 
119ff53604bSXiao Guangrong 	switch (msr) {
120ff53604bSXiao Guangrong 	case MSR_MTRRfix64K_00000:
121ff53604bSXiao Guangrong 		start = 0x0;
122ff53604bSXiao Guangrong 		end = 0x80000;
123ff53604bSXiao Guangrong 		break;
124ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_80000:
125ff53604bSXiao Guangrong 		start = 0x80000;
126ff53604bSXiao Guangrong 		end = 0xa0000;
127ff53604bSXiao Guangrong 		break;
128ff53604bSXiao Guangrong 	case MSR_MTRRfix16K_A0000:
129ff53604bSXiao Guangrong 		start = 0xa0000;
130ff53604bSXiao Guangrong 		end = 0xc0000;
131ff53604bSXiao Guangrong 		break;
132ff53604bSXiao Guangrong 	case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000:
133ff53604bSXiao Guangrong 		index = msr - MSR_MTRRfix4K_C0000;
134ff53604bSXiao Guangrong 		start = 0xc0000 + index * (32 << 10);
135ff53604bSXiao Guangrong 		end = start + (32 << 10);
136ff53604bSXiao Guangrong 		break;
137ff53604bSXiao Guangrong 	case MSR_MTRRdefType:
138ff53604bSXiao Guangrong 		is_fixed = false;
139ff53604bSXiao Guangrong 		start = 0x0;
140ff53604bSXiao Guangrong 		end = ~0ULL;
141ff53604bSXiao Guangrong 		break;
142ff53604bSXiao Guangrong 	default:
143ff53604bSXiao Guangrong 		/* variable range MTRRs. */
144ff53604bSXiao Guangrong 		is_fixed = false;
145ff53604bSXiao Guangrong 		index = (msr - 0x200) / 2;
146ff53604bSXiao Guangrong 		start = (((u64)mtrr_state->var_ranges[index].base_hi) << 32) +
147ff53604bSXiao Guangrong 		       (mtrr_state->var_ranges[index].base_lo & PAGE_MASK);
148ff53604bSXiao Guangrong 		mask = (((u64)mtrr_state->var_ranges[index].mask_hi) << 32) +
149ff53604bSXiao Guangrong 		       (mtrr_state->var_ranges[index].mask_lo & PAGE_MASK);
150ff53604bSXiao Guangrong 		mask |= ~0ULL << cpuid_maxphyaddr(vcpu);
151ff53604bSXiao Guangrong 
152ff53604bSXiao Guangrong 		end = ((start & mask) | ~mask) + 1;
153ff53604bSXiao Guangrong 	}
154ff53604bSXiao Guangrong 
155ff53604bSXiao Guangrong 	if (is_fixed && !(mtrr_enabled & 0x1))
156ff53604bSXiao Guangrong 		return;
157ff53604bSXiao Guangrong 
158ff53604bSXiao Guangrong 	kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end));
159ff53604bSXiao Guangrong }
160ff53604bSXiao Guangrong 
161ff53604bSXiao Guangrong int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
162ff53604bSXiao Guangrong {
163ff53604bSXiao Guangrong 	u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
164ff53604bSXiao Guangrong 
165ff53604bSXiao Guangrong 	if (!kvm_mtrr_valid(vcpu, msr, data))
166ff53604bSXiao Guangrong 		return 1;
167ff53604bSXiao Guangrong 
168ff53604bSXiao Guangrong 	if (msr == MSR_MTRRdefType) {
169ff53604bSXiao Guangrong 		vcpu->arch.mtrr_state.def_type = data;
170ff53604bSXiao Guangrong 		vcpu->arch.mtrr_state.enabled = (data & 0xc00) >> 10;
171ff53604bSXiao Guangrong 	} else if (msr == MSR_MTRRfix64K_00000)
172ff53604bSXiao Guangrong 		p[0] = data;
173ff53604bSXiao Guangrong 	else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000)
174ff53604bSXiao Guangrong 		p[1 + msr - MSR_MTRRfix16K_80000] = data;
175ff53604bSXiao Guangrong 	else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000)
176ff53604bSXiao Guangrong 		p[3 + msr - MSR_MTRRfix4K_C0000] = data;
177ff53604bSXiao Guangrong 	else if (msr == MSR_IA32_CR_PAT)
178ff53604bSXiao Guangrong 		vcpu->arch.pat = data;
179ff53604bSXiao Guangrong 	else {	/* Variable MTRRs */
180ff53604bSXiao Guangrong 		int idx, is_mtrr_mask;
181ff53604bSXiao Guangrong 		u64 *pt;
182ff53604bSXiao Guangrong 
183ff53604bSXiao Guangrong 		idx = (msr - 0x200) / 2;
184ff53604bSXiao Guangrong 		is_mtrr_mask = msr - 0x200 - 2 * idx;
185ff53604bSXiao Guangrong 		if (!is_mtrr_mask)
186ff53604bSXiao Guangrong 			pt =
187ff53604bSXiao Guangrong 			  (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].base_lo;
188ff53604bSXiao Guangrong 		else
189ff53604bSXiao Guangrong 			pt =
190ff53604bSXiao Guangrong 			  (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].mask_lo;
191ff53604bSXiao Guangrong 		*pt = data;
192ff53604bSXiao Guangrong 	}
193ff53604bSXiao Guangrong 
194ff53604bSXiao Guangrong 	update_mtrr(vcpu, msr);
195ff53604bSXiao Guangrong 	return 0;
196ff53604bSXiao Guangrong }
197ff53604bSXiao Guangrong 
198ff53604bSXiao Guangrong int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
199ff53604bSXiao Guangrong {
200ff53604bSXiao Guangrong 	u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
201ff53604bSXiao Guangrong 
202eb839917SXiao Guangrong 	/* MSR_MTRRcap is a readonly MSR. */
203eb839917SXiao Guangrong 	if (msr == MSR_MTRRcap) {
204eb839917SXiao Guangrong 		/*
205eb839917SXiao Guangrong 		 * SMRR = 0
206eb839917SXiao Guangrong 		 * WC = 1
207eb839917SXiao Guangrong 		 * FIX = 1
208eb839917SXiao Guangrong 		 * VCNT = KVM_NR_VAR_MTRR
209eb839917SXiao Guangrong 		 */
210eb839917SXiao Guangrong 		*pdata = 0x500 | KVM_NR_VAR_MTRR;
211eb839917SXiao Guangrong 		return 0;
212eb839917SXiao Guangrong 	}
213eb839917SXiao Guangrong 
214ff53604bSXiao Guangrong 	if (!msr_mtrr_valid(msr))
215ff53604bSXiao Guangrong 		return 1;
216ff53604bSXiao Guangrong 
217ff53604bSXiao Guangrong 	if (msr == MSR_MTRRdefType)
218ff53604bSXiao Guangrong 		*pdata = vcpu->arch.mtrr_state.def_type +
219ff53604bSXiao Guangrong 			 (vcpu->arch.mtrr_state.enabled << 10);
220ff53604bSXiao Guangrong 	else if (msr == MSR_MTRRfix64K_00000)
221ff53604bSXiao Guangrong 		*pdata = p[0];
222ff53604bSXiao Guangrong 	else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000)
223ff53604bSXiao Guangrong 		*pdata = p[1 + msr - MSR_MTRRfix16K_80000];
224ff53604bSXiao Guangrong 	else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000)
225ff53604bSXiao Guangrong 		*pdata = p[3 + msr - MSR_MTRRfix4K_C0000];
226ff53604bSXiao Guangrong 	else if (msr == MSR_IA32_CR_PAT)
227ff53604bSXiao Guangrong 		*pdata = vcpu->arch.pat;
228ff53604bSXiao Guangrong 	else {	/* Variable MTRRs */
229ff53604bSXiao Guangrong 		int idx, is_mtrr_mask;
230ff53604bSXiao Guangrong 		u64 *pt;
231ff53604bSXiao Guangrong 
232ff53604bSXiao Guangrong 		idx = (msr - 0x200) / 2;
233ff53604bSXiao Guangrong 		is_mtrr_mask = msr - 0x200 - 2 * idx;
234ff53604bSXiao Guangrong 		if (!is_mtrr_mask)
235ff53604bSXiao Guangrong 			pt =
236ff53604bSXiao Guangrong 			  (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].base_lo;
237ff53604bSXiao Guangrong 		else
238ff53604bSXiao Guangrong 			pt =
239ff53604bSXiao Guangrong 			  (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].mask_lo;
240ff53604bSXiao Guangrong 		*pdata = *pt;
241ff53604bSXiao Guangrong 	}
242ff53604bSXiao Guangrong 
243ff53604bSXiao Guangrong 	return 0;
244ff53604bSXiao Guangrong }
245ff53604bSXiao Guangrong 
246ff53604bSXiao Guangrong /*
247ff53604bSXiao Guangrong  * The function is based on mtrr_type_lookup() in
248ff53604bSXiao Guangrong  * arch/x86/kernel/cpu/mtrr/generic.c
249ff53604bSXiao Guangrong  */
250*70109e7dSXiao Guangrong static int get_mtrr_type(struct kvm_mtrr *mtrr_state,
251ff53604bSXiao Guangrong 			 u64 start, u64 end)
252ff53604bSXiao Guangrong {
253ff53604bSXiao Guangrong 	u64 base, mask;
254ff53604bSXiao Guangrong 	u8 prev_match, curr_match;
255ff53604bSXiao Guangrong 	int i, num_var_ranges = KVM_NR_VAR_MTRR;
256ff53604bSXiao Guangrong 
257ff53604bSXiao Guangrong 	/* MTRR is completely disabled, use UC for all of physical memory. */
258ff53604bSXiao Guangrong 	if (!(mtrr_state->enabled & 0x2))
259ff53604bSXiao Guangrong 		return MTRR_TYPE_UNCACHABLE;
260ff53604bSXiao Guangrong 
261ff53604bSXiao Guangrong 	/* Make end inclusive end, instead of exclusive */
262ff53604bSXiao Guangrong 	end--;
263ff53604bSXiao Guangrong 
264ff53604bSXiao Guangrong 	/* Look in fixed ranges. Just return the type as per start */
265*70109e7dSXiao Guangrong 	if ((mtrr_state->enabled & 0x1) && (start < 0x100000)) {
266ff53604bSXiao Guangrong 		int idx;
267ff53604bSXiao Guangrong 
268ff53604bSXiao Guangrong 		if (start < 0x80000) {
269ff53604bSXiao Guangrong 			idx = 0;
270ff53604bSXiao Guangrong 			idx += (start >> 16);
271ff53604bSXiao Guangrong 			return mtrr_state->fixed_ranges[idx];
272ff53604bSXiao Guangrong 		} else if (start < 0xC0000) {
273ff53604bSXiao Guangrong 			idx = 1 * 8;
274ff53604bSXiao Guangrong 			idx += ((start - 0x80000) >> 14);
275ff53604bSXiao Guangrong 			return mtrr_state->fixed_ranges[idx];
276ff53604bSXiao Guangrong 		} else if (start < 0x1000000) {
277ff53604bSXiao Guangrong 			idx = 3 * 8;
278ff53604bSXiao Guangrong 			idx += ((start - 0xC0000) >> 12);
279ff53604bSXiao Guangrong 			return mtrr_state->fixed_ranges[idx];
280ff53604bSXiao Guangrong 		}
281ff53604bSXiao Guangrong 	}
282ff53604bSXiao Guangrong 
283ff53604bSXiao Guangrong 	/*
284ff53604bSXiao Guangrong 	 * Look in variable ranges
285ff53604bSXiao Guangrong 	 * Look of multiple ranges matching this address and pick type
286ff53604bSXiao Guangrong 	 * as per MTRR precedence
287ff53604bSXiao Guangrong 	 */
288ff53604bSXiao Guangrong 	prev_match = 0xFF;
289ff53604bSXiao Guangrong 	for (i = 0; i < num_var_ranges; ++i) {
290ff53604bSXiao Guangrong 		unsigned short start_state, end_state;
291ff53604bSXiao Guangrong 
292ff53604bSXiao Guangrong 		if (!(mtrr_state->var_ranges[i].mask_lo & (1 << 11)))
293ff53604bSXiao Guangrong 			continue;
294ff53604bSXiao Guangrong 
295ff53604bSXiao Guangrong 		base = (((u64)mtrr_state->var_ranges[i].base_hi) << 32) +
296ff53604bSXiao Guangrong 		       (mtrr_state->var_ranges[i].base_lo & PAGE_MASK);
297ff53604bSXiao Guangrong 		mask = (((u64)mtrr_state->var_ranges[i].mask_hi) << 32) +
298ff53604bSXiao Guangrong 		       (mtrr_state->var_ranges[i].mask_lo & PAGE_MASK);
299ff53604bSXiao Guangrong 
300ff53604bSXiao Guangrong 		start_state = ((start & mask) == (base & mask));
301ff53604bSXiao Guangrong 		end_state = ((end & mask) == (base & mask));
302ff53604bSXiao Guangrong 		if (start_state != end_state)
303ff53604bSXiao Guangrong 			return 0xFE;
304ff53604bSXiao Guangrong 
305ff53604bSXiao Guangrong 		if ((start & mask) != (base & mask))
306ff53604bSXiao Guangrong 			continue;
307ff53604bSXiao Guangrong 
308ff53604bSXiao Guangrong 		curr_match = mtrr_state->var_ranges[i].base_lo & 0xff;
309ff53604bSXiao Guangrong 		if (prev_match == 0xFF) {
310ff53604bSXiao Guangrong 			prev_match = curr_match;
311ff53604bSXiao Guangrong 			continue;
312ff53604bSXiao Guangrong 		}
313ff53604bSXiao Guangrong 
314ff53604bSXiao Guangrong 		if (prev_match == MTRR_TYPE_UNCACHABLE ||
315ff53604bSXiao Guangrong 		    curr_match == MTRR_TYPE_UNCACHABLE)
316ff53604bSXiao Guangrong 			return MTRR_TYPE_UNCACHABLE;
317ff53604bSXiao Guangrong 
318ff53604bSXiao Guangrong 		if ((prev_match == MTRR_TYPE_WRBACK &&
319ff53604bSXiao Guangrong 		     curr_match == MTRR_TYPE_WRTHROUGH) ||
320ff53604bSXiao Guangrong 		    (prev_match == MTRR_TYPE_WRTHROUGH &&
321ff53604bSXiao Guangrong 		     curr_match == MTRR_TYPE_WRBACK)) {
322ff53604bSXiao Guangrong 			prev_match = MTRR_TYPE_WRTHROUGH;
323ff53604bSXiao Guangrong 			curr_match = MTRR_TYPE_WRTHROUGH;
324ff53604bSXiao Guangrong 		}
325ff53604bSXiao Guangrong 
326ff53604bSXiao Guangrong 		if (prev_match != curr_match)
327ff53604bSXiao Guangrong 			return MTRR_TYPE_UNCACHABLE;
328ff53604bSXiao Guangrong 	}
329ff53604bSXiao Guangrong 
330ff53604bSXiao Guangrong 	if (prev_match != 0xFF)
331ff53604bSXiao Guangrong 		return prev_match;
332ff53604bSXiao Guangrong 
333ff53604bSXiao Guangrong 	return mtrr_state->def_type;
334ff53604bSXiao Guangrong }
335ff53604bSXiao Guangrong 
336ff53604bSXiao Guangrong u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
337ff53604bSXiao Guangrong {
338ff53604bSXiao Guangrong 	u8 mtrr;
339ff53604bSXiao Guangrong 
340ff53604bSXiao Guangrong 	mtrr = get_mtrr_type(&vcpu->arch.mtrr_state, gfn << PAGE_SHIFT,
341ff53604bSXiao Guangrong 			     (gfn << PAGE_SHIFT) + PAGE_SIZE);
342ff53604bSXiao Guangrong 	if (mtrr == 0xfe || mtrr == 0xff)
343ff53604bSXiao Guangrong 		mtrr = MTRR_TYPE_WRBACK;
344ff53604bSXiao Guangrong 	return mtrr;
345ff53604bSXiao Guangrong }
346ff53604bSXiao Guangrong EXPORT_SYMBOL_GPL(kvm_mtrr_get_guest_memory_type);
347