1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License, version 2, as
4  * published by the Free Software Foundation.
5  *
6  * Copyright 2010-2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
7  */
8 
9 #include <linux/types.h>
10 #include <linux/string.h>
11 #include <linux/kvm.h>
12 #include <linux/kvm_host.h>
13 #include <linux/hugetlb.h>
14 
15 #include <asm/tlbflush.h>
16 #include <asm/kvm_ppc.h>
17 #include <asm/kvm_book3s.h>
18 #include <asm/mmu-hash64.h>
19 #include <asm/hvcall.h>
20 #include <asm/synch.h>
21 #include <asm/ppc-opcode.h>
22 
23 /* For now use fixed-size 16MB page table */
24 #define HPT_ORDER	24
25 #define HPT_NPTEG	(1ul << (HPT_ORDER - 7))	/* 128B per pteg */
26 #define HPT_HASH_MASK	(HPT_NPTEG - 1)
27 
28 #define HPTE_V_HVLOCK	0x40UL
29 
30 static inline long lock_hpte(unsigned long *hpte, unsigned long bits)
31 {
32 	unsigned long tmp, old;
33 
34 	asm volatile("	ldarx	%0,0,%2\n"
35 		     "	and.	%1,%0,%3\n"
36 		     "	bne	2f\n"
37 		     "	ori	%0,%0,%4\n"
38 		     "  stdcx.	%0,0,%2\n"
39 		     "	beq+	2f\n"
40 		     "	li	%1,%3\n"
41 		     "2:	isync"
42 		     : "=&r" (tmp), "=&r" (old)
43 		     : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK)
44 		     : "cc", "memory");
45 	return old == 0;
46 }
47 
48 long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
49 		    long pte_index, unsigned long pteh, unsigned long ptel)
50 {
51 	unsigned long porder;
52 	struct kvm *kvm = vcpu->kvm;
53 	unsigned long i, lpn, pa;
54 	unsigned long *hpte;
55 
56 	/* only handle 4k, 64k and 16M pages for now */
57 	porder = 12;
58 	if (pteh & HPTE_V_LARGE) {
59 		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
60 		    (ptel & 0xf000) == 0x1000) {
61 			/* 64k page */
62 			porder = 16;
63 		} else if ((ptel & 0xff000) == 0) {
64 			/* 16M page */
65 			porder = 24;
66 			/* lowest AVA bit must be 0 for 16M pages */
67 			if (pteh & 0x80)
68 				return H_PARAMETER;
69 		} else
70 			return H_PARAMETER;
71 	}
72 	lpn = (ptel & HPTE_R_RPN) >> kvm->arch.ram_porder;
73 	if (lpn >= kvm->arch.ram_npages || porder > kvm->arch.ram_porder)
74 		return H_PARAMETER;
75 	pa = kvm->arch.ram_pginfo[lpn].pfn << PAGE_SHIFT;
76 	if (!pa)
77 		return H_PARAMETER;
78 	/* Check WIMG */
79 	if ((ptel & HPTE_R_WIMG) != HPTE_R_M &&
80 	    (ptel & HPTE_R_WIMG) != (HPTE_R_W | HPTE_R_I | HPTE_R_M))
81 		return H_PARAMETER;
82 	pteh &= ~0x60UL;
83 	ptel &= ~(HPTE_R_PP0 - kvm->arch.ram_psize);
84 	ptel |= pa;
85 	if (pte_index >= (HPT_NPTEG << 3))
86 		return H_PARAMETER;
87 	if (likely((flags & H_EXACT) == 0)) {
88 		pte_index &= ~7UL;
89 		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
90 		for (i = 0; ; ++i) {
91 			if (i == 8)
92 				return H_PTEG_FULL;
93 			if ((*hpte & HPTE_V_VALID) == 0 &&
94 			    lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
95 				break;
96 			hpte += 2;
97 		}
98 	} else {
99 		i = 0;
100 		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
101 		if (!lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID))
102 			return H_PTEG_FULL;
103 	}
104 	hpte[1] = ptel;
105 	eieio();
106 	hpte[0] = pteh;
107 	asm volatile("ptesync" : : : "memory");
108 	atomic_inc(&kvm->arch.ram_pginfo[lpn].refcnt);
109 	vcpu->arch.gpr[4] = pte_index + i;
110 	return H_SUCCESS;
111 }
112 
113 static unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
114 				      unsigned long pte_index)
115 {
116 	unsigned long rb, va_low;
117 
118 	rb = (v & ~0x7fUL) << 16;		/* AVA field */
119 	va_low = pte_index >> 3;
120 	if (v & HPTE_V_SECONDARY)
121 		va_low = ~va_low;
122 	/* xor vsid from AVA */
123 	if (!(v & HPTE_V_1TB_SEG))
124 		va_low ^= v >> 12;
125 	else
126 		va_low ^= v >> 24;
127 	va_low &= 0x7ff;
128 	if (v & HPTE_V_LARGE) {
129 		rb |= 1;			/* L field */
130 		if (cpu_has_feature(CPU_FTR_ARCH_206) &&
131 		    (r & 0xff000)) {
132 			/* non-16MB large page, must be 64k */
133 			/* (masks depend on page size) */
134 			rb |= 0x1000;		/* page encoding in LP field */
135 			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
136 			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
137 		}
138 	} else {
139 		/* 4kB page */
140 		rb |= (va_low & 0x7ff) << 12;	/* remaining 11b of VA */
141 	}
142 	rb |= (v >> 54) & 0x300;		/* B field */
143 	return rb;
144 }
145 
146 #define LOCK_TOKEN	(*(u32 *)(&get_paca()->lock_token))
147 
148 static inline int try_lock_tlbie(unsigned int *lock)
149 {
150 	unsigned int tmp, old;
151 	unsigned int token = LOCK_TOKEN;
152 
153 	asm volatile("1:lwarx	%1,0,%2\n"
154 		     "	cmpwi	cr0,%1,0\n"
155 		     "	bne	2f\n"
156 		     "  stwcx.	%3,0,%2\n"
157 		     "	bne-	1b\n"
158 		     "  isync\n"
159 		     "2:"
160 		     : "=&r" (tmp), "=&r" (old)
161 		     : "r" (lock), "r" (token)
162 		     : "cc", "memory");
163 	return old == 0;
164 }
165 
166 long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
167 		     unsigned long pte_index, unsigned long avpn,
168 		     unsigned long va)
169 {
170 	struct kvm *kvm = vcpu->kvm;
171 	unsigned long *hpte;
172 	unsigned long v, r, rb;
173 
174 	if (pte_index >= (HPT_NPTEG << 3))
175 		return H_PARAMETER;
176 	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
177 	while (!lock_hpte(hpte, HPTE_V_HVLOCK))
178 		cpu_relax();
179 	if ((hpte[0] & HPTE_V_VALID) == 0 ||
180 	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) ||
181 	    ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) {
182 		hpte[0] &= ~HPTE_V_HVLOCK;
183 		return H_NOT_FOUND;
184 	}
185 	if (atomic_read(&kvm->online_vcpus) == 1)
186 		flags |= H_LOCAL;
187 	vcpu->arch.gpr[4] = v = hpte[0] & ~HPTE_V_HVLOCK;
188 	vcpu->arch.gpr[5] = r = hpte[1];
189 	rb = compute_tlbie_rb(v, r, pte_index);
190 	hpte[0] = 0;
191 	if (!(flags & H_LOCAL)) {
192 		while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
193 			cpu_relax();
194 		asm volatile("ptesync" : : : "memory");
195 		asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
196 			     : : "r" (rb), "r" (kvm->arch.lpid));
197 		asm volatile("ptesync" : : : "memory");
198 		kvm->arch.tlbie_lock = 0;
199 	} else {
200 		asm volatile("ptesync" : : : "memory");
201 		asm volatile("tlbiel %0" : : "r" (rb));
202 		asm volatile("ptesync" : : : "memory");
203 	}
204 	return H_SUCCESS;
205 }
206 
207 long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
208 {
209 	struct kvm *kvm = vcpu->kvm;
210 	unsigned long *args = &vcpu->arch.gpr[4];
211 	unsigned long *hp, tlbrb[4];
212 	long int i, found;
213 	long int n_inval = 0;
214 	unsigned long flags, req, pte_index;
215 	long int local = 0;
216 	long int ret = H_SUCCESS;
217 
218 	if (atomic_read(&kvm->online_vcpus) == 1)
219 		local = 1;
220 	for (i = 0; i < 4; ++i) {
221 		pte_index = args[i * 2];
222 		flags = pte_index >> 56;
223 		pte_index &= ((1ul << 56) - 1);
224 		req = flags >> 6;
225 		flags &= 3;
226 		if (req == 3)
227 			break;
228 		if (req != 1 || flags == 3 ||
229 		    pte_index >= (HPT_NPTEG << 3)) {
230 			/* parameter error */
231 			args[i * 2] = ((0xa0 | flags) << 56) + pte_index;
232 			ret = H_PARAMETER;
233 			break;
234 		}
235 		hp = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
236 		while (!lock_hpte(hp, HPTE_V_HVLOCK))
237 			cpu_relax();
238 		found = 0;
239 		if (hp[0] & HPTE_V_VALID) {
240 			switch (flags & 3) {
241 			case 0:		/* absolute */
242 				found = 1;
243 				break;
244 			case 1:		/* andcond */
245 				if (!(hp[0] & args[i * 2 + 1]))
246 					found = 1;
247 				break;
248 			case 2:		/* AVPN */
249 				if ((hp[0] & ~0x7fUL) == args[i * 2 + 1])
250 					found = 1;
251 				break;
252 			}
253 		}
254 		if (!found) {
255 			hp[0] &= ~HPTE_V_HVLOCK;
256 			args[i * 2] = ((0x90 | flags) << 56) + pte_index;
257 			continue;
258 		}
259 		/* insert R and C bits from PTE */
260 		flags |= (hp[1] >> 5) & 0x0c;
261 		args[i * 2] = ((0x80 | flags) << 56) + pte_index;
262 		tlbrb[n_inval++] = compute_tlbie_rb(hp[0], hp[1], pte_index);
263 		hp[0] = 0;
264 	}
265 	if (n_inval == 0)
266 		return ret;
267 
268 	if (!local) {
269 		while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
270 			cpu_relax();
271 		asm volatile("ptesync" : : : "memory");
272 		for (i = 0; i < n_inval; ++i)
273 			asm volatile(PPC_TLBIE(%1,%0)
274 				     : : "r" (tlbrb[i]), "r" (kvm->arch.lpid));
275 		asm volatile("eieio; tlbsync; ptesync" : : : "memory");
276 		kvm->arch.tlbie_lock = 0;
277 	} else {
278 		asm volatile("ptesync" : : : "memory");
279 		for (i = 0; i < n_inval; ++i)
280 			asm volatile("tlbiel %0" : : "r" (tlbrb[i]));
281 		asm volatile("ptesync" : : : "memory");
282 	}
283 	return ret;
284 }
285 
286 long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
287 		      unsigned long pte_index, unsigned long avpn,
288 		      unsigned long va)
289 {
290 	struct kvm *kvm = vcpu->kvm;
291 	unsigned long *hpte;
292 	unsigned long v, r, rb;
293 
294 	if (pte_index >= (HPT_NPTEG << 3))
295 		return H_PARAMETER;
296 	hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
297 	while (!lock_hpte(hpte, HPTE_V_HVLOCK))
298 		cpu_relax();
299 	if ((hpte[0] & HPTE_V_VALID) == 0 ||
300 	    ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) {
301 		hpte[0] &= ~HPTE_V_HVLOCK;
302 		return H_NOT_FOUND;
303 	}
304 	if (atomic_read(&kvm->online_vcpus) == 1)
305 		flags |= H_LOCAL;
306 	v = hpte[0];
307 	r = hpte[1] & ~(HPTE_R_PP0 | HPTE_R_PP | HPTE_R_N |
308 			HPTE_R_KEY_HI | HPTE_R_KEY_LO);
309 	r |= (flags << 55) & HPTE_R_PP0;
310 	r |= (flags << 48) & HPTE_R_KEY_HI;
311 	r |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
312 	rb = compute_tlbie_rb(v, r, pte_index);
313 	hpte[0] = v & ~HPTE_V_VALID;
314 	if (!(flags & H_LOCAL)) {
315 		while(!try_lock_tlbie(&kvm->arch.tlbie_lock))
316 			cpu_relax();
317 		asm volatile("ptesync" : : : "memory");
318 		asm volatile(PPC_TLBIE(%1,%0)"; eieio; tlbsync"
319 			     : : "r" (rb), "r" (kvm->arch.lpid));
320 		asm volatile("ptesync" : : : "memory");
321 		kvm->arch.tlbie_lock = 0;
322 	} else {
323 		asm volatile("ptesync" : : : "memory");
324 		asm volatile("tlbiel %0" : : "r" (rb));
325 		asm volatile("ptesync" : : : "memory");
326 	}
327 	hpte[1] = r;
328 	eieio();
329 	hpte[0] = v & ~HPTE_V_HVLOCK;
330 	asm volatile("ptesync" : : : "memory");
331 	return H_SUCCESS;
332 }
333 
334 static unsigned long reverse_xlate(struct kvm *kvm, unsigned long realaddr)
335 {
336 	long int i;
337 	unsigned long offset, rpn;
338 
339 	offset = realaddr & (kvm->arch.ram_psize - 1);
340 	rpn = (realaddr - offset) >> PAGE_SHIFT;
341 	for (i = 0; i < kvm->arch.ram_npages; ++i)
342 		if (rpn == kvm->arch.ram_pginfo[i].pfn)
343 			return (i << PAGE_SHIFT) + offset;
344 	return HPTE_R_RPN;	/* all 1s in the RPN field */
345 }
346 
347 long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
348 		   unsigned long pte_index)
349 {
350 	struct kvm *kvm = vcpu->kvm;
351 	unsigned long *hpte, r;
352 	int i, n = 1;
353 
354 	if (pte_index >= (HPT_NPTEG << 3))
355 		return H_PARAMETER;
356 	if (flags & H_READ_4) {
357 		pte_index &= ~3;
358 		n = 4;
359 	}
360 	for (i = 0; i < n; ++i, ++pte_index) {
361 		hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
362 		r = hpte[1];
363 		if ((flags & H_R_XLATE) && (hpte[0] & HPTE_V_VALID))
364 			r = reverse_xlate(kvm, r & HPTE_R_RPN) |
365 				(r & ~HPTE_R_RPN);
366 		vcpu->arch.gpr[4 + i * 2] = hpte[0];
367 		vcpu->arch.gpr[5 + i * 2] = r;
368 	}
369 	return H_SUCCESS;
370 }
371