diff options
| -rw-r--r-- | arch/powerpc/mm/hash_native_64.c | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 79aedaf36f2b..7b7fe2d7b9dc 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <asm/tlb.h> | 26 | #include <asm/tlb.h> |
| 27 | #include <asm/cputable.h> | 27 | #include <asm/cputable.h> |
| 28 | #include <asm/udbg.h> | 28 | #include <asm/udbg.h> |
| 29 | #include <asm/kexec.h> | ||
| 29 | 30 | ||
| 30 | #ifdef DEBUG_LOW | 31 | #ifdef DEBUG_LOW |
| 31 | #define DBG_LOW(fmt...) udbg_printf(fmt) | 32 | #define DBG_LOW(fmt...) udbg_printf(fmt) |
| @@ -340,31 +341,70 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, | |||
| 340 | local_irq_restore(flags); | 341 | local_irq_restore(flags); |
| 341 | } | 342 | } |
| 342 | 343 | ||
| 343 | /* | 344 | #define LP_SHIFT 12 |
| 344 | * XXX This need fixing based on page size. It's only used by | 345 | #define LP_BITS 8 |
| 345 | * native_hpte_clear() for now which needs fixing too so they | 346 | #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) |
| 346 | * make a good pair... | ||
| 347 | */ | ||
| 348 | static unsigned long slot2va(unsigned long hpte_v, unsigned long slot) | ||
| 349 | { | ||
| 350 | unsigned long avpn = HPTE_V_AVPN_VAL(hpte_v); | ||
| 351 | unsigned long va; | ||
| 352 | 347 | ||
| 353 | va = avpn << 23; | 348 | static void hpte_decode(hpte_t *hpte, unsigned long slot, |
| 349 | int *psize, unsigned long *va) | ||
| 350 | { | ||
| 351 | unsigned long hpte_r = hpte->r; | ||
| 352 | unsigned long hpte_v = hpte->v; | ||
| 353 | unsigned long avpn; | ||
| 354 | int i, size, shift, penc, avpnm_bits; | ||
| 355 | |||
| 356 | if (!(hpte_v & HPTE_V_LARGE)) | ||
| 357 | size = MMU_PAGE_4K; | ||
| 358 | else { | ||
| 359 | for (i = 0; i < LP_BITS; i++) { | ||
| 360 | if ((hpte_r & LP_MASK(i+1)) == LP_MASK(i+1)) | ||
| 361 | break; | ||
| 362 | } | ||
| 363 | penc = LP_MASK(i+1) >> LP_SHIFT; | ||
| 364 | for (size = 0; size < MMU_PAGE_COUNT; size++) { | ||
| 354 | 365 | ||
| 355 | if (! (hpte_v & HPTE_V_LARGE)) { | 366 | /* 4K pages are not represented by LP */ |
| 356 | unsigned long vpi, pteg; | 367 | if (size == MMU_PAGE_4K) |
| 368 | continue; | ||
| 357 | 369 | ||
| 358 | pteg = slot / HPTES_PER_GROUP; | 370 | /* valid entries have a shift value */ |
| 359 | if (hpte_v & HPTE_V_SECONDARY) | 371 | if (!mmu_psize_defs[size].shift) |
| 360 | pteg = ~pteg; | 372 | continue; |
| 361 | 373 | ||
| 362 | vpi = ((va >> 28) ^ pteg) & htab_hash_mask; | 374 | if (penc == mmu_psize_defs[size].penc) |
| 375 | break; | ||
| 376 | } | ||
| 377 | } | ||
| 363 | 378 | ||
| 364 | va |= vpi << PAGE_SHIFT; | 379 | /* |
| 380 | * FIXME, the code below works for 16M, 64K, and 4K pages as these | ||
| 381 | * fall under the p<=23 rules for calculating the virtual address. | ||
| 382 | * In the case of 16M pages, an extra bit is stolen from the AVPN | ||
| 383 | * field to achieve the requisite 24 bits. | ||
| 384 | * | ||
| 385 | * Does not work for 16G pages or 1 TB segments. | ||
| 386 | */ | ||
| 387 | shift = mmu_psize_defs[size].shift; | ||
| 388 | if (mmu_psize_defs[size].avpnm) | ||
| 389 | avpnm_bits = __ilog2_u64(mmu_psize_defs[size].avpnm) + 1; | ||
| 390 | else | ||
| 391 | avpnm_bits = 0; | ||
| 392 | if (shift - avpnm_bits <= 23) { | ||
| 393 | avpn = HPTE_V_AVPN_VAL(hpte_v) << 23; | ||
| 394 | |||
| 395 | if (shift < 23) { | ||
| 396 | unsigned long vpi, pteg; | ||
| 397 | |||
| 398 | pteg = slot / HPTES_PER_GROUP; | ||
| 399 | if (hpte_v & HPTE_V_SECONDARY) | ||
| 400 | pteg = ~pteg; | ||
| 401 | vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask; | ||
| 402 | avpn |= (vpi << mmu_psize_defs[size].shift); | ||
| 403 | } | ||
| 365 | } | 404 | } |
| 366 | 405 | ||
| 367 | return va; | 406 | *va = avpn; |
| 407 | *psize = size; | ||
| 368 | } | 408 | } |
| 369 | 409 | ||
| 370 | /* | 410 | /* |
| @@ -374,15 +414,14 @@ static unsigned long slot2va(unsigned long hpte_v, unsigned long slot) | |||
| 374 | * | 414 | * |
| 375 | * TODO: add batching support when enabled. remember, no dynamic memory here, | 415 | * TODO: add batching support when enabled. remember, no dynamic memory here, |
| 376 | * athough there is the control page available... | 416 | * athough there is the control page available... |
| 377 | * | ||
| 378 | * XXX FIXME: 4k only for now ! | ||
| 379 | */ | 417 | */ |
| 380 | static void native_hpte_clear(void) | 418 | static void native_hpte_clear(void) |
| 381 | { | 419 | { |
| 382 | unsigned long slot, slots, flags; | 420 | unsigned long slot, slots, flags; |
| 383 | hpte_t *hptep = htab_address; | 421 | hpte_t *hptep = htab_address; |
| 384 | unsigned long hpte_v; | 422 | unsigned long hpte_v, va; |
| 385 | unsigned long pteg_count; | 423 | unsigned long pteg_count; |
| 424 | int psize; | ||
| 386 | 425 | ||
| 387 | pteg_count = htab_hash_mask + 1; | 426 | pteg_count = htab_hash_mask + 1; |
| 388 | 427 | ||
| @@ -408,8 +447,9 @@ static void native_hpte_clear(void) | |||
| 408 | * already hold the native_tlbie_lock. | 447 | * already hold the native_tlbie_lock. |
| 409 | */ | 448 | */ |
| 410 | if (hpte_v & HPTE_V_VALID) { | 449 | if (hpte_v & HPTE_V_VALID) { |
| 450 | hpte_decode(hptep, slot, &psize, &va); | ||
| 411 | hptep->v = 0; | 451 | hptep->v = 0; |
| 412 | __tlbie(slot2va(hpte_v, slot), MMU_PAGE_4K); | 452 | __tlbie(va, psize); |
| 413 | } | 453 | } |
| 414 | } | 454 | } |
| 415 | 455 | ||
