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