aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/hash_low_64.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/hash_low_64.S')
-rw-r--r--arch/powerpc/mm/hash_low_64.S31
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 */
514htab_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
499htab_bail_ok: 523htab_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
663BEGIN_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
668END_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...)