diff options
Diffstat (limited to 'arch/powerpc/mm/hash_low_64.S')
-rw-r--r-- | arch/powerpc/mm/hash_low_64.S | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index e0d02c4a2615..52e914238959 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S | |||
@@ -136,6 +136,7 @@ _GLOBAL(__hash_page_4K) | |||
136 | and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ | 136 | and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ |
137 | andc r0,r30,r0 /* r0 = pte & ~r0 */ | 137 | andc r0,r30,r0 /* r0 = pte & ~r0 */ |
138 | rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ | 138 | rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ |
139 | ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ | ||
139 | 140 | ||
140 | /* We eventually do the icache sync here (maybe inline that | 141 | /* We eventually do the icache sync here (maybe inline that |
141 | * code rather than call a C function...) | 142 | * code rather than call a C function...) |
@@ -368,6 +369,7 @@ _GLOBAL(__hash_page_4K) | |||
368 | rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ | 369 | rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */ |
369 | or r30,r30,r31 | 370 | or r30,r30,r31 |
370 | ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE | 371 | ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE |
372 | oris r30,r30,_PAGE_COMBO@h | ||
371 | /* Write the linux PTE atomically (setting busy) */ | 373 | /* Write the linux PTE atomically (setting busy) */ |
372 | stdcx. r30,0,r6 | 374 | stdcx. r30,0,r6 |
373 | bne- 1b | 375 | bne- 1b |
@@ -400,6 +402,7 @@ _GLOBAL(__hash_page_4K) | |||
400 | and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ | 402 | and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ |
401 | andc r0,r30,r0 /* r0 = pte & ~r0 */ | 403 | andc r0,r30,r0 /* r0 = pte & ~r0 */ |
402 | rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ | 404 | rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ |
405 | ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ | ||
403 | 406 | ||
404 | /* We eventually do the icache sync here (maybe inline that | 407 | /* We eventually do the icache sync here (maybe inline that |
405 | * code rather than call a C function...) | 408 | * code rather than call a C function...) |
@@ -426,6 +429,14 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) | |||
426 | andi. r0,r31,_PAGE_HASHPTE | 429 | andi. r0,r31,_PAGE_HASHPTE |
427 | li r26,0 /* Default hidx */ | 430 | li r26,0 /* Default hidx */ |
428 | beq htab_insert_pte | 431 | beq htab_insert_pte |
432 | |||
433 | /* | ||
434 | * Check if the pte was already inserted into the hash table | ||
435 | * as a 64k HW page, and invalidate the 64k HPTE if so. | ||
436 | */ | ||
437 | andis. r0,r31,_PAGE_COMBO@h | ||
438 | beq htab_inval_old_hpte | ||
439 | |||
429 | ld r6,STK_PARM(r6)(r1) | 440 | ld r6,STK_PARM(r6)(r1) |
430 | ori r26,r6,0x8000 /* Load the hidx mask */ | 441 | ori r26,r6,0x8000 /* Load the hidx mask */ |
431 | ld r26,0(r26) | 442 | ld r26,0(r26) |
@@ -496,6 +507,19 @@ _GLOBAL(htab_call_hpte_remove) | |||
496 | /* Try all again */ | 507 | /* Try all again */ |
497 | b htab_insert_pte | 508 | b htab_insert_pte |
498 | 509 | ||
510 | /* | ||
511 | * Call out to C code to invalidate an 64k HW HPTE that is | ||
512 | * useless now that the segment has been switched to 4k pages. | ||
513 | */ | ||
514 | htab_inval_old_hpte: | ||
515 | mr r3,r29 /* virtual addr */ | ||
516 | mr r4,r31 /* PTE.pte */ | ||
517 | li r5,0 /* PTE.hidx */ | ||
518 | li r6,MMU_PAGE_64K /* psize */ | ||
519 | ld r7,STK_PARM(r8)(r1) /* local */ | ||
520 | bl .flush_hash_page | ||
521 | b htab_insert_pte | ||
522 | |||
499 | htab_bail_ok: | 523 | htab_bail_ok: |
500 | li r3,0 | 524 | li r3,0 |
501 | b htab_bail | 525 | b htab_bail |
@@ -636,6 +660,12 @@ _GLOBAL(__hash_page_64K) | |||
636 | * is changing this PTE anyway and might hash it. | 660 | * is changing this PTE anyway and might hash it. |
637 | */ | 661 | */ |
638 | bne- ht64_bail_ok | 662 | bne- ht64_bail_ok |
663 | BEGIN_FTR_SECTION | ||
664 | /* Check if PTE has the cache-inhibit bit set */ | ||
665 | andi. r0,r31,_PAGE_NO_CACHE | ||
666 | /* If so, bail out and refault as a 4k page */ | ||
667 | bne- ht64_bail_ok | ||
668 | END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE) | ||
639 | /* Prepare new PTE value (turn access RW into DIRTY, then | 669 | /* Prepare new PTE value (turn access RW into DIRTY, then |
640 | * add BUSY,HASHPTE and ACCESSED) | 670 | * add BUSY,HASHPTE and ACCESSED) |
641 | */ | 671 | */ |
@@ -671,6 +701,7 @@ _GLOBAL(__hash_page_64K) | |||
671 | and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ | 701 | and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/ |
672 | andc r0,r30,r0 /* r0 = pte & ~r0 */ | 702 | andc r0,r30,r0 /* r0 = pte & ~r0 */ |
673 | rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ | 703 | rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ |
704 | ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */ | ||
674 | 705 | ||
675 | /* We eventually do the icache sync here (maybe inline that | 706 | /* We eventually do the icache sync here (maybe inline that |
676 | * code rather than call a C function...) | 707 | * code rather than call a C function...) |