aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/lpar.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/lpar.c')
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c77
1 files changed, 31 insertions, 46 deletions
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 5f3ef876ded2..0da39fed355a 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -31,7 +31,6 @@
31#include <asm/page.h> 31#include <asm/page.h>
32#include <asm/pgtable.h> 32#include <asm/pgtable.h>
33#include <asm/machdep.h> 33#include <asm/machdep.h>
34#include <asm/abs_addr.h>
35#include <asm/mmu_context.h> 34#include <asm/mmu_context.h>
36#include <asm/iommu.h> 35#include <asm/iommu.h>
37#include <asm/tlbflush.h> 36#include <asm/tlbflush.h>
@@ -108,9 +107,9 @@ void vpa_init(int cpu)
108} 107}
109 108
110static long pSeries_lpar_hpte_insert(unsigned long hpte_group, 109static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
111 unsigned long va, unsigned long pa, 110 unsigned long vpn, unsigned long pa,
112 unsigned long rflags, unsigned long vflags, 111 unsigned long rflags, unsigned long vflags,
113 int psize, int ssize) 112 int psize, int ssize)
114{ 113{
115 unsigned long lpar_rc; 114 unsigned long lpar_rc;
116 unsigned long flags; 115 unsigned long flags;
@@ -118,11 +117,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
118 unsigned long hpte_v, hpte_r; 117 unsigned long hpte_v, hpte_r;
119 118
120 if (!(vflags & HPTE_V_BOLTED)) 119 if (!(vflags & HPTE_V_BOLTED))
121 pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, " 120 pr_devel("hpte_insert(group=%lx, vpn=%016lx, "
122 "rflags=%lx, vflags=%lx, psize=%d)\n", 121 "pa=%016lx, rflags=%lx, vflags=%lx, psize=%d)\n",
123 hpte_group, va, pa, rflags, vflags, psize); 122 hpte_group, vpn, pa, rflags, vflags, psize);
124 123
125 hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID; 124 hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
126 hpte_r = hpte_encode_r(pa, psize) | rflags; 125 hpte_r = hpte_encode_r(pa, psize) | rflags;
127 126
128 if (!(vflags & HPTE_V_BOLTED)) 127 if (!(vflags & HPTE_V_BOLTED))
@@ -227,22 +226,6 @@ static void pSeries_lpar_hptab_clear(void)
227} 226}
228 227
229/* 228/*
230 * This computes the AVPN and B fields of the first dword of a HPTE,
231 * for use when we want to match an existing PTE. The bottom 7 bits
232 * of the returned value are zero.
233 */
234static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
235 int ssize)
236{
237 unsigned long v;
238
239 v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
240 v <<= HPTE_V_AVPN_SHIFT;
241 v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
242 return v;
243}
244
245/*
246 * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and 229 * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
247 * the low 3 bits of flags happen to line up. So no transform is needed. 230 * the low 3 bits of flags happen to line up. So no transform is needed.
248 * We can probably optimize here and assume the high bits of newpp are 231 * We can probably optimize here and assume the high bits of newpp are
@@ -250,14 +233,14 @@ static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
250 */ 233 */
251static long pSeries_lpar_hpte_updatepp(unsigned long slot, 234static long pSeries_lpar_hpte_updatepp(unsigned long slot,
252 unsigned long newpp, 235 unsigned long newpp,
253 unsigned long va, 236 unsigned long vpn,
254 int psize, int ssize, int local) 237 int psize, int ssize, int local)
255{ 238{
256 unsigned long lpar_rc; 239 unsigned long lpar_rc;
257 unsigned long flags = (newpp & 7) | H_AVPN; 240 unsigned long flags = (newpp & 7) | H_AVPN;
258 unsigned long want_v; 241 unsigned long want_v;
259 242
260 want_v = hpte_encode_avpn(va, psize, ssize); 243 want_v = hpte_encode_avpn(vpn, psize, ssize);
261 244
262 pr_devel(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...", 245 pr_devel(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
263 want_v, slot, flags, psize); 246 want_v, slot, flags, psize);
@@ -295,15 +278,15 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
295 return dword0; 278 return dword0;
296} 279}
297 280
298static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize) 281static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
299{ 282{
300 unsigned long hash; 283 unsigned long hash;
301 unsigned long i; 284 unsigned long i;
302 long slot; 285 long slot;
303 unsigned long want_v, hpte_v; 286 unsigned long want_v, hpte_v;
304 287
305 hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize); 288 hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
306 want_v = hpte_encode_avpn(va, psize, ssize); 289 want_v = hpte_encode_avpn(vpn, psize, ssize);
307 290
308 /* Bolted entries are always in the primary group */ 291 /* Bolted entries are always in the primary group */
309 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; 292 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -323,12 +306,13 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
323 unsigned long ea, 306 unsigned long ea,
324 int psize, int ssize) 307 int psize, int ssize)
325{ 308{
326 unsigned long lpar_rc, slot, vsid, va, flags; 309 unsigned long vpn;
310 unsigned long lpar_rc, slot, vsid, flags;
327 311
328 vsid = get_kernel_vsid(ea, ssize); 312 vsid = get_kernel_vsid(ea, ssize);
329 va = hpt_va(ea, vsid, ssize); 313 vpn = hpt_vpn(ea, vsid, ssize);
330 314
331 slot = pSeries_lpar_hpte_find(va, psize, ssize); 315 slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
332 BUG_ON(slot == -1); 316 BUG_ON(slot == -1);
333 317
334 flags = newpp & 7; 318 flags = newpp & 7;
@@ -337,17 +321,17 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
337 BUG_ON(lpar_rc != H_SUCCESS); 321 BUG_ON(lpar_rc != H_SUCCESS);
338} 322}
339 323
340static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, 324static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
341 int psize, int ssize, int local) 325 int psize, int ssize, int local)
342{ 326{
343 unsigned long want_v; 327 unsigned long want_v;
344 unsigned long lpar_rc; 328 unsigned long lpar_rc;
345 unsigned long dummy1, dummy2; 329 unsigned long dummy1, dummy2;
346 330
347 pr_devel(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n", 331 pr_devel(" inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n",
348 slot, va, psize, local); 332 slot, vpn, psize, local);
349 333
350 want_v = hpte_encode_avpn(va, psize, ssize); 334 want_v = hpte_encode_avpn(vpn, psize, ssize);
351 lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2); 335 lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
352 if (lpar_rc == H_NOT_FOUND) 336 if (lpar_rc == H_NOT_FOUND)
353 return; 337 return;
@@ -358,15 +342,16 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
358static void pSeries_lpar_hpte_removebolted(unsigned long ea, 342static void pSeries_lpar_hpte_removebolted(unsigned long ea,
359 int psize, int ssize) 343 int psize, int ssize)
360{ 344{
361 unsigned long slot, vsid, va; 345 unsigned long vpn;
346 unsigned long slot, vsid;
362 347
363 vsid = get_kernel_vsid(ea, ssize); 348 vsid = get_kernel_vsid(ea, ssize);
364 va = hpt_va(ea, vsid, ssize); 349 vpn = hpt_vpn(ea, vsid, ssize);
365 350
366 slot = pSeries_lpar_hpte_find(va, psize, ssize); 351 slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
367 BUG_ON(slot == -1); 352 BUG_ON(slot == -1);
368 353
369 pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0); 354 pSeries_lpar_hpte_invalidate(slot, vpn, psize, ssize, 0);
370} 355}
371 356
372/* Flag bits for H_BULK_REMOVE */ 357/* Flag bits for H_BULK_REMOVE */
@@ -382,12 +367,12 @@ static void pSeries_lpar_hpte_removebolted(unsigned long ea,
382 */ 367 */
383static void pSeries_lpar_flush_hash_range(unsigned long number, int local) 368static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
384{ 369{
370 unsigned long vpn;
385 unsigned long i, pix, rc; 371 unsigned long i, pix, rc;
386 unsigned long flags = 0; 372 unsigned long flags = 0;
387 struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); 373 struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
388 int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); 374 int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
389 unsigned long param[9]; 375 unsigned long param[9];
390 unsigned long va;
391 unsigned long hash, index, shift, hidx, slot; 376 unsigned long hash, index, shift, hidx, slot;
392 real_pte_t pte; 377 real_pte_t pte;
393 int psize, ssize; 378 int psize, ssize;
@@ -399,21 +384,21 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
399 ssize = batch->ssize; 384 ssize = batch->ssize;
400 pix = 0; 385 pix = 0;
401 for (i = 0; i < number; i++) { 386 for (i = 0; i < number; i++) {
402 va = batch->vaddr[i]; 387 vpn = batch->vpn[i];
403 pte = batch->pte[i]; 388 pte = batch->pte[i];
404 pte_iterate_hashed_subpages(pte, psize, va, index, shift) { 389 pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
405 hash = hpt_hash(va, shift, ssize); 390 hash = hpt_hash(vpn, shift, ssize);
406 hidx = __rpte_to_hidx(pte, index); 391 hidx = __rpte_to_hidx(pte, index);
407 if (hidx & _PTEIDX_SECONDARY) 392 if (hidx & _PTEIDX_SECONDARY)
408 hash = ~hash; 393 hash = ~hash;
409 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; 394 slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
410 slot += hidx & _PTEIDX_GROUP_IX; 395 slot += hidx & _PTEIDX_GROUP_IX;
411 if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { 396 if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
412 pSeries_lpar_hpte_invalidate(slot, va, psize, 397 pSeries_lpar_hpte_invalidate(slot, vpn, psize,
413 ssize, local); 398 ssize, local);
414 } else { 399 } else {
415 param[pix] = HBR_REQUEST | HBR_AVPN | slot; 400 param[pix] = HBR_REQUEST | HBR_AVPN | slot;
416 param[pix+1] = hpte_encode_avpn(va, psize, 401 param[pix+1] = hpte_encode_avpn(vpn, psize,
417 ssize); 402 ssize);
418 pix += 2; 403 pix += 2;
419 if (pix == 8) { 404 if (pix == 8) {