diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/lpar.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 77 |
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 | ||
110 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 109 | static 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 | */ | ||
234 | static 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 | */ |
251 | static long pSeries_lpar_hpte_updatepp(unsigned long slot, | 234 | static 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 | ||
298 | static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize) | 281 | static 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 | ||
340 | static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, | 324 | static 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, | |||
358 | static void pSeries_lpar_hpte_removebolted(unsigned long ea, | 342 | static 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 | */ |
383 | static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | 368 | static 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) { |