xref: /OK3568_Linux_fs/kernel/arch/powerpc/kvm/e500_mmu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. All rights reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Yu Liu, yu.liu@freescale.com
6*4882a593Smuzhiyun  *         Scott Wood, scottwood@freescale.com
7*4882a593Smuzhiyun  *         Ashish Kalra, ashish.kalra@freescale.com
8*4882a593Smuzhiyun  *         Varun Sethi, varun.sethi@freescale.com
9*4882a593Smuzhiyun  *         Alexander Graf, agraf@suse.de
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * Description:
12*4882a593Smuzhiyun  * This file is based on arch/powerpc/kvm/44x_tlb.c,
13*4882a593Smuzhiyun  * by Hollis Blanchard <hollisb@us.ibm.com>.
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun #include <linux/types.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <linux/string.h>
20*4882a593Smuzhiyun #include <linux/kvm.h>
21*4882a593Smuzhiyun #include <linux/kvm_host.h>
22*4882a593Smuzhiyun #include <linux/highmem.h>
23*4882a593Smuzhiyun #include <linux/log2.h>
24*4882a593Smuzhiyun #include <linux/uaccess.h>
25*4882a593Smuzhiyun #include <linux/sched.h>
26*4882a593Smuzhiyun #include <linux/rwsem.h>
27*4882a593Smuzhiyun #include <linux/vmalloc.h>
28*4882a593Smuzhiyun #include <linux/hugetlb.h>
29*4882a593Smuzhiyun #include <asm/kvm_ppc.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include "e500.h"
32*4882a593Smuzhiyun #include "trace_booke.h"
33*4882a593Smuzhiyun #include "timing.h"
34*4882a593Smuzhiyun #include "e500_mmu_host.h"
35*4882a593Smuzhiyun 
gtlb0_get_next_victim(struct kvmppc_vcpu_e500 * vcpu_e500)36*4882a593Smuzhiyun static inline unsigned int gtlb0_get_next_victim(
37*4882a593Smuzhiyun 		struct kvmppc_vcpu_e500 *vcpu_e500)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	unsigned int victim;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	victim = vcpu_e500->gtlb_nv[0]++;
42*4882a593Smuzhiyun 	if (unlikely(vcpu_e500->gtlb_nv[0] >= vcpu_e500->gtlb_params[0].ways))
43*4882a593Smuzhiyun 		vcpu_e500->gtlb_nv[0] = 0;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	return victim;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
tlb0_set_base(gva_t addr,int sets,int ways)48*4882a593Smuzhiyun static int tlb0_set_base(gva_t addr, int sets, int ways)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	int set_base;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	set_base = (addr >> PAGE_SHIFT) & (sets - 1);
53*4882a593Smuzhiyun 	set_base *= ways;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	return set_base;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
gtlb0_set_base(struct kvmppc_vcpu_e500 * vcpu_e500,gva_t addr)58*4882a593Smuzhiyun static int gtlb0_set_base(struct kvmppc_vcpu_e500 *vcpu_e500, gva_t addr)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	return tlb0_set_base(addr, vcpu_e500->gtlb_params[0].sets,
61*4882a593Smuzhiyun 			     vcpu_e500->gtlb_params[0].ways);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
get_tlb_esel(struct kvm_vcpu * vcpu,int tlbsel)64*4882a593Smuzhiyun static unsigned int get_tlb_esel(struct kvm_vcpu *vcpu, int tlbsel)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
67*4882a593Smuzhiyun 	int esel = get_tlb_esel_bit(vcpu);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	if (tlbsel == 0) {
70*4882a593Smuzhiyun 		esel &= vcpu_e500->gtlb_params[0].ways - 1;
71*4882a593Smuzhiyun 		esel += gtlb0_set_base(vcpu_e500, vcpu->arch.shared->mas2);
72*4882a593Smuzhiyun 	} else {
73*4882a593Smuzhiyun 		esel &= vcpu_e500->gtlb_params[tlbsel].entries - 1;
74*4882a593Smuzhiyun 	}
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return esel;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /* Search the guest TLB for a matching entry. */
kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 * vcpu_e500,gva_t eaddr,int tlbsel,unsigned int pid,int as)80*4882a593Smuzhiyun static int kvmppc_e500_tlb_index(struct kvmppc_vcpu_e500 *vcpu_e500,
81*4882a593Smuzhiyun 		gva_t eaddr, int tlbsel, unsigned int pid, int as)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	int size = vcpu_e500->gtlb_params[tlbsel].entries;
84*4882a593Smuzhiyun 	unsigned int set_base, offset;
85*4882a593Smuzhiyun 	int i;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (tlbsel == 0) {
88*4882a593Smuzhiyun 		set_base = gtlb0_set_base(vcpu_e500, eaddr);
89*4882a593Smuzhiyun 		size = vcpu_e500->gtlb_params[0].ways;
90*4882a593Smuzhiyun 	} else {
91*4882a593Smuzhiyun 		if (eaddr < vcpu_e500->tlb1_min_eaddr ||
92*4882a593Smuzhiyun 				eaddr > vcpu_e500->tlb1_max_eaddr)
93*4882a593Smuzhiyun 			return -1;
94*4882a593Smuzhiyun 		set_base = 0;
95*4882a593Smuzhiyun 	}
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	offset = vcpu_e500->gtlb_offset[tlbsel];
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	for (i = 0; i < size; i++) {
100*4882a593Smuzhiyun 		struct kvm_book3e_206_tlb_entry *tlbe =
101*4882a593Smuzhiyun 			&vcpu_e500->gtlb_arch[offset + set_base + i];
102*4882a593Smuzhiyun 		unsigned int tid;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 		if (eaddr < get_tlb_eaddr(tlbe))
105*4882a593Smuzhiyun 			continue;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 		if (eaddr > get_tlb_end(tlbe))
108*4882a593Smuzhiyun 			continue;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 		tid = get_tlb_tid(tlbe);
111*4882a593Smuzhiyun 		if (tid && (tid != pid))
112*4882a593Smuzhiyun 			continue;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 		if (!get_tlb_v(tlbe))
115*4882a593Smuzhiyun 			continue;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 		if (get_tlb_ts(tlbe) != as && as != -1)
118*4882a593Smuzhiyun 			continue;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 		return set_base + i;
121*4882a593Smuzhiyun 	}
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	return -1;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu * vcpu,gva_t eaddr,int as)126*4882a593Smuzhiyun static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
127*4882a593Smuzhiyun 		gva_t eaddr, int as)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
130*4882a593Smuzhiyun 	unsigned int victim, tsized;
131*4882a593Smuzhiyun 	int tlbsel;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	/* since we only have two TLBs, only lower bit is used. */
134*4882a593Smuzhiyun 	tlbsel = (vcpu->arch.shared->mas4 >> 28) & 0x1;
135*4882a593Smuzhiyun 	victim = (tlbsel == 0) ? gtlb0_get_next_victim(vcpu_e500) : 0;
136*4882a593Smuzhiyun 	tsized = (vcpu->arch.shared->mas4 >> 7) & 0x1f;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(victim)
139*4882a593Smuzhiyun 		| MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
140*4882a593Smuzhiyun 	vcpu->arch.shared->mas1 = MAS1_VALID | (as ? MAS1_TS : 0)
141*4882a593Smuzhiyun 		| MAS1_TID(get_tlbmiss_tid(vcpu))
142*4882a593Smuzhiyun 		| MAS1_TSIZE(tsized);
143*4882a593Smuzhiyun 	vcpu->arch.shared->mas2 = (eaddr & MAS2_EPN)
144*4882a593Smuzhiyun 		| (vcpu->arch.shared->mas4 & MAS2_ATTRIB_MASK);
145*4882a593Smuzhiyun 	vcpu->arch.shared->mas7_3 &= MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3;
146*4882a593Smuzhiyun 	vcpu->arch.shared->mas6 = (vcpu->arch.shared->mas6 & MAS6_SPID1)
147*4882a593Smuzhiyun 		| (get_cur_pid(vcpu) << 16)
148*4882a593Smuzhiyun 		| (as ? MAS6_SAS : 0);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
kvmppc_recalc_tlb1map_range(struct kvmppc_vcpu_e500 * vcpu_e500)151*4882a593Smuzhiyun static void kvmppc_recalc_tlb1map_range(struct kvmppc_vcpu_e500 *vcpu_e500)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	int size = vcpu_e500->gtlb_params[1].entries;
154*4882a593Smuzhiyun 	unsigned int offset;
155*4882a593Smuzhiyun 	gva_t eaddr;
156*4882a593Smuzhiyun 	int i;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	vcpu_e500->tlb1_min_eaddr = ~0UL;
159*4882a593Smuzhiyun 	vcpu_e500->tlb1_max_eaddr = 0;
160*4882a593Smuzhiyun 	offset = vcpu_e500->gtlb_offset[1];
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	for (i = 0; i < size; i++) {
163*4882a593Smuzhiyun 		struct kvm_book3e_206_tlb_entry *tlbe =
164*4882a593Smuzhiyun 			&vcpu_e500->gtlb_arch[offset + i];
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 		if (!get_tlb_v(tlbe))
167*4882a593Smuzhiyun 			continue;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 		eaddr = get_tlb_eaddr(tlbe);
170*4882a593Smuzhiyun 		vcpu_e500->tlb1_min_eaddr =
171*4882a593Smuzhiyun 				min(vcpu_e500->tlb1_min_eaddr, eaddr);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 		eaddr = get_tlb_end(tlbe);
174*4882a593Smuzhiyun 		vcpu_e500->tlb1_max_eaddr =
175*4882a593Smuzhiyun 				max(vcpu_e500->tlb1_max_eaddr, eaddr);
176*4882a593Smuzhiyun 	}
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun 
kvmppc_need_recalc_tlb1map_range(struct kvmppc_vcpu_e500 * vcpu_e500,struct kvm_book3e_206_tlb_entry * gtlbe)179*4882a593Smuzhiyun static int kvmppc_need_recalc_tlb1map_range(struct kvmppc_vcpu_e500 *vcpu_e500,
180*4882a593Smuzhiyun 				struct kvm_book3e_206_tlb_entry *gtlbe)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	unsigned long start, end, size;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	size = get_tlb_bytes(gtlbe);
185*4882a593Smuzhiyun 	start = get_tlb_eaddr(gtlbe) & ~(size - 1);
186*4882a593Smuzhiyun 	end = start + size - 1;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	return vcpu_e500->tlb1_min_eaddr == start ||
189*4882a593Smuzhiyun 			vcpu_e500->tlb1_max_eaddr == end;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun /* This function is supposed to be called for a adding a new valid tlb entry */
kvmppc_set_tlb1map_range(struct kvm_vcpu * vcpu,struct kvm_book3e_206_tlb_entry * gtlbe)193*4882a593Smuzhiyun static void kvmppc_set_tlb1map_range(struct kvm_vcpu *vcpu,
194*4882a593Smuzhiyun 				struct kvm_book3e_206_tlb_entry *gtlbe)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun 	unsigned long start, end, size;
197*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	if (!get_tlb_v(gtlbe))
200*4882a593Smuzhiyun 		return;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	size = get_tlb_bytes(gtlbe);
203*4882a593Smuzhiyun 	start = get_tlb_eaddr(gtlbe) & ~(size - 1);
204*4882a593Smuzhiyun 	end = start + size - 1;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	vcpu_e500->tlb1_min_eaddr = min(vcpu_e500->tlb1_min_eaddr, start);
207*4882a593Smuzhiyun 	vcpu_e500->tlb1_max_eaddr = max(vcpu_e500->tlb1_max_eaddr, end);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
kvmppc_e500_gtlbe_invalidate(struct kvmppc_vcpu_e500 * vcpu_e500,int tlbsel,int esel)210*4882a593Smuzhiyun static inline int kvmppc_e500_gtlbe_invalidate(
211*4882a593Smuzhiyun 				struct kvmppc_vcpu_e500 *vcpu_e500,
212*4882a593Smuzhiyun 				int tlbsel, int esel)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct kvm_book3e_206_tlb_entry *gtlbe =
215*4882a593Smuzhiyun 		get_entry(vcpu_e500, tlbsel, esel);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	if (unlikely(get_tlb_iprot(gtlbe)))
218*4882a593Smuzhiyun 		return -1;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	if (tlbsel == 1 && kvmppc_need_recalc_tlb1map_range(vcpu_e500, gtlbe))
221*4882a593Smuzhiyun 		kvmppc_recalc_tlb1map_range(vcpu_e500);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	gtlbe->mas1 = 0;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	return 0;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 * vcpu_e500,ulong value)228*4882a593Smuzhiyun int kvmppc_e500_emul_mt_mmucsr0(struct kvmppc_vcpu_e500 *vcpu_e500, ulong value)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	int esel;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	if (value & MMUCSR0_TLB0FI)
233*4882a593Smuzhiyun 		for (esel = 0; esel < vcpu_e500->gtlb_params[0].entries; esel++)
234*4882a593Smuzhiyun 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, 0, esel);
235*4882a593Smuzhiyun 	if (value & MMUCSR0_TLB1FI)
236*4882a593Smuzhiyun 		for (esel = 0; esel < vcpu_e500->gtlb_params[1].entries; esel++)
237*4882a593Smuzhiyun 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, 1, esel);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/* Invalidate all host shadow mappings */
240*4882a593Smuzhiyun 	kvmppc_core_flush_tlb(&vcpu_e500->vcpu);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	return EMULATE_DONE;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
kvmppc_e500_emul_tlbivax(struct kvm_vcpu * vcpu,gva_t ea)245*4882a593Smuzhiyun int kvmppc_e500_emul_tlbivax(struct kvm_vcpu *vcpu, gva_t ea)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
248*4882a593Smuzhiyun 	unsigned int ia;
249*4882a593Smuzhiyun 	int esel, tlbsel;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	ia = (ea >> 2) & 0x1;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	/* since we only have two TLBs, only lower bit is used. */
254*4882a593Smuzhiyun 	tlbsel = (ea >> 3) & 0x1;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (ia) {
257*4882a593Smuzhiyun 		/* invalidate all entries */
258*4882a593Smuzhiyun 		for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries;
259*4882a593Smuzhiyun 		     esel++)
260*4882a593Smuzhiyun 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
261*4882a593Smuzhiyun 	} else {
262*4882a593Smuzhiyun 		ea &= 0xfffff000;
263*4882a593Smuzhiyun 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel,
264*4882a593Smuzhiyun 				get_cur_pid(vcpu), -1);
265*4882a593Smuzhiyun 		if (esel >= 0)
266*4882a593Smuzhiyun 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	/* Invalidate all host shadow mappings */
270*4882a593Smuzhiyun 	kvmppc_core_flush_tlb(&vcpu_e500->vcpu);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	return EMULATE_DONE;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
tlbilx_all(struct kvmppc_vcpu_e500 * vcpu_e500,int tlbsel,int pid,int type)275*4882a593Smuzhiyun static void tlbilx_all(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
276*4882a593Smuzhiyun 		       int pid, int type)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	struct kvm_book3e_206_tlb_entry *tlbe;
279*4882a593Smuzhiyun 	int tid, esel;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	/* invalidate all entries */
282*4882a593Smuzhiyun 	for (esel = 0; esel < vcpu_e500->gtlb_params[tlbsel].entries; esel++) {
283*4882a593Smuzhiyun 		tlbe = get_entry(vcpu_e500, tlbsel, esel);
284*4882a593Smuzhiyun 		tid = get_tlb_tid(tlbe);
285*4882a593Smuzhiyun 		if (type == 0 || tid == pid) {
286*4882a593Smuzhiyun 			inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
287*4882a593Smuzhiyun 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
288*4882a593Smuzhiyun 		}
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
tlbilx_one(struct kvmppc_vcpu_e500 * vcpu_e500,int pid,gva_t ea)292*4882a593Smuzhiyun static void tlbilx_one(struct kvmppc_vcpu_e500 *vcpu_e500, int pid,
293*4882a593Smuzhiyun 		       gva_t ea)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun 	int tlbsel, esel;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
298*4882a593Smuzhiyun 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, -1);
299*4882a593Smuzhiyun 		if (esel >= 0) {
300*4882a593Smuzhiyun 			inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
301*4882a593Smuzhiyun 			kvmppc_e500_gtlbe_invalidate(vcpu_e500, tlbsel, esel);
302*4882a593Smuzhiyun 			break;
303*4882a593Smuzhiyun 		}
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
kvmppc_e500_emul_tlbilx(struct kvm_vcpu * vcpu,int type,gva_t ea)307*4882a593Smuzhiyun int kvmppc_e500_emul_tlbilx(struct kvm_vcpu *vcpu, int type, gva_t ea)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
310*4882a593Smuzhiyun 	int pid = get_cur_spid(vcpu);
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if (type == 0 || type == 1) {
313*4882a593Smuzhiyun 		tlbilx_all(vcpu_e500, 0, pid, type);
314*4882a593Smuzhiyun 		tlbilx_all(vcpu_e500, 1, pid, type);
315*4882a593Smuzhiyun 	} else if (type == 3) {
316*4882a593Smuzhiyun 		tlbilx_one(vcpu_e500, pid, ea);
317*4882a593Smuzhiyun 	}
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	return EMULATE_DONE;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
kvmppc_e500_emul_tlbre(struct kvm_vcpu * vcpu)322*4882a593Smuzhiyun int kvmppc_e500_emul_tlbre(struct kvm_vcpu *vcpu)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
325*4882a593Smuzhiyun 	int tlbsel, esel;
326*4882a593Smuzhiyun 	struct kvm_book3e_206_tlb_entry *gtlbe;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	tlbsel = get_tlb_tlbsel(vcpu);
329*4882a593Smuzhiyun 	esel = get_tlb_esel(vcpu, tlbsel);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	gtlbe = get_entry(vcpu_e500, tlbsel, esel);
332*4882a593Smuzhiyun 	vcpu->arch.shared->mas0 &= ~MAS0_NV(~0);
333*4882a593Smuzhiyun 	vcpu->arch.shared->mas0 |= MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
334*4882a593Smuzhiyun 	vcpu->arch.shared->mas1 = gtlbe->mas1;
335*4882a593Smuzhiyun 	vcpu->arch.shared->mas2 = gtlbe->mas2;
336*4882a593Smuzhiyun 	vcpu->arch.shared->mas7_3 = gtlbe->mas7_3;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	return EMULATE_DONE;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
kvmppc_e500_emul_tlbsx(struct kvm_vcpu * vcpu,gva_t ea)341*4882a593Smuzhiyun int kvmppc_e500_emul_tlbsx(struct kvm_vcpu *vcpu, gva_t ea)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
344*4882a593Smuzhiyun 	int as = !!get_cur_sas(vcpu);
345*4882a593Smuzhiyun 	unsigned int pid = get_cur_spid(vcpu);
346*4882a593Smuzhiyun 	int esel, tlbsel;
347*4882a593Smuzhiyun 	struct kvm_book3e_206_tlb_entry *gtlbe = NULL;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
350*4882a593Smuzhiyun 		esel = kvmppc_e500_tlb_index(vcpu_e500, ea, tlbsel, pid, as);
351*4882a593Smuzhiyun 		if (esel >= 0) {
352*4882a593Smuzhiyun 			gtlbe = get_entry(vcpu_e500, tlbsel, esel);
353*4882a593Smuzhiyun 			break;
354*4882a593Smuzhiyun 		}
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	if (gtlbe) {
358*4882a593Smuzhiyun 		esel &= vcpu_e500->gtlb_params[tlbsel].ways - 1;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 		vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel)
361*4882a593Smuzhiyun 			| MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
362*4882a593Smuzhiyun 		vcpu->arch.shared->mas1 = gtlbe->mas1;
363*4882a593Smuzhiyun 		vcpu->arch.shared->mas2 = gtlbe->mas2;
364*4882a593Smuzhiyun 		vcpu->arch.shared->mas7_3 = gtlbe->mas7_3;
365*4882a593Smuzhiyun 	} else {
366*4882a593Smuzhiyun 		int victim;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 		/* since we only have two TLBs, only lower bit is used. */
369*4882a593Smuzhiyun 		tlbsel = vcpu->arch.shared->mas4 >> 28 & 0x1;
370*4882a593Smuzhiyun 		victim = (tlbsel == 0) ? gtlb0_get_next_victim(vcpu_e500) : 0;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 		vcpu->arch.shared->mas0 = MAS0_TLBSEL(tlbsel)
373*4882a593Smuzhiyun 			| MAS0_ESEL(victim)
374*4882a593Smuzhiyun 			| MAS0_NV(vcpu_e500->gtlb_nv[tlbsel]);
375*4882a593Smuzhiyun 		vcpu->arch.shared->mas1 =
376*4882a593Smuzhiyun 			  (vcpu->arch.shared->mas6 & MAS6_SPID0)
377*4882a593Smuzhiyun 			| ((vcpu->arch.shared->mas6 & MAS6_SAS) ? MAS1_TS : 0)
378*4882a593Smuzhiyun 			| (vcpu->arch.shared->mas4 & MAS4_TSIZED(~0));
379*4882a593Smuzhiyun 		vcpu->arch.shared->mas2 &= MAS2_EPN;
380*4882a593Smuzhiyun 		vcpu->arch.shared->mas2 |= vcpu->arch.shared->mas4 &
381*4882a593Smuzhiyun 					   MAS2_ATTRIB_MASK;
382*4882a593Smuzhiyun 		vcpu->arch.shared->mas7_3 &= MAS3_U0 | MAS3_U1 |
383*4882a593Smuzhiyun 					     MAS3_U2 | MAS3_U3;
384*4882a593Smuzhiyun 	}
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS);
387*4882a593Smuzhiyun 	return EMULATE_DONE;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
kvmppc_e500_emul_tlbwe(struct kvm_vcpu * vcpu)390*4882a593Smuzhiyun int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu)
391*4882a593Smuzhiyun {
392*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
393*4882a593Smuzhiyun 	struct kvm_book3e_206_tlb_entry *gtlbe;
394*4882a593Smuzhiyun 	int tlbsel, esel;
395*4882a593Smuzhiyun 	int recal = 0;
396*4882a593Smuzhiyun 	int idx;
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	tlbsel = get_tlb_tlbsel(vcpu);
399*4882a593Smuzhiyun 	esel = get_tlb_esel(vcpu, tlbsel);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	gtlbe = get_entry(vcpu_e500, tlbsel, esel);
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	if (get_tlb_v(gtlbe)) {
404*4882a593Smuzhiyun 		inval_gtlbe_on_host(vcpu_e500, tlbsel, esel);
405*4882a593Smuzhiyun 		if ((tlbsel == 1) &&
406*4882a593Smuzhiyun 			kvmppc_need_recalc_tlb1map_range(vcpu_e500, gtlbe))
407*4882a593Smuzhiyun 			recal = 1;
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	gtlbe->mas1 = vcpu->arch.shared->mas1;
411*4882a593Smuzhiyun 	gtlbe->mas2 = vcpu->arch.shared->mas2;
412*4882a593Smuzhiyun 	if (!(vcpu->arch.shared->msr & MSR_CM))
413*4882a593Smuzhiyun 		gtlbe->mas2 &= 0xffffffffUL;
414*4882a593Smuzhiyun 	gtlbe->mas7_3 = vcpu->arch.shared->mas7_3;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	trace_kvm_booke206_gtlb_write(vcpu->arch.shared->mas0, gtlbe->mas1,
417*4882a593Smuzhiyun 	                              gtlbe->mas2, gtlbe->mas7_3);
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	if (tlbsel == 1) {
420*4882a593Smuzhiyun 		/*
421*4882a593Smuzhiyun 		 * If a valid tlb1 entry is overwritten then recalculate the
422*4882a593Smuzhiyun 		 * min/max TLB1 map address range otherwise no need to look
423*4882a593Smuzhiyun 		 * in tlb1 array.
424*4882a593Smuzhiyun 		 */
425*4882a593Smuzhiyun 		if (recal)
426*4882a593Smuzhiyun 			kvmppc_recalc_tlb1map_range(vcpu_e500);
427*4882a593Smuzhiyun 		else
428*4882a593Smuzhiyun 			kvmppc_set_tlb1map_range(vcpu, gtlbe);
429*4882a593Smuzhiyun 	}
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	idx = srcu_read_lock(&vcpu->kvm->srcu);
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
434*4882a593Smuzhiyun 	if (tlbe_is_host_safe(vcpu, gtlbe)) {
435*4882a593Smuzhiyun 		u64 eaddr = get_tlb_eaddr(gtlbe);
436*4882a593Smuzhiyun 		u64 raddr = get_tlb_raddr(gtlbe);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 		if (tlbsel == 0) {
439*4882a593Smuzhiyun 			gtlbe->mas1 &= ~MAS1_TSIZE(~0);
440*4882a593Smuzhiyun 			gtlbe->mas1 |= MAS1_TSIZE(BOOK3E_PAGESZ_4K);
441*4882a593Smuzhiyun 		}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 		/* Premap the faulting page */
444*4882a593Smuzhiyun 		kvmppc_mmu_map(vcpu, eaddr, raddr, index_of(tlbsel, esel));
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
450*4882a593Smuzhiyun 	return EMULATE_DONE;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun 
kvmppc_e500_tlb_search(struct kvm_vcpu * vcpu,gva_t eaddr,unsigned int pid,int as)453*4882a593Smuzhiyun static int kvmppc_e500_tlb_search(struct kvm_vcpu *vcpu,
454*4882a593Smuzhiyun 				  gva_t eaddr, unsigned int pid, int as)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
457*4882a593Smuzhiyun 	int esel, tlbsel;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	for (tlbsel = 0; tlbsel < 2; tlbsel++) {
460*4882a593Smuzhiyun 		esel = kvmppc_e500_tlb_index(vcpu_e500, eaddr, tlbsel, pid, as);
461*4882a593Smuzhiyun 		if (esel >= 0)
462*4882a593Smuzhiyun 			return index_of(tlbsel, esel);
463*4882a593Smuzhiyun 	}
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	return -1;
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun /* 'linear_address' is actually an encoding of AS|PID|EADDR . */
kvmppc_core_vcpu_translate(struct kvm_vcpu * vcpu,struct kvm_translation * tr)469*4882a593Smuzhiyun int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
470*4882a593Smuzhiyun                                struct kvm_translation *tr)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun 	int index;
473*4882a593Smuzhiyun 	gva_t eaddr;
474*4882a593Smuzhiyun 	u8 pid;
475*4882a593Smuzhiyun 	u8 as;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	eaddr = tr->linear_address;
478*4882a593Smuzhiyun 	pid = (tr->linear_address >> 32) & 0xff;
479*4882a593Smuzhiyun 	as = (tr->linear_address >> 40) & 0x1;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	index = kvmppc_e500_tlb_search(vcpu, eaddr, pid, as);
482*4882a593Smuzhiyun 	if (index < 0) {
483*4882a593Smuzhiyun 		tr->valid = 0;
484*4882a593Smuzhiyun 		return 0;
485*4882a593Smuzhiyun 	}
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr);
488*4882a593Smuzhiyun 	/* XXX what does "writeable" and "usermode" even mean? */
489*4882a593Smuzhiyun 	tr->valid = 1;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	return 0;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 
kvmppc_mmu_itlb_index(struct kvm_vcpu * vcpu,gva_t eaddr)495*4882a593Smuzhiyun int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun 	unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
kvmppc_mmu_dtlb_index(struct kvm_vcpu * vcpu,gva_t eaddr)502*4882a593Smuzhiyun int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as);
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun 
kvmppc_mmu_itlb_miss(struct kvm_vcpu * vcpu)509*4882a593Smuzhiyun void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun 	unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.regs.nip, as);
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun 
kvmppc_mmu_dtlb_miss(struct kvm_vcpu * vcpu)516*4882a593Smuzhiyun void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun 	unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.fault_dear, as);
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun 
kvmppc_mmu_xlate(struct kvm_vcpu * vcpu,unsigned int index,gva_t eaddr)523*4882a593Smuzhiyun gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index,
524*4882a593Smuzhiyun 			gva_t eaddr)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
527*4882a593Smuzhiyun 	struct kvm_book3e_206_tlb_entry *gtlbe;
528*4882a593Smuzhiyun 	u64 pgmask;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	gtlbe = get_entry(vcpu_e500, tlbsel_of(index), esel_of(index));
531*4882a593Smuzhiyun 	pgmask = get_tlb_bytes(gtlbe) - 1;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun /*****************************************/
537*4882a593Smuzhiyun 
free_gtlb(struct kvmppc_vcpu_e500 * vcpu_e500)538*4882a593Smuzhiyun static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun 	int i;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	kvmppc_core_flush_tlb(&vcpu_e500->vcpu);
543*4882a593Smuzhiyun 	kfree(vcpu_e500->g2h_tlb1_map);
544*4882a593Smuzhiyun 	kfree(vcpu_e500->gtlb_priv[0]);
545*4882a593Smuzhiyun 	kfree(vcpu_e500->gtlb_priv[1]);
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	if (vcpu_e500->shared_tlb_pages) {
548*4882a593Smuzhiyun 		vfree((void *)(round_down((uintptr_t)vcpu_e500->gtlb_arch,
549*4882a593Smuzhiyun 					  PAGE_SIZE)));
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 		for (i = 0; i < vcpu_e500->num_shared_tlb_pages; i++) {
552*4882a593Smuzhiyun 			set_page_dirty_lock(vcpu_e500->shared_tlb_pages[i]);
553*4882a593Smuzhiyun 			put_page(vcpu_e500->shared_tlb_pages[i]);
554*4882a593Smuzhiyun 		}
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 		vcpu_e500->num_shared_tlb_pages = 0;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 		kfree(vcpu_e500->shared_tlb_pages);
559*4882a593Smuzhiyun 		vcpu_e500->shared_tlb_pages = NULL;
560*4882a593Smuzhiyun 	} else {
561*4882a593Smuzhiyun 		kfree(vcpu_e500->gtlb_arch);
562*4882a593Smuzhiyun 	}
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	vcpu_e500->gtlb_arch = NULL;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun 
kvmppc_get_sregs_e500_tlb(struct kvm_vcpu * vcpu,struct kvm_sregs * sregs)567*4882a593Smuzhiyun void kvmppc_get_sregs_e500_tlb(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	sregs->u.e.mas0 = vcpu->arch.shared->mas0;
570*4882a593Smuzhiyun 	sregs->u.e.mas1 = vcpu->arch.shared->mas1;
571*4882a593Smuzhiyun 	sregs->u.e.mas2 = vcpu->arch.shared->mas2;
572*4882a593Smuzhiyun 	sregs->u.e.mas7_3 = vcpu->arch.shared->mas7_3;
573*4882a593Smuzhiyun 	sregs->u.e.mas4 = vcpu->arch.shared->mas4;
574*4882a593Smuzhiyun 	sregs->u.e.mas6 = vcpu->arch.shared->mas6;
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	sregs->u.e.mmucfg = vcpu->arch.mmucfg;
577*4882a593Smuzhiyun 	sregs->u.e.tlbcfg[0] = vcpu->arch.tlbcfg[0];
578*4882a593Smuzhiyun 	sregs->u.e.tlbcfg[1] = vcpu->arch.tlbcfg[1];
579*4882a593Smuzhiyun 	sregs->u.e.tlbcfg[2] = 0;
580*4882a593Smuzhiyun 	sregs->u.e.tlbcfg[3] = 0;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun 
kvmppc_set_sregs_e500_tlb(struct kvm_vcpu * vcpu,struct kvm_sregs * sregs)583*4882a593Smuzhiyun int kvmppc_set_sregs_e500_tlb(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun 	if (sregs->u.e.features & KVM_SREGS_E_ARCH206_MMU) {
586*4882a593Smuzhiyun 		vcpu->arch.shared->mas0 = sregs->u.e.mas0;
587*4882a593Smuzhiyun 		vcpu->arch.shared->mas1 = sregs->u.e.mas1;
588*4882a593Smuzhiyun 		vcpu->arch.shared->mas2 = sregs->u.e.mas2;
589*4882a593Smuzhiyun 		vcpu->arch.shared->mas7_3 = sregs->u.e.mas7_3;
590*4882a593Smuzhiyun 		vcpu->arch.shared->mas4 = sregs->u.e.mas4;
591*4882a593Smuzhiyun 		vcpu->arch.shared->mas6 = sregs->u.e.mas6;
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	return 0;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun 
kvmppc_get_one_reg_e500_tlb(struct kvm_vcpu * vcpu,u64 id,union kvmppc_one_reg * val)597*4882a593Smuzhiyun int kvmppc_get_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
598*4882a593Smuzhiyun 				union kvmppc_one_reg *val)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun 	int r = 0;
601*4882a593Smuzhiyun 	long int i;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	switch (id) {
604*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS0:
605*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.shared->mas0);
606*4882a593Smuzhiyun 		break;
607*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS1:
608*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.shared->mas1);
609*4882a593Smuzhiyun 		break;
610*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS2:
611*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.shared->mas2);
612*4882a593Smuzhiyun 		break;
613*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS7_3:
614*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.shared->mas7_3);
615*4882a593Smuzhiyun 		break;
616*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS4:
617*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.shared->mas4);
618*4882a593Smuzhiyun 		break;
619*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS6:
620*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.shared->mas6);
621*4882a593Smuzhiyun 		break;
622*4882a593Smuzhiyun 	case KVM_REG_PPC_MMUCFG:
623*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.mmucfg);
624*4882a593Smuzhiyun 		break;
625*4882a593Smuzhiyun 	case KVM_REG_PPC_EPTCFG:
626*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.eptcfg);
627*4882a593Smuzhiyun 		break;
628*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB0CFG:
629*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB1CFG:
630*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB2CFG:
631*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB3CFG:
632*4882a593Smuzhiyun 		i = id - KVM_REG_PPC_TLB0CFG;
633*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.tlbcfg[i]);
634*4882a593Smuzhiyun 		break;
635*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB0PS:
636*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB1PS:
637*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB2PS:
638*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB3PS:
639*4882a593Smuzhiyun 		i = id - KVM_REG_PPC_TLB0PS;
640*4882a593Smuzhiyun 		*val = get_reg_val(id, vcpu->arch.tlbps[i]);
641*4882a593Smuzhiyun 		break;
642*4882a593Smuzhiyun 	default:
643*4882a593Smuzhiyun 		r = -EINVAL;
644*4882a593Smuzhiyun 		break;
645*4882a593Smuzhiyun 	}
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun 	return r;
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun 
kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu * vcpu,u64 id,union kvmppc_one_reg * val)650*4882a593Smuzhiyun int kvmppc_set_one_reg_e500_tlb(struct kvm_vcpu *vcpu, u64 id,
651*4882a593Smuzhiyun 			       union kvmppc_one_reg *val)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun 	int r = 0;
654*4882a593Smuzhiyun 	long int i;
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	switch (id) {
657*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS0:
658*4882a593Smuzhiyun 		vcpu->arch.shared->mas0 = set_reg_val(id, *val);
659*4882a593Smuzhiyun 		break;
660*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS1:
661*4882a593Smuzhiyun 		vcpu->arch.shared->mas1 = set_reg_val(id, *val);
662*4882a593Smuzhiyun 		break;
663*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS2:
664*4882a593Smuzhiyun 		vcpu->arch.shared->mas2 = set_reg_val(id, *val);
665*4882a593Smuzhiyun 		break;
666*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS7_3:
667*4882a593Smuzhiyun 		vcpu->arch.shared->mas7_3 = set_reg_val(id, *val);
668*4882a593Smuzhiyun 		break;
669*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS4:
670*4882a593Smuzhiyun 		vcpu->arch.shared->mas4 = set_reg_val(id, *val);
671*4882a593Smuzhiyun 		break;
672*4882a593Smuzhiyun 	case KVM_REG_PPC_MAS6:
673*4882a593Smuzhiyun 		vcpu->arch.shared->mas6 = set_reg_val(id, *val);
674*4882a593Smuzhiyun 		break;
675*4882a593Smuzhiyun 	/* Only allow MMU registers to be set to the config supported by KVM */
676*4882a593Smuzhiyun 	case KVM_REG_PPC_MMUCFG: {
677*4882a593Smuzhiyun 		u32 reg = set_reg_val(id, *val);
678*4882a593Smuzhiyun 		if (reg != vcpu->arch.mmucfg)
679*4882a593Smuzhiyun 			r = -EINVAL;
680*4882a593Smuzhiyun 		break;
681*4882a593Smuzhiyun 	}
682*4882a593Smuzhiyun 	case KVM_REG_PPC_EPTCFG: {
683*4882a593Smuzhiyun 		u32 reg = set_reg_val(id, *val);
684*4882a593Smuzhiyun 		if (reg != vcpu->arch.eptcfg)
685*4882a593Smuzhiyun 			r = -EINVAL;
686*4882a593Smuzhiyun 		break;
687*4882a593Smuzhiyun 	}
688*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB0CFG:
689*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB1CFG:
690*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB2CFG:
691*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB3CFG: {
692*4882a593Smuzhiyun 		/* MMU geometry (N_ENTRY/ASSOC) can be set only using SW_TLB */
693*4882a593Smuzhiyun 		u32 reg = set_reg_val(id, *val);
694*4882a593Smuzhiyun 		i = id - KVM_REG_PPC_TLB0CFG;
695*4882a593Smuzhiyun 		if (reg != vcpu->arch.tlbcfg[i])
696*4882a593Smuzhiyun 			r = -EINVAL;
697*4882a593Smuzhiyun 		break;
698*4882a593Smuzhiyun 	}
699*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB0PS:
700*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB1PS:
701*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB2PS:
702*4882a593Smuzhiyun 	case KVM_REG_PPC_TLB3PS: {
703*4882a593Smuzhiyun 		u32 reg = set_reg_val(id, *val);
704*4882a593Smuzhiyun 		i = id - KVM_REG_PPC_TLB0PS;
705*4882a593Smuzhiyun 		if (reg != vcpu->arch.tlbps[i])
706*4882a593Smuzhiyun 			r = -EINVAL;
707*4882a593Smuzhiyun 		break;
708*4882a593Smuzhiyun 	}
709*4882a593Smuzhiyun 	default:
710*4882a593Smuzhiyun 		r = -EINVAL;
711*4882a593Smuzhiyun 		break;
712*4882a593Smuzhiyun 	}
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	return r;
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun 
vcpu_mmu_geometry_update(struct kvm_vcpu * vcpu,struct kvm_book3e_206_tlb_params * params)717*4882a593Smuzhiyun static int vcpu_mmu_geometry_update(struct kvm_vcpu *vcpu,
718*4882a593Smuzhiyun 		struct kvm_book3e_206_tlb_params *params)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[0] &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
721*4882a593Smuzhiyun 	if (params->tlb_sizes[0] <= 2048)
722*4882a593Smuzhiyun 		vcpu->arch.tlbcfg[0] |= params->tlb_sizes[0];
723*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[0] |= params->tlb_ways[0] << TLBnCFG_ASSOC_SHIFT;
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[1] &= ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
726*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[1] |= params->tlb_sizes[1];
727*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[1] |= params->tlb_ways[1] << TLBnCFG_ASSOC_SHIFT;
728*4882a593Smuzhiyun 	return 0;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun 
kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu * vcpu,struct kvm_config_tlb * cfg)731*4882a593Smuzhiyun int kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
732*4882a593Smuzhiyun 			      struct kvm_config_tlb *cfg)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
735*4882a593Smuzhiyun 	struct kvm_book3e_206_tlb_params params;
736*4882a593Smuzhiyun 	char *virt;
737*4882a593Smuzhiyun 	struct page **pages;
738*4882a593Smuzhiyun 	struct tlbe_priv *privs[2] = {};
739*4882a593Smuzhiyun 	u64 *g2h_bitmap;
740*4882a593Smuzhiyun 	size_t array_len;
741*4882a593Smuzhiyun 	u32 sets;
742*4882a593Smuzhiyun 	int num_pages, ret, i;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	if (cfg->mmu_type != KVM_MMU_FSL_BOOKE_NOHV)
745*4882a593Smuzhiyun 		return -EINVAL;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	if (copy_from_user(&params, (void __user *)(uintptr_t)cfg->params,
748*4882a593Smuzhiyun 			   sizeof(params)))
749*4882a593Smuzhiyun 		return -EFAULT;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	if (params.tlb_sizes[1] > 64)
752*4882a593Smuzhiyun 		return -EINVAL;
753*4882a593Smuzhiyun 	if (params.tlb_ways[1] != params.tlb_sizes[1])
754*4882a593Smuzhiyun 		return -EINVAL;
755*4882a593Smuzhiyun 	if (params.tlb_sizes[2] != 0 || params.tlb_sizes[3] != 0)
756*4882a593Smuzhiyun 		return -EINVAL;
757*4882a593Smuzhiyun 	if (params.tlb_ways[2] != 0 || params.tlb_ways[3] != 0)
758*4882a593Smuzhiyun 		return -EINVAL;
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 	if (!is_power_of_2(params.tlb_ways[0]))
761*4882a593Smuzhiyun 		return -EINVAL;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	sets = params.tlb_sizes[0] >> ilog2(params.tlb_ways[0]);
764*4882a593Smuzhiyun 	if (!is_power_of_2(sets))
765*4882a593Smuzhiyun 		return -EINVAL;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	array_len = params.tlb_sizes[0] + params.tlb_sizes[1];
768*4882a593Smuzhiyun 	array_len *= sizeof(struct kvm_book3e_206_tlb_entry);
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun 	if (cfg->array_len < array_len)
771*4882a593Smuzhiyun 		return -EINVAL;
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	num_pages = DIV_ROUND_UP(cfg->array + array_len - 1, PAGE_SIZE) -
774*4882a593Smuzhiyun 		    cfg->array / PAGE_SIZE;
775*4882a593Smuzhiyun 	pages = kmalloc_array(num_pages, sizeof(*pages), GFP_KERNEL);
776*4882a593Smuzhiyun 	if (!pages)
777*4882a593Smuzhiyun 		return -ENOMEM;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	ret = get_user_pages_fast(cfg->array, num_pages, FOLL_WRITE, pages);
780*4882a593Smuzhiyun 	if (ret < 0)
781*4882a593Smuzhiyun 		goto free_pages;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	if (ret != num_pages) {
784*4882a593Smuzhiyun 		num_pages = ret;
785*4882a593Smuzhiyun 		ret = -EFAULT;
786*4882a593Smuzhiyun 		goto put_pages;
787*4882a593Smuzhiyun 	}
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	virt = vmap(pages, num_pages, VM_MAP, PAGE_KERNEL);
790*4882a593Smuzhiyun 	if (!virt) {
791*4882a593Smuzhiyun 		ret = -ENOMEM;
792*4882a593Smuzhiyun 		goto put_pages;
793*4882a593Smuzhiyun 	}
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 	privs[0] = kcalloc(params.tlb_sizes[0], sizeof(*privs[0]), GFP_KERNEL);
796*4882a593Smuzhiyun 	if (!privs[0]) {
797*4882a593Smuzhiyun 		ret = -ENOMEM;
798*4882a593Smuzhiyun 		goto put_pages;
799*4882a593Smuzhiyun 	}
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	privs[1] = kcalloc(params.tlb_sizes[1], sizeof(*privs[1]), GFP_KERNEL);
802*4882a593Smuzhiyun 	if (!privs[1]) {
803*4882a593Smuzhiyun 		ret = -ENOMEM;
804*4882a593Smuzhiyun 		goto free_privs_first;
805*4882a593Smuzhiyun 	}
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 	g2h_bitmap = kcalloc(params.tlb_sizes[1],
808*4882a593Smuzhiyun 			     sizeof(*g2h_bitmap),
809*4882a593Smuzhiyun 			     GFP_KERNEL);
810*4882a593Smuzhiyun 	if (!g2h_bitmap) {
811*4882a593Smuzhiyun 		ret = -ENOMEM;
812*4882a593Smuzhiyun 		goto free_privs_second;
813*4882a593Smuzhiyun 	}
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun 	free_gtlb(vcpu_e500);
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	vcpu_e500->gtlb_priv[0] = privs[0];
818*4882a593Smuzhiyun 	vcpu_e500->gtlb_priv[1] = privs[1];
819*4882a593Smuzhiyun 	vcpu_e500->g2h_tlb1_map = g2h_bitmap;
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	vcpu_e500->gtlb_arch = (struct kvm_book3e_206_tlb_entry *)
822*4882a593Smuzhiyun 		(virt + (cfg->array & (PAGE_SIZE - 1)));
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[0].entries = params.tlb_sizes[0];
825*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[1].entries = params.tlb_sizes[1];
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	vcpu_e500->gtlb_offset[0] = 0;
828*4882a593Smuzhiyun 	vcpu_e500->gtlb_offset[1] = params.tlb_sizes[0];
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	/* Update vcpu's MMU geometry based on SW_TLB input */
831*4882a593Smuzhiyun 	vcpu_mmu_geometry_update(vcpu, &params);
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 	vcpu_e500->shared_tlb_pages = pages;
834*4882a593Smuzhiyun 	vcpu_e500->num_shared_tlb_pages = num_pages;
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[0].ways = params.tlb_ways[0];
837*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[0].sets = sets;
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[1].ways = params.tlb_sizes[1];
840*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[1].sets = 1;
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	kvmppc_recalc_tlb1map_range(vcpu_e500);
843*4882a593Smuzhiyun 	return 0;
844*4882a593Smuzhiyun  free_privs_second:
845*4882a593Smuzhiyun 	kfree(privs[1]);
846*4882a593Smuzhiyun  free_privs_first:
847*4882a593Smuzhiyun 	kfree(privs[0]);
848*4882a593Smuzhiyun  put_pages:
849*4882a593Smuzhiyun 	for (i = 0; i < num_pages; i++)
850*4882a593Smuzhiyun 		put_page(pages[i]);
851*4882a593Smuzhiyun  free_pages:
852*4882a593Smuzhiyun 	kfree(pages);
853*4882a593Smuzhiyun 	return ret;
854*4882a593Smuzhiyun }
855*4882a593Smuzhiyun 
kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu * vcpu,struct kvm_dirty_tlb * dirty)856*4882a593Smuzhiyun int kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
857*4882a593Smuzhiyun 			     struct kvm_dirty_tlb *dirty)
858*4882a593Smuzhiyun {
859*4882a593Smuzhiyun 	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
860*4882a593Smuzhiyun 	kvmppc_recalc_tlb1map_range(vcpu_e500);
861*4882a593Smuzhiyun 	kvmppc_core_flush_tlb(vcpu);
862*4882a593Smuzhiyun 	return 0;
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun /* Vcpu's MMU default configuration */
vcpu_mmu_init(struct kvm_vcpu * vcpu,struct kvmppc_e500_tlb_params * params)866*4882a593Smuzhiyun static int vcpu_mmu_init(struct kvm_vcpu *vcpu,
867*4882a593Smuzhiyun 		       struct kvmppc_e500_tlb_params *params)
868*4882a593Smuzhiyun {
869*4882a593Smuzhiyun 	/* Initialize RASIZE, PIDSIZE, NTLBS and MAVN fields with host values*/
870*4882a593Smuzhiyun 	vcpu->arch.mmucfg = mfspr(SPRN_MMUCFG) & ~MMUCFG_LPIDSIZE;
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun 	/* Initialize TLBnCFG fields with host values and SW_TLB geometry*/
873*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[0] = mfspr(SPRN_TLB0CFG) &
874*4882a593Smuzhiyun 			     ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
875*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[0] |= params[0].entries;
876*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[0] |= params[0].ways << TLBnCFG_ASSOC_SHIFT;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[1] = mfspr(SPRN_TLB1CFG) &
879*4882a593Smuzhiyun 			     ~(TLBnCFG_N_ENTRY | TLBnCFG_ASSOC);
880*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[1] |= params[1].entries;
881*4882a593Smuzhiyun 	vcpu->arch.tlbcfg[1] |= params[1].ways << TLBnCFG_ASSOC_SHIFT;
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 	if (has_feature(vcpu, VCPU_FTR_MMU_V2)) {
884*4882a593Smuzhiyun 		vcpu->arch.tlbps[0] = mfspr(SPRN_TLB0PS);
885*4882a593Smuzhiyun 		vcpu->arch.tlbps[1] = mfspr(SPRN_TLB1PS);
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 		vcpu->arch.mmucfg &= ~MMUCFG_LRAT;
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 		/* Guest mmu emulation currently doesn't handle E.PT */
890*4882a593Smuzhiyun 		vcpu->arch.eptcfg = 0;
891*4882a593Smuzhiyun 		vcpu->arch.tlbcfg[0] &= ~TLBnCFG_PT;
892*4882a593Smuzhiyun 		vcpu->arch.tlbcfg[1] &= ~TLBnCFG_IND;
893*4882a593Smuzhiyun 	}
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 	return 0;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun 
kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 * vcpu_e500)898*4882a593Smuzhiyun int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
899*4882a593Smuzhiyun {
900*4882a593Smuzhiyun 	struct kvm_vcpu *vcpu = &vcpu_e500->vcpu;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	if (e500_mmu_host_init(vcpu_e500))
903*4882a593Smuzhiyun 		goto free_vcpu;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[0].entries = KVM_E500_TLB0_SIZE;
906*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[1].entries = KVM_E500_TLB1_SIZE;
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[0].ways = KVM_E500_TLB0_WAY_NUM;
909*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[0].sets =
910*4882a593Smuzhiyun 		KVM_E500_TLB0_SIZE / KVM_E500_TLB0_WAY_NUM;
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[1].ways = KVM_E500_TLB1_SIZE;
913*4882a593Smuzhiyun 	vcpu_e500->gtlb_params[1].sets = 1;
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 	vcpu_e500->gtlb_arch = kmalloc_array(KVM_E500_TLB0_SIZE +
916*4882a593Smuzhiyun 					     KVM_E500_TLB1_SIZE,
917*4882a593Smuzhiyun 					     sizeof(*vcpu_e500->gtlb_arch),
918*4882a593Smuzhiyun 					     GFP_KERNEL);
919*4882a593Smuzhiyun 	if (!vcpu_e500->gtlb_arch)
920*4882a593Smuzhiyun 		return -ENOMEM;
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	vcpu_e500->gtlb_offset[0] = 0;
923*4882a593Smuzhiyun 	vcpu_e500->gtlb_offset[1] = KVM_E500_TLB0_SIZE;
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun 	vcpu_e500->gtlb_priv[0] = kcalloc(vcpu_e500->gtlb_params[0].entries,
926*4882a593Smuzhiyun 					  sizeof(struct tlbe_ref),
927*4882a593Smuzhiyun 					  GFP_KERNEL);
928*4882a593Smuzhiyun 	if (!vcpu_e500->gtlb_priv[0])
929*4882a593Smuzhiyun 		goto free_vcpu;
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	vcpu_e500->gtlb_priv[1] = kcalloc(vcpu_e500->gtlb_params[1].entries,
932*4882a593Smuzhiyun 					  sizeof(struct tlbe_ref),
933*4882a593Smuzhiyun 					  GFP_KERNEL);
934*4882a593Smuzhiyun 	if (!vcpu_e500->gtlb_priv[1])
935*4882a593Smuzhiyun 		goto free_vcpu;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 	vcpu_e500->g2h_tlb1_map = kcalloc(vcpu_e500->gtlb_params[1].entries,
938*4882a593Smuzhiyun 					  sizeof(*vcpu_e500->g2h_tlb1_map),
939*4882a593Smuzhiyun 					  GFP_KERNEL);
940*4882a593Smuzhiyun 	if (!vcpu_e500->g2h_tlb1_map)
941*4882a593Smuzhiyun 		goto free_vcpu;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	vcpu_mmu_init(vcpu, vcpu_e500->gtlb_params);
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun 	kvmppc_recalc_tlb1map_range(vcpu_e500);
946*4882a593Smuzhiyun 	return 0;
947*4882a593Smuzhiyun  free_vcpu:
948*4882a593Smuzhiyun 	free_gtlb(vcpu_e500);
949*4882a593Smuzhiyun 	return -1;
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun 
kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 * vcpu_e500)952*4882a593Smuzhiyun void kvmppc_e500_tlb_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
953*4882a593Smuzhiyun {
954*4882a593Smuzhiyun 	free_gtlb(vcpu_e500);
955*4882a593Smuzhiyun 	e500_mmu_host_uninit(vcpu_e500);
956*4882a593Smuzhiyun }
957