2 * ppc64 MMU hashtable management routines
4 * (c) Copyright IBM Corp. 2003, 2005
6 * Maintained by: Benjamin Herrenschmidt
7 * <benh@kernel.crashing.org>
9 * This file is covered by the GNU Public Licence v2 as
10 * described in the kernel's COPYING file.
14 #include <asm/pgtable.h>
17 #include <asm/types.h>
18 #include <asm/ppc_asm.h>
19 #include <asm/asm-offsets.h>
20 #include <asm/cputable.h>
27 * +-> Back chain (SP + 256)
28 * | General register save area (SP + 112)
29 * | Parameter save area (SP + 48)
30 * | TOC save area (SP + 40)
31 * | link editor doubleword (SP + 32)
32 * | compiler doubleword (SP + 24)
33 * | LR save area (SP + 16)
34 * | CR save area (SP + 8)
35 * SP ---> +-- Back chain (SP + 0)
38 #ifndef CONFIG_PPC_64K_PAGES
40 /*****************************************************************************
42 * 4K SW & 4K HW pages implementation *
44 *****************************************************************************/
48 * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
49 * pte_t *ptep, unsigned long trap, int local, int ssize)
51 * Adds a 4K page to the hash table in a segment of 4K pages only
54 _GLOBAL(__hash_page_4K)
57 stdu r1,-STACKFRAMESIZE(r1)
58 /* Save all params that we need after a function call */
59 std r6,STK_PARAM(R6)(r1)
60 std r8,STK_PARAM(R8)(r1)
61 std r9,STK_PARAM(R9)(r1)
63 /* Save non-volatile registers.
64 * r31 will hold "old PTE"
68 * r27 is hashtab mask (maybe dynamic patched instead ?)
70 std r27,STK_REG(R27)(r1)
71 std r28,STK_REG(R28)(r1)
72 std r29,STK_REG(R29)(r1)
73 std r30,STK_REG(R30)(r1)
74 std r31,STK_REG(R31)(r1)
78 * Check permissions, atomically mark the linux PTE busy
83 /* Check access rights (access & ~(pte_val(*ptep))) */
85 bne- htab_wrong_access
86 /* Check if PTE is busy */
87 andi. r0,r31,_PAGE_BUSY
88 /* If so, just bail out and refault if needed. Someone else
89 * is changing this PTE anyway and might hash it.
93 /* Prepare new PTE value (turn access RW into DIRTY, then
94 * add BUSY,HASHPTE and ACCESSED)
96 rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
98 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
99 /* Write the linux PTE atomically (setting busy) */
106 * Insert/Update the HPTE in the hash table. At this point,
107 * r4 (access) is re-useable, we use it for the new HPTE flags
111 cmpdi r9,0 /* check segment size */
113 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
114 /* Calc va and put it in r29 */
115 rldicr r29,r5,28,63-28
119 /* Calculate hash value for primary slot and store it in r28 */
120 rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
121 rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */
125 3: /* Calc VA and hash in r29 and r28 for 1T segment */
126 sldi r29,r5,40 /* vsid << 40 */
127 clrldi r3,r3,24 /* ea & 0xffffffffff */
128 rldic r28,r5,25,25 /* (vsid << 25) & 0x7fffffffff */
129 clrldi r5,r5,40 /* vsid & 0xffffff */
130 rldicl r0,r3,64-12,36 /* (ea >> 12) & 0xfffffff */
132 or r29,r3,r29 /* VA */
133 xor r28,r28,r0 /* hash */
135 /* Convert linux PTE bits into HW equivalents */
136 4: andi. r3,r30,0x1fe /* Get basic set of flags */
137 xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
138 rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
139 rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
140 and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
141 andc r0,r30,r0 /* r0 = pte & ~r0 */
142 rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
143 ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */
145 /* We eventually do the icache sync here (maybe inline that
146 * code rather than call a C function...)
151 bl .hash_page_do_lazy_icache
152 END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
154 /* At this point, r3 contains new PP bits, save them in
155 * place of "access" in the param area (sic)
157 std r3,STK_PARAM(R4)(r1)
159 /* Get htab_hash_mask */
160 ld r4,htab_hash_mask@got(2)
161 ld r27,0(r4) /* htab_hash_mask -> r27 */
163 /* Check if we may already be in the hashtable, in this case, we
164 * go to out-of-line code to try to modify the HPTE
166 andi. r0,r31,_PAGE_HASHPTE
170 /* Clear hpte bits in new pte (we also clear BUSY btw) and
173 lis r0,_PAGE_HPTEFLAGS@h
174 ori r0,r0,_PAGE_HPTEFLAGS@l
176 ori r30,r30,_PAGE_HASHPTE
178 /* physical address r5 */
179 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
180 sldi r5,r5,PAGE_SHIFT
182 /* Calculate primary group hash */
184 rldicr r3,r0,3,63-3 /* r3 = (hash & mask) << 3 */
186 /* Call ppc_md.hpte_insert */
187 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
188 mr r4,r29 /* Retrieve va */
189 li r7,0 /* !bolted, !secondary */
190 li r8,MMU_PAGE_4K /* page size */
191 ld r9,STK_PARAM(R9)(r1) /* segment size */
192 _GLOBAL(htab_call_hpte_insert1)
193 bl . /* Patched by htab_finish_init() */
195 bge htab_pte_insert_ok /* Insertion successful */
196 cmpdi 0,r3,-2 /* Critical failure */
197 beq- htab_pte_insert_failure
199 /* Now try secondary slot */
201 /* physical address r5 */
202 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
203 sldi r5,r5,PAGE_SHIFT
205 /* Calculate secondary group hash */
207 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
209 /* Call ppc_md.hpte_insert */
210 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
211 mr r4,r29 /* Retrieve va */
212 li r7,HPTE_V_SECONDARY /* !bolted, secondary */
213 li r8,MMU_PAGE_4K /* page size */
214 ld r9,STK_PARAM(R9)(r1) /* segment size */
215 _GLOBAL(htab_call_hpte_insert2)
216 bl . /* Patched by htab_finish_init() */
218 bge+ htab_pte_insert_ok /* Insertion successful */
219 cmpdi 0,r3,-2 /* Critical failure */
220 beq- htab_pte_insert_failure
222 /* Both are full, we need to evict something */
224 /* Pick a random group based on TB */
230 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
231 /* Call ppc_md.hpte_remove */
232 _GLOBAL(htab_call_hpte_remove)
233 bl . /* Patched by htab_finish_init() */
243 /* Insert slot number & secondary bit in PTE */
244 rldimi r30,r3,12,63-15
246 /* Write out the PTE with a normal write
247 * (maybe add eieio may be good still ?)
250 ld r6,STK_PARAM(R6)(r1)
254 ld r27,STK_REG(R27)(r1)
255 ld r28,STK_REG(R28)(r1)
256 ld r29,STK_REG(R29)(r1)
257 ld r30,STK_REG(R30)(r1)
258 ld r31,STK_REG(R31)(r1)
259 addi r1,r1,STACKFRAMESIZE
265 /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
267 rlwinm r3,r31,32-12,29,31
269 /* Secondary group ? if yes, get a inverted hash value */
271 andi. r0,r31,_PAGE_SECONDARY
275 /* Calculate proper slot value for ppc_md.hpte_updatepp */
277 rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
278 add r3,r0,r3 /* add slot idx */
280 /* Call ppc_md.hpte_updatepp */
282 li r6,MMU_PAGE_4K /* page size */
283 ld r7,STK_PARAM(R9)(r1) /* segment size */
284 ld r8,STK_PARAM(R8)(r1) /* get "local" param */
285 _GLOBAL(htab_call_hpte_updatepp)
286 bl . /* Patched by htab_finish_init() */
288 /* if we failed because typically the HPTE wasn't really here
289 * we try an insertion.
294 /* Clear the BUSY bit and Write out the PTE */
300 /* Bail out clearing reservation */
305 htab_pte_insert_failure:
306 /* Bail out restoring old PTE */
307 ld r6,STK_PARAM(R6)(r1)
313 #else /* CONFIG_PPC_64K_PAGES */
316 /*****************************************************************************
318 * 64K SW & 4K or 64K HW in a 4K segment pages implementation *
320 *****************************************************************************/
322 /* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
323 * pte_t *ptep, unsigned long trap, int local, int ssize,
328 * For now, we do NOT implement Admixed pages
330 _GLOBAL(__hash_page_4K)
333 stdu r1,-STACKFRAMESIZE(r1)
334 /* Save all params that we need after a function call */
335 std r6,STK_PARAM(R6)(r1)
336 std r8,STK_PARAM(R8)(r1)
337 std r9,STK_PARAM(R9)(r1)
339 /* Save non-volatile registers.
340 * r31 will hold "old PTE"
343 * r28 is a hash value
344 * r27 is hashtab mask (maybe dynamic patched instead ?)
345 * r26 is the hidx mask
346 * r25 is the index in combo page
348 std r25,STK_REG(R25)(r1)
349 std r26,STK_REG(R26)(r1)
350 std r27,STK_REG(R27)(r1)
351 std r28,STK_REG(R28)(r1)
352 std r29,STK_REG(R29)(r1)
353 std r30,STK_REG(R30)(r1)
354 std r31,STK_REG(R31)(r1)
358 * Check permissions, atomically mark the linux PTE busy
363 /* Check access rights (access & ~(pte_val(*ptep))) */
365 bne- htab_wrong_access
366 /* Check if PTE is busy */
367 andi. r0,r31,_PAGE_BUSY
368 /* If so, just bail out and refault if needed. Someone else
369 * is changing this PTE anyway and might hash it.
372 /* Prepare new PTE value (turn access RW into DIRTY, then
373 * add BUSY and ACCESSED)
375 rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
377 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED
378 oris r30,r30,_PAGE_COMBO@h
379 /* Write the linux PTE atomically (setting busy) */
386 * Insert/Update the HPTE in the hash table. At this point,
387 * r4 (access) is re-useable, we use it for the new HPTE flags
390 /* Load the hidx index */
391 rldicl r25,r3,64-12,60
394 cmpdi r9,0 /* check segment size */
396 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
397 /* Calc va and put it in r29 */
398 rldicr r29,r5,28,63-28 /* r29 = (vsid << 28) */
399 rldicl r3,r3,0,36 /* r3 = (ea & 0x0fffffff) */
400 or r29,r3,r29 /* r29 = va */
402 /* Calculate hash value for primary slot and store it in r28 */
403 rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
404 rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */
408 3: /* Calc VA and hash in r29 and r28 for 1T segment */
409 sldi r29,r5,40 /* vsid << 40 */
410 clrldi r3,r3,24 /* ea & 0xffffffffff */
411 rldic r28,r5,25,25 /* (vsid << 25) & 0x7fffffffff */
412 clrldi r5,r5,40 /* vsid & 0xffffff */
413 rldicl r0,r3,64-12,36 /* (ea >> 12) & 0xfffffff */
415 or r29,r3,r29 /* VA */
416 xor r28,r28,r0 /* hash */
418 /* Convert linux PTE bits into HW equivalents */
420 #ifdef CONFIG_PPC_SUBPAGE_PROT
422 andi. r3,r10,0x1fe /* Get basic set of flags */
423 rlwinm r0,r10,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
425 andi. r3,r30,0x1fe /* Get basic set of flags */
426 rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
428 xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
429 rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
430 and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
431 andc r0,r3,r0 /* r0 = pte & ~r0 */
432 rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
433 ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */
435 /* We eventually do the icache sync here (maybe inline that
436 * code rather than call a C function...)
441 bl .hash_page_do_lazy_icache
442 END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
444 /* At this point, r3 contains new PP bits, save them in
445 * place of "access" in the param area (sic)
447 std r3,STK_PARAM(R4)(r1)
449 /* Get htab_hash_mask */
450 ld r4,htab_hash_mask@got(2)
451 ld r27,0(r4) /* htab_hash_mask -> r27 */
453 /* Check if we may already be in the hashtable, in this case, we
454 * go to out-of-line code to try to modify the HPTE. We look for
455 * the bit at (1 >> (index + 32))
457 rldicl. r0,r31,64-12,48
458 li r26,0 /* Default hidx */
462 * Check if the pte was already inserted into the hash table
463 * as a 64k HW page, and invalidate the 64k HPTE if so.
465 andis. r0,r31,_PAGE_COMBO@h
466 beq htab_inval_old_hpte
468 ld r6,STK_PARAM(R6)(r1)
469 ori r26,r6,0x8000 /* Load the hidx mask */
471 addi r5,r25,36 /* Check actual HPTE_SUB bit, this */
472 rldcr. r0,r31,r5,0 /* must match pgtable.h definition */
476 /* real page number in r5, PTE RPN value + index */
477 andis. r0,r31,_PAGE_4K_PFN@h
478 srdi r5,r31,PTE_RPN_SHIFT
479 bne- htab_special_pfn
480 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
483 sldi r5,r5,HW_PAGE_SHIFT
485 /* Calculate primary group hash */
487 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
489 /* Call ppc_md.hpte_insert */
490 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
491 mr r4,r29 /* Retrieve va */
492 li r7,0 /* !bolted, !secondary */
493 li r8,MMU_PAGE_4K /* page size */
494 ld r9,STK_PARAM(R9)(r1) /* segment size */
495 _GLOBAL(htab_call_hpte_insert1)
496 bl . /* patched by htab_finish_init() */
498 bge htab_pte_insert_ok /* Insertion successful */
499 cmpdi 0,r3,-2 /* Critical failure */
500 beq- htab_pte_insert_failure
502 /* Now try secondary slot */
504 /* real page number in r5, PTE RPN value + index */
505 andis. r0,r31,_PAGE_4K_PFN@h
506 srdi r5,r31,PTE_RPN_SHIFT
508 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
510 3: sldi r5,r5,HW_PAGE_SHIFT
512 /* Calculate secondary group hash */
514 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
516 /* Call ppc_md.hpte_insert */
517 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
518 mr r4,r29 /* Retrieve va */
519 li r7,HPTE_V_SECONDARY /* !bolted, secondary */
520 li r8,MMU_PAGE_4K /* page size */
521 ld r9,STK_PARAM(R9)(r1) /* segment size */
522 _GLOBAL(htab_call_hpte_insert2)
523 bl . /* patched by htab_finish_init() */
525 bge+ htab_pte_insert_ok /* Insertion successful */
526 cmpdi 0,r3,-2 /* Critical failure */
527 beq- htab_pte_insert_failure
529 /* Both are full, we need to evict something */
531 /* Pick a random group based on TB */
537 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
538 /* Call ppc_md.hpte_remove */
539 _GLOBAL(htab_call_hpte_remove)
540 bl . /* patched by htab_finish_init() */
546 * Call out to C code to invalidate an 64k HW HPTE that is
547 * useless now that the segment has been switched to 4k pages.
550 mr r3,r29 /* virtual addr */
551 mr r4,r31 /* PTE.pte */
552 li r5,0 /* PTE.hidx */
553 li r6,MMU_PAGE_64K /* psize */
554 ld r7,STK_PARAM(R9)(r1) /* ssize */
555 ld r8,STK_PARAM(R8)(r1) /* local */
557 /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */
558 lis r0,_PAGE_HPTE_SUB@h
559 ori r0,r0,_PAGE_HPTE_SUB@l
568 /* Insert slot number & secondary bit in PTE second half,
569 * clear _PAGE_BUSY and set approriate HPTE slot bit
571 ld r6,STK_PARAM(R6)(r1)
576 subfic r5,r25,27 /* Must match bit position in */
577 sld r0,r0,r5 /* pgtable.h */
592 ld r25,STK_REG(R25)(r1)
593 ld r26,STK_REG(R26)(r1)
594 ld r27,STK_REG(R27)(r1)
595 ld r28,STK_REG(R28)(r1)
596 ld r29,STK_REG(R29)(r1)
597 ld r30,STK_REG(R30)(r1)
598 ld r31,STK_REG(R31)(r1)
599 addi r1,r1,STACKFRAMESIZE
605 /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
610 /* Secondary group ? if yes, get a inverted hash value */
612 andi. r0,r3,0x8 /* page secondary ? */
615 1: andi. r3,r3,0x7 /* extract idx alone */
617 /* Calculate proper slot value for ppc_md.hpte_updatepp */
619 rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
620 add r3,r0,r3 /* add slot idx */
622 /* Call ppc_md.hpte_updatepp */
624 li r6,MMU_PAGE_4K /* page size */
625 ld r7,STK_PARAM(R9)(r1) /* segment size */
626 ld r8,STK_PARAM(R8)(r1) /* get "local" param */
627 _GLOBAL(htab_call_hpte_updatepp)
628 bl . /* patched by htab_finish_init() */
630 /* if we failed because typically the HPTE wasn't really here
631 * we try an insertion.
636 /* Clear the BUSY bit and Write out the PTE */
639 ld r6,STK_PARAM(R6)(r1)
645 /* Bail out clearing reservation */
650 htab_pte_insert_failure:
651 /* Bail out restoring old PTE */
652 ld r6,STK_PARAM(R6)(r1)
657 #endif /* CONFIG_PPC_64K_PAGES */
659 #ifdef CONFIG_PPC_HAS_HASH_64K
661 /*****************************************************************************
663 * 64K SW & 64K HW in a 64K segment pages implementation *
665 *****************************************************************************/
667 _GLOBAL(__hash_page_64K)
670 stdu r1,-STACKFRAMESIZE(r1)
671 /* Save all params that we need after a function call */
672 std r6,STK_PARAM(R6)(r1)
673 std r8,STK_PARAM(R8)(r1)
674 std r9,STK_PARAM(R9)(r1)
676 /* Save non-volatile registers.
677 * r31 will hold "old PTE"
680 * r28 is a hash value
681 * r27 is hashtab mask (maybe dynamic patched instead ?)
683 std r27,STK_REG(R27)(r1)
684 std r28,STK_REG(R28)(r1)
685 std r29,STK_REG(R29)(r1)
686 std r30,STK_REG(R30)(r1)
687 std r31,STK_REG(R31)(r1)
691 * Check permissions, atomically mark the linux PTE busy
696 /* Check access rights (access & ~(pte_val(*ptep))) */
698 bne- ht64_wrong_access
699 /* Check if PTE is busy */
700 andi. r0,r31,_PAGE_BUSY
701 /* If so, just bail out and refault if needed. Someone else
702 * is changing this PTE anyway and might hash it.
706 /* Check if PTE has the cache-inhibit bit set */
707 andi. r0,r31,_PAGE_NO_CACHE
708 /* If so, bail out and refault as a 4k page */
710 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_CI_LARGE_PAGE)
711 /* Prepare new PTE value (turn access RW into DIRTY, then
712 * add BUSY and ACCESSED)
714 rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
716 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED
717 /* Write the linux PTE atomically (setting busy) */
724 * Insert/Update the HPTE in the hash table. At this point,
725 * r4 (access) is re-useable, we use it for the new HPTE flags
729 cmpdi r9,0 /* check segment size */
731 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
732 /* Calc va and put it in r29 */
733 rldicr r29,r5,28,63-28
737 /* Calculate hash value for primary slot and store it in r28 */
738 rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
739 rldicl r0,r3,64-16,52 /* (ea >> 16) & 0xfff */
743 3: /* Calc VA and hash in r29 and r28 for 1T segment */
744 sldi r29,r5,40 /* vsid << 40 */
745 clrldi r3,r3,24 /* ea & 0xffffffffff */
746 rldic r28,r5,25,25 /* (vsid << 25) & 0x7fffffffff */
747 clrldi r5,r5,40 /* vsid & 0xffffff */
748 rldicl r0,r3,64-16,40 /* (ea >> 16) & 0xffffff */
750 or r29,r3,r29 /* VA */
751 xor r28,r28,r0 /* hash */
753 /* Convert linux PTE bits into HW equivalents */
754 4: andi. r3,r30,0x1fe /* Get basic set of flags */
755 xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
756 rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
757 rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
758 and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
759 andc r0,r30,r0 /* r0 = pte & ~r0 */
760 rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
761 ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */
763 /* We eventually do the icache sync here (maybe inline that
764 * code rather than call a C function...)
769 bl .hash_page_do_lazy_icache
770 END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
772 /* At this point, r3 contains new PP bits, save them in
773 * place of "access" in the param area (sic)
775 std r3,STK_PARAM(R4)(r1)
777 /* Get htab_hash_mask */
778 ld r4,htab_hash_mask@got(2)
779 ld r27,0(r4) /* htab_hash_mask -> r27 */
781 /* Check if we may already be in the hashtable, in this case, we
782 * go to out-of-line code to try to modify the HPTE
784 rldicl. r0,r31,64-12,48
788 /* Clear hpte bits in new pte (we also clear BUSY btw) and
789 * add _PAGE_HPTE_SUB0
791 lis r0,_PAGE_HPTEFLAGS@h
792 ori r0,r0,_PAGE_HPTEFLAGS@l
794 #ifdef CONFIG_PPC_64K_PAGES
795 oris r30,r30,_PAGE_HPTE_SUB0@h
797 ori r30,r30,_PAGE_HASHPTE
799 /* Phyical address in r5 */
800 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
801 sldi r5,r5,PAGE_SHIFT
803 /* Calculate primary group hash */
805 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
807 /* Call ppc_md.hpte_insert */
808 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
809 mr r4,r29 /* Retrieve va */
810 li r7,0 /* !bolted, !secondary */
812 ld r9,STK_PARAM(R9)(r1) /* segment size */
813 _GLOBAL(ht64_call_hpte_insert1)
814 bl . /* patched by htab_finish_init() */
816 bge ht64_pte_insert_ok /* Insertion successful */
817 cmpdi 0,r3,-2 /* Critical failure */
818 beq- ht64_pte_insert_failure
820 /* Now try secondary slot */
822 /* Phyical address in r5 */
823 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
824 sldi r5,r5,PAGE_SHIFT
826 /* Calculate secondary group hash */
828 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
830 /* Call ppc_md.hpte_insert */
831 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
832 mr r4,r29 /* Retrieve va */
833 li r7,HPTE_V_SECONDARY /* !bolted, secondary */
835 ld r9,STK_PARAM(R9)(r1) /* segment size */
836 _GLOBAL(ht64_call_hpte_insert2)
837 bl . /* patched by htab_finish_init() */
839 bge+ ht64_pte_insert_ok /* Insertion successful */
840 cmpdi 0,r3,-2 /* Critical failure */
841 beq- ht64_pte_insert_failure
843 /* Both are full, we need to evict something */
845 /* Pick a random group based on TB */
851 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
852 /* Call ppc_md.hpte_remove */
853 _GLOBAL(ht64_call_hpte_remove)
854 bl . /* patched by htab_finish_init() */
864 /* Insert slot number & secondary bit in PTE */
865 rldimi r30,r3,12,63-15
867 /* Write out the PTE with a normal write
868 * (maybe add eieio may be good still ?)
871 ld r6,STK_PARAM(R6)(r1)
875 ld r27,STK_REG(R27)(r1)
876 ld r28,STK_REG(R28)(r1)
877 ld r29,STK_REG(R29)(r1)
878 ld r30,STK_REG(R30)(r1)
879 ld r31,STK_REG(R31)(r1)
880 addi r1,r1,STACKFRAMESIZE
886 /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
888 rlwinm r3,r31,32-12,29,31
890 /* Secondary group ? if yes, get a inverted hash value */
892 andi. r0,r31,_PAGE_F_SECOND
896 /* Calculate proper slot value for ppc_md.hpte_updatepp */
898 rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
899 add r3,r0,r3 /* add slot idx */
901 /* Call ppc_md.hpte_updatepp */
904 ld r7,STK_PARAM(R9)(r1) /* segment size */
905 ld r8,STK_PARAM(R8)(r1) /* get "local" param */
906 _GLOBAL(ht64_call_hpte_updatepp)
907 bl . /* patched by htab_finish_init() */
909 /* if we failed because typically the HPTE wasn't really here
910 * we try an insertion.
915 /* Clear the BUSY bit and Write out the PTE */
921 /* Bail out clearing reservation */
926 ht64_pte_insert_failure:
927 /* Bail out restoring old PTE */
928 ld r6,STK_PARAM(R6)(r1)
934 #endif /* CONFIG_PPC_HAS_HASH_64K */
937 /*****************************************************************************
939 * Huge pages implementation is in hugetlbpage.c *
941 *****************************************************************************/