blob: 7443481a315c4922063a5f8801c62ee9bfb7691f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ppc64 MMU hashtable management routines
3 *
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +11004 * (c) Copyright IBM Corp. 2003, 2005
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
6 * Maintained by: Benjamin Herrenschmidt
7 * <benh@kernel.crashing.org>
8 *
9 * This file is covered by the GNU Public Licence v2 as
10 * described in the kernel's COPYING file.
11 */
12
Paul Mackerrasab1f9da2005-10-10 21:58:35 +100013#include <asm/reg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <asm/pgtable.h>
15#include <asm/mmu.h>
16#include <asm/page.h>
17#include <asm/types.h>
18#include <asm/ppc_asm.h>
Sam Ravnborg0013a852005-09-09 20:57:26 +020019#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <asm/cputable.h>
21
22 .text
23
24/*
25 * Stackframe:
26 *
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)
36 */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110037
38#ifndef CONFIG_PPC_64K_PAGES
39
40/*****************************************************************************
41 * *
42 * 4K SW & 4K HW pages implementation *
43 * *
44 *****************************************************************************/
45
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047/*
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110048 * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
Paul Mackerras1189be62007-10-11 20:37:10 +100049 * pte_t *ptep, unsigned long trap, int local, int ssize)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 *
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110051 * Adds a 4K page to the hash table in a segment of 4K pages only
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 */
53
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110054_GLOBAL(__hash_page_4K)
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 mflr r0
56 std r0,16(r1)
57 stdu r1,-STACKFRAMESIZE(r1)
58 /* Save all params that we need after a function call */
Michael Neuling44ce6a52012-06-25 13:33:14 +000059 std r6,STK_PARAM(R6)(r1)
60 std r8,STK_PARAM(R8)(r1)
61 std r9,STK_PARAM(R9)(r1)
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 /* Save non-volatile registers.
64 * r31 will hold "old PTE"
65 * r30 is "new PTE"
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +000066 * r29 is vpn
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 * r28 is a hash value
68 * r27 is hashtab mask (maybe dynamic patched instead ?)
69 */
Michael Neulingc75df6f2012-06-25 13:33:10 +000070 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)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76 /* Step 1:
77 *
78 * Check permissions, atomically mark the linux PTE busy
79 * and hashed.
80 */
811:
82 ldarx r31,0,r6
83 /* Check access rights (access & ~(pte_val(*ptep))) */
84 andc. r0,r4,r31
85 bne- htab_wrong_access
86 /* Check if PTE is busy */
87 andi. r0,r31,_PAGE_BUSY
Olof Johanssond03853d2005-05-01 08:58:45 -070088 /* If so, just bail out and refault if needed. Someone else
89 * is changing this PTE anyway and might hash it.
90 */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +110091 bne- htab_bail_ok
92
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 /* Prepare new PTE value (turn access RW into DIRTY, then
94 * add BUSY,HASHPTE and ACCESSED)
95 */
96 rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
97 or r30,r30,r31
98 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
99 /* Write the linux PTE atomically (setting busy) */
100 stdcx. r30,0,r6
101 bne- 1b
102 isync
103
104 /* Step 2:
105 *
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
108 */
109
Paul Mackerras1189be62007-10-11 20:37:10 +1000110BEGIN_FTR_SECTION
111 cmpdi r9,0 /* check segment size */
112 bne 3f
Matt Evans44ae3ab2011-04-06 19:48:50 +0000113END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000114 /* Calc vpn and put it in r29 */
115 sldi r29,r5,SID_SHIFT - VPN_SHIFT
116 rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
117 or r29,r28,r29
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000118 /*
119 * Calculate hash value for primary slot and store it in r28
120 * r3 = va, r5 = vsid
121 * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
122 */
123 rldicl r0,r3,64-12,48
124 xor r28,r5,r0 /* hash */
Paul Mackerras1189be62007-10-11 20:37:10 +1000125 b 4f
126
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +00001273: /* Calc vpn and put it in r29 */
128 sldi r29,r5,SID_SHIFT_1T - VPN_SHIFT
129 rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
130 or r29,r28,r29
131
132 /*
133 * calculate hash value for primary slot and
134 * store it in r28 for 1T segment
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000135 * r3 = va, r5 = vsid
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000136 */
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000137 sldi r28,r5,25 /* vsid << 25 */
138 /* r0 = (va >> 12) & ((1ul << (40 - 12)) -1) */
139 rldicl r0,r3,64-12,36
140 xor r28,r28,r5 /* vsid ^ ( vsid << 25) */
Paul Mackerras1189be62007-10-11 20:37:10 +1000141 xor r28,r28,r0 /* hash */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143 /* Convert linux PTE bits into HW equivalents */
Paul Mackerras1189be62007-10-11 20:37:10 +10001444: andi. r3,r30,0x1fe /* Get basic set of flags */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100145 xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
147 rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100148 and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 andc r0,r30,r0 /* r0 = pte & ~r0 */
150 rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
Benjamin Herrenschmidtc5cf0e32006-05-30 14:14:19 +1000151 ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
153 /* We eventually do the icache sync here (maybe inline that
154 * code rather than call a C function...)
155 */
156BEGIN_FTR_SECTION
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 mr r4,r30
158 mr r5,r7
159 bl .hash_page_do_lazy_icache
David Gibson8913ca12005-07-27 15:47:23 +1000160END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
162 /* At this point, r3 contains new PP bits, save them in
163 * place of "access" in the param area (sic)
164 */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000165 std r3,STK_PARAM(R4)(r1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167 /* Get htab_hash_mask */
168 ld r4,htab_hash_mask@got(2)
169 ld r27,0(r4) /* htab_hash_mask -> r27 */
170
171 /* Check if we may already be in the hashtable, in this case, we
172 * go to out-of-line code to try to modify the HPTE
173 */
174 andi. r0,r31,_PAGE_HASHPTE
175 bne htab_modify_pte
176
177htab_insert_pte:
178 /* Clear hpte bits in new pte (we also clear BUSY btw) and
179 * add _PAGE_HASHPTE
180 */
181 lis r0,_PAGE_HPTEFLAGS@h
182 ori r0,r0,_PAGE_HPTEFLAGS@l
183 andc r30,r30,r0
184 ori r30,r30,_PAGE_HASHPTE
185
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100186 /* physical address r5 */
187 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
188 sldi r5,r5,PAGE_SHIFT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /* Calculate primary group hash */
191 and r0,r28,r27
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100192 rldicr r3,r0,3,63-3 /* r3 = (hash & mask) << 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193
194 /* Call ppc_md.hpte_insert */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000195 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000196 mr r4,r29 /* Retrieve vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100197 li r7,0 /* !bolted, !secondary */
198 li r8,MMU_PAGE_4K /* page size */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000199 ld r9,STK_PARAM(R9)(r1) /* segment size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200_GLOBAL(htab_call_hpte_insert1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100201 bl . /* Patched by htab_finish_init() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 cmpdi 0,r3,0
203 bge htab_pte_insert_ok /* Insertion successful */
204 cmpdi 0,r3,-2 /* Critical failure */
205 beq- htab_pte_insert_failure
206
207 /* Now try secondary slot */
208
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100209 /* physical address r5 */
210 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
211 sldi r5,r5,PAGE_SHIFT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213 /* Calculate secondary group hash */
214 andc r0,r27,r28
215 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
216
217 /* Call ppc_md.hpte_insert */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000218 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000219 mr r4,r29 /* Retrieve vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100220 li r7,HPTE_V_SECONDARY /* !bolted, secondary */
221 li r8,MMU_PAGE_4K /* page size */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000222 ld r9,STK_PARAM(R9)(r1) /* segment size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223_GLOBAL(htab_call_hpte_insert2)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100224 bl . /* Patched by htab_finish_init() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 cmpdi 0,r3,0
226 bge+ htab_pte_insert_ok /* Insertion successful */
227 cmpdi 0,r3,-2 /* Critical failure */
228 beq- htab_pte_insert_failure
229
230 /* Both are full, we need to evict something */
231 mftb r0
232 /* Pick a random group based on TB */
233 andi. r0,r0,1
234 mr r5,r28
235 bne 2f
236 not r5,r5
2372: and r0,r5,r27
238 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
239 /* Call ppc_md.hpte_remove */
240_GLOBAL(htab_call_hpte_remove)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100241 bl . /* Patched by htab_finish_init() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
243 /* Try all again */
244 b htab_insert_pte
245
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100246htab_bail_ok:
Olof Johanssond03853d2005-05-01 08:58:45 -0700247 li r3,0
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100248 b htab_bail
Olof Johanssond03853d2005-05-01 08:58:45 -0700249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250htab_pte_insert_ok:
251 /* Insert slot number & secondary bit in PTE */
252 rldimi r30,r3,12,63-15
253
254 /* Write out the PTE with a normal write
255 * (maybe add eieio may be good still ?)
256 */
257htab_write_out_pte:
Michael Neuling44ce6a52012-06-25 13:33:14 +0000258 ld r6,STK_PARAM(R6)(r1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 std r30,0(r6)
260 li r3, 0
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100261htab_bail:
Michael Neulingc75df6f2012-06-25 13:33:10 +0000262 ld r27,STK_REG(R27)(r1)
263 ld r28,STK_REG(R28)(r1)
264 ld r29,STK_REG(R29)(r1)
265 ld r30,STK_REG(R30)(r1)
266 ld r31,STK_REG(R31)(r1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 addi r1,r1,STACKFRAMESIZE
268 ld r0,16(r1)
269 mtlr r0
270 blr
271
272htab_modify_pte:
273 /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
274 mr r4,r3
275 rlwinm r3,r31,32-12,29,31
276
277 /* Secondary group ? if yes, get a inverted hash value */
278 mr r5,r28
279 andi. r0,r31,_PAGE_SECONDARY
280 beq 1f
281 not r5,r5
2821:
283 /* Calculate proper slot value for ppc_md.hpte_updatepp */
284 and r0,r5,r27
285 rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
286 add r3,r0,r3 /* add slot idx */
287
288 /* Call ppc_md.hpte_updatepp */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000289 mr r5,r29 /* vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100290 li r6,MMU_PAGE_4K /* page size */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000291 ld r7,STK_PARAM(R9)(r1) /* segment size */
292 ld r8,STK_PARAM(R8)(r1) /* get "local" param */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293_GLOBAL(htab_call_hpte_updatepp)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100294 bl . /* Patched by htab_finish_init() */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295
296 /* if we failed because typically the HPTE wasn't really here
297 * we try an insertion.
298 */
299 cmpdi 0,r3,-1
300 beq- htab_insert_pte
301
302 /* Clear the BUSY bit and Write out the PTE */
303 li r0,_PAGE_BUSY
304 andc r30,r30,r0
305 b htab_write_out_pte
306
307htab_wrong_access:
308 /* Bail out clearing reservation */
309 stdcx. r31,0,r6
310 li r3,1
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100311 b htab_bail
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
313htab_pte_insert_failure:
314 /* Bail out restoring old PTE */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000315 ld r6,STK_PARAM(R6)(r1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 std r31,0(r6)
317 li r3,-1
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100318 b htab_bail
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100321#else /* CONFIG_PPC_64K_PAGES */
322
323
324/*****************************************************************************
325 * *
326 * 64K SW & 4K or 64K HW in a 4K segment pages implementation *
327 * *
328 *****************************************************************************/
329
330/* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
Paul Mackerrasfa282372008-01-24 08:35:13 +1100331 * pte_t *ptep, unsigned long trap, int local, int ssize,
332 * int subpg_prot)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100333 */
334
335/*
336 * For now, we do NOT implement Admixed pages
337 */
338_GLOBAL(__hash_page_4K)
339 mflr r0
340 std r0,16(r1)
341 stdu r1,-STACKFRAMESIZE(r1)
342 /* Save all params that we need after a function call */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000343 std r6,STK_PARAM(R6)(r1)
344 std r8,STK_PARAM(R8)(r1)
345 std r9,STK_PARAM(R9)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100346
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100347 /* Save non-volatile registers.
348 * r31 will hold "old PTE"
349 * r30 is "new PTE"
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000350 * r29 is vpn
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100351 * r28 is a hash value
352 * r27 is hashtab mask (maybe dynamic patched instead ?)
353 * r26 is the hidx mask
354 * r25 is the index in combo page
355 */
Michael Neulingc75df6f2012-06-25 13:33:10 +0000356 std r25,STK_REG(R25)(r1)
357 std r26,STK_REG(R26)(r1)
358 std r27,STK_REG(R27)(r1)
359 std r28,STK_REG(R28)(r1)
360 std r29,STK_REG(R29)(r1)
361 std r30,STK_REG(R30)(r1)
362 std r31,STK_REG(R31)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100363
364 /* Step 1:
365 *
366 * Check permissions, atomically mark the linux PTE busy
367 * and hashed.
368 */
3691:
370 ldarx r31,0,r6
371 /* Check access rights (access & ~(pte_val(*ptep))) */
372 andc. r0,r4,r31
373 bne- htab_wrong_access
374 /* Check if PTE is busy */
375 andi. r0,r31,_PAGE_BUSY
376 /* If so, just bail out and refault if needed. Someone else
377 * is changing this PTE anyway and might hash it.
378 */
379 bne- htab_bail_ok
380 /* Prepare new PTE value (turn access RW into DIRTY, then
381 * add BUSY and ACCESSED)
382 */
383 rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
384 or r30,r30,r31
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000385 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED
Paul Mackerrasbf72aeb2006-06-15 10:45:18 +1000386 oris r30,r30,_PAGE_COMBO@h
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100387 /* Write the linux PTE atomically (setting busy) */
388 stdcx. r30,0,r6
389 bne- 1b
390 isync
391
392 /* Step 2:
393 *
394 * Insert/Update the HPTE in the hash table. At this point,
395 * r4 (access) is re-useable, we use it for the new HPTE flags
396 */
397
398 /* Load the hidx index */
399 rldicl r25,r3,64-12,60
400
Paul Mackerras1189be62007-10-11 20:37:10 +1000401BEGIN_FTR_SECTION
402 cmpdi r9,0 /* check segment size */
403 bne 3f
Matt Evans44ae3ab2011-04-06 19:48:50 +0000404END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000405 /* Calc vpn and put it in r29 */
406 sldi r29,r5,SID_SHIFT - VPN_SHIFT
407 /*
408 * clrldi r3,r3,64 - SID_SHIFT --> ea & 0xfffffff
409 * srdi r28,r3,VPN_SHIFT
410 */
411 rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
412 or r29,r28,r29
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000413 /*
414 * Calculate hash value for primary slot and store it in r28
415 * r3 = va, r5 = vsid
416 * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
417 */
418 rldicl r0,r3,64-12,48
419 xor r28,r5,r0 /* hash */
Paul Mackerras1189be62007-10-11 20:37:10 +1000420 b 4f
421
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +00004223: /* Calc vpn and put it in r29 */
423 sldi r29,r5,SID_SHIFT_1T - VPN_SHIFT
424 /*
425 * clrldi r3,r3,64 - SID_SHIFT_1T --> ea & 0xffffffffff
426 * srdi r28,r3,VPN_SHIFT
427 */
428 rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
429 or r29,r28,r29
430
431 /*
432 * Calculate hash value for primary slot and
433 * store it in r28 for 1T segment
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000434 * r3 = va, r5 = vsid
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000435 */
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000436 sldi r28,r5,25 /* vsid << 25 */
437 /* r0 = (va >> 12) & ((1ul << (40 - 12)) -1) */
438 rldicl r0,r3,64-12,36
439 xor r28,r28,r5 /* vsid ^ ( vsid << 25) */
Paul Mackerras1189be62007-10-11 20:37:10 +1000440 xor r28,r28,r0 /* hash */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100441
442 /* Convert linux PTE bits into HW equivalents */
Paul Mackerrasfa282372008-01-24 08:35:13 +11004434:
444#ifdef CONFIG_PPC_SUBPAGE_PROT
445 andc r10,r30,r10
446 andi. r3,r10,0x1fe /* Get basic set of flags */
447 rlwinm r0,r10,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
448#else
449 andi. r3,r30,0x1fe /* Get basic set of flags */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100450 rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
Paul Mackerrasfa282372008-01-24 08:35:13 +1100451#endif
452 xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100453 rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
454 and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
Paul Mackerrasfa282372008-01-24 08:35:13 +1100455 andc r0,r3,r0 /* r0 = pte & ~r0 */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100456 rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
Benjamin Herrenschmidtc5cf0e32006-05-30 14:14:19 +1000457 ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100458
459 /* We eventually do the icache sync here (maybe inline that
460 * code rather than call a C function...)
461 */
462BEGIN_FTR_SECTION
463 mr r4,r30
464 mr r5,r7
465 bl .hash_page_do_lazy_icache
466END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
467
468 /* At this point, r3 contains new PP bits, save them in
469 * place of "access" in the param area (sic)
470 */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000471 std r3,STK_PARAM(R4)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100472
473 /* Get htab_hash_mask */
474 ld r4,htab_hash_mask@got(2)
475 ld r27,0(r4) /* htab_hash_mask -> r27 */
476
477 /* Check if we may already be in the hashtable, in this case, we
478 * go to out-of-line code to try to modify the HPTE. We look for
479 * the bit at (1 >> (index + 32))
480 */
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000481 rldicl. r0,r31,64-12,48
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100482 li r26,0 /* Default hidx */
483 beq htab_insert_pte
Paul Mackerrasbf72aeb2006-06-15 10:45:18 +1000484
485 /*
486 * Check if the pte was already inserted into the hash table
487 * as a 64k HW page, and invalidate the 64k HPTE if so.
488 */
489 andis. r0,r31,_PAGE_COMBO@h
490 beq htab_inval_old_hpte
491
Michael Neuling44ce6a52012-06-25 13:33:14 +0000492 ld r6,STK_PARAM(R6)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100493 ori r26,r6,0x8000 /* Load the hidx mask */
494 ld r26,0(r26)
495 addi r5,r25,36 /* Check actual HPTE_SUB bit, this */
496 rldcr. r0,r31,r5,0 /* must match pgtable.h definition */
497 bne htab_modify_pte
498
499htab_insert_pte:
500 /* real page number in r5, PTE RPN value + index */
Paul Mackerras721151d2007-04-03 21:24:02 +1000501 andis. r0,r31,_PAGE_4K_PFN@h
502 srdi r5,r31,PTE_RPN_SHIFT
503 bne- htab_special_pfn
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100504 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
505 add r5,r5,r25
Paul Mackerras721151d2007-04-03 21:24:02 +1000506htab_special_pfn:
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100507 sldi r5,r5,HW_PAGE_SHIFT
508
509 /* Calculate primary group hash */
510 and r0,r28,r27
511 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
512
513 /* Call ppc_md.hpte_insert */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000514 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000515 mr r4,r29 /* Retrieve vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100516 li r7,0 /* !bolted, !secondary */
517 li r8,MMU_PAGE_4K /* page size */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000518 ld r9,STK_PARAM(R9)(r1) /* segment size */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100519_GLOBAL(htab_call_hpte_insert1)
520 bl . /* patched by htab_finish_init() */
521 cmpdi 0,r3,0
522 bge htab_pte_insert_ok /* Insertion successful */
523 cmpdi 0,r3,-2 /* Critical failure */
524 beq- htab_pte_insert_failure
525
526 /* Now try secondary slot */
527
528 /* real page number in r5, PTE RPN value + index */
Paul Mackerras430404e2007-08-03 19:16:11 +1000529 andis. r0,r31,_PAGE_4K_PFN@h
530 srdi r5,r31,PTE_RPN_SHIFT
531 bne- 3f
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100532 sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
533 add r5,r5,r25
Paul Mackerras430404e2007-08-03 19:16:11 +10005343: sldi r5,r5,HW_PAGE_SHIFT
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100535
536 /* Calculate secondary group hash */
537 andc r0,r27,r28
538 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
539
540 /* Call ppc_md.hpte_insert */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000541 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000542 mr r4,r29 /* Retrieve vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100543 li r7,HPTE_V_SECONDARY /* !bolted, secondary */
544 li r8,MMU_PAGE_4K /* page size */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000545 ld r9,STK_PARAM(R9)(r1) /* segment size */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100546_GLOBAL(htab_call_hpte_insert2)
547 bl . /* patched by htab_finish_init() */
548 cmpdi 0,r3,0
549 bge+ htab_pte_insert_ok /* Insertion successful */
550 cmpdi 0,r3,-2 /* Critical failure */
551 beq- htab_pte_insert_failure
552
553 /* Both are full, we need to evict something */
554 mftb r0
555 /* Pick a random group based on TB */
556 andi. r0,r0,1
557 mr r5,r28
558 bne 2f
559 not r5,r5
5602: and r0,r5,r27
561 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
562 /* Call ppc_md.hpte_remove */
563_GLOBAL(htab_call_hpte_remove)
564 bl . /* patched by htab_finish_init() */
565
566 /* Try all again */
567 b htab_insert_pte
568
Paul Mackerrasbf72aeb2006-06-15 10:45:18 +1000569 /*
570 * Call out to C code to invalidate an 64k HW HPTE that is
571 * useless now that the segment has been switched to 4k pages.
572 */
573htab_inval_old_hpte:
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000574 mr r3,r29 /* vpn */
Paul Mackerrasbf72aeb2006-06-15 10:45:18 +1000575 mr r4,r31 /* PTE.pte */
576 li r5,0 /* PTE.hidx */
577 li r6,MMU_PAGE_64K /* psize */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000578 ld r7,STK_PARAM(R9)(r1) /* ssize */
579 ld r8,STK_PARAM(R8)(r1) /* local */
Paul Mackerrasbf72aeb2006-06-15 10:45:18 +1000580 bl .flush_hash_page
Paul Mackerras65ba6cd2008-06-18 16:40:35 +1000581 /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */
582 lis r0,_PAGE_HPTE_SUB@h
583 ori r0,r0,_PAGE_HPTE_SUB@l
584 andc r30,r30,r0
Paul Mackerrasbf72aeb2006-06-15 10:45:18 +1000585 b htab_insert_pte
586
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100587htab_bail_ok:
588 li r3,0
589 b htab_bail
590
591htab_pte_insert_ok:
592 /* Insert slot number & secondary bit in PTE second half,
593 * clear _PAGE_BUSY and set approriate HPTE slot bit
594 */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000595 ld r6,STK_PARAM(R6)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100596 li r0,_PAGE_BUSY
597 andc r30,r30,r0
598 /* HPTE SUB bit */
599 li r0,1
600 subfic r5,r25,27 /* Must match bit position in */
601 sld r0,r0,r5 /* pgtable.h */
602 or r30,r30,r0
603 /* hindx */
604 sldi r5,r25,2
605 sld r3,r3,r5
606 li r4,0xf
607 sld r4,r4,r5
608 andc r26,r26,r4
609 or r26,r26,r3
610 ori r5,r6,0x8000
611 std r26,0(r5)
612 lwsync
613 std r30,0(r6)
614 li r3, 0
615htab_bail:
Michael Neulingc75df6f2012-06-25 13:33:10 +0000616 ld r25,STK_REG(R25)(r1)
617 ld r26,STK_REG(R26)(r1)
618 ld r27,STK_REG(R27)(r1)
619 ld r28,STK_REG(R28)(r1)
620 ld r29,STK_REG(R29)(r1)
621 ld r30,STK_REG(R30)(r1)
622 ld r31,STK_REG(R31)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100623 addi r1,r1,STACKFRAMESIZE
624 ld r0,16(r1)
625 mtlr r0
626 blr
627
628htab_modify_pte:
629 /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
630 mr r4,r3
631 sldi r5,r25,2
632 srd r3,r26,r5
633
634 /* Secondary group ? if yes, get a inverted hash value */
635 mr r5,r28
636 andi. r0,r3,0x8 /* page secondary ? */
637 beq 1f
638 not r5,r5
6391: andi. r3,r3,0x7 /* extract idx alone */
640
641 /* Calculate proper slot value for ppc_md.hpte_updatepp */
642 and r0,r5,r27
643 rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
644 add r3,r0,r3 /* add slot idx */
645
646 /* Call ppc_md.hpte_updatepp */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000647 mr r5,r29 /* vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100648 li r6,MMU_PAGE_4K /* page size */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000649 ld r7,STK_PARAM(R9)(r1) /* segment size */
650 ld r8,STK_PARAM(R8)(r1) /* get "local" param */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100651_GLOBAL(htab_call_hpte_updatepp)
652 bl . /* patched by htab_finish_init() */
653
654 /* if we failed because typically the HPTE wasn't really here
655 * we try an insertion.
656 */
657 cmpdi 0,r3,-1
658 beq- htab_insert_pte
659
660 /* Clear the BUSY bit and Write out the PTE */
661 li r0,_PAGE_BUSY
662 andc r30,r30,r0
Michael Neuling44ce6a52012-06-25 13:33:14 +0000663 ld r6,STK_PARAM(R6)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100664 std r30,0(r6)
665 li r3,0
666 b htab_bail
667
668htab_wrong_access:
669 /* Bail out clearing reservation */
670 stdcx. r31,0,r6
671 li r3,1
672 b htab_bail
673
674htab_pte_insert_failure:
675 /* Bail out restoring old PTE */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000676 ld r6,STK_PARAM(R6)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100677 std r31,0(r6)
678 li r3,-1
679 b htab_bail
680
Benjamin Herrenschmidt16c2d472007-05-08 16:27:28 +1000681#endif /* CONFIG_PPC_64K_PAGES */
682
683#ifdef CONFIG_PPC_HAS_HASH_64K
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100684
685/*****************************************************************************
686 * *
687 * 64K SW & 64K HW in a 64K segment pages implementation *
688 * *
689 *****************************************************************************/
690
691_GLOBAL(__hash_page_64K)
692 mflr r0
693 std r0,16(r1)
694 stdu r1,-STACKFRAMESIZE(r1)
695 /* Save all params that we need after a function call */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000696 std r6,STK_PARAM(R6)(r1)
697 std r8,STK_PARAM(R8)(r1)
698 std r9,STK_PARAM(R9)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100699
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100700 /* Save non-volatile registers.
701 * r31 will hold "old PTE"
702 * r30 is "new PTE"
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000703 * r29 is vpn
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100704 * r28 is a hash value
705 * r27 is hashtab mask (maybe dynamic patched instead ?)
706 */
Michael Neulingc75df6f2012-06-25 13:33:10 +0000707 std r27,STK_REG(R27)(r1)
708 std r28,STK_REG(R28)(r1)
709 std r29,STK_REG(R29)(r1)
710 std r30,STK_REG(R30)(r1)
711 std r31,STK_REG(R31)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100712
713 /* Step 1:
714 *
715 * Check permissions, atomically mark the linux PTE busy
716 * and hashed.
717 */
7181:
719 ldarx r31,0,r6
720 /* Check access rights (access & ~(pte_val(*ptep))) */
721 andc. r0,r4,r31
722 bne- ht64_wrong_access
723 /* Check if PTE is busy */
724 andi. r0,r31,_PAGE_BUSY
725 /* If so, just bail out and refault if needed. Someone else
726 * is changing this PTE anyway and might hash it.
727 */
728 bne- ht64_bail_ok
Paul Mackerrasbf72aeb2006-06-15 10:45:18 +1000729BEGIN_FTR_SECTION
730 /* Check if PTE has the cache-inhibit bit set */
731 andi. r0,r31,_PAGE_NO_CACHE
732 /* If so, bail out and refault as a 4k page */
733 bne- ht64_bail_ok
Matt Evans44ae3ab2011-04-06 19:48:50 +0000734END_MMU_FTR_SECTION_IFCLR(MMU_FTR_CI_LARGE_PAGE)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100735 /* Prepare new PTE value (turn access RW into DIRTY, then
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000736 * add BUSY and ACCESSED)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100737 */
738 rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
739 or r30,r30,r31
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000740 ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100741 /* Write the linux PTE atomically (setting busy) */
742 stdcx. r30,0,r6
743 bne- 1b
744 isync
745
746 /* Step 2:
747 *
748 * Insert/Update the HPTE in the hash table. At this point,
749 * r4 (access) is re-useable, we use it for the new HPTE flags
750 */
751
Paul Mackerras1189be62007-10-11 20:37:10 +1000752BEGIN_FTR_SECTION
753 cmpdi r9,0 /* check segment size */
754 bne 3f
Matt Evans44ae3ab2011-04-06 19:48:50 +0000755END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000756 /* Calc vpn and put it in r29 */
757 sldi r29,r5,SID_SHIFT - VPN_SHIFT
758 rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
759 or r29,r28,r29
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100760
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000761 /* Calculate hash value for primary slot and store it in r28
762 * r3 = va, r5 = vsid
763 * r0 = (va >> 16) & ((1ul << (28 - 16)) -1)
764 */
765 rldicl r0,r3,64-16,52
766 xor r28,r5,r0 /* hash */
Paul Mackerras1189be62007-10-11 20:37:10 +1000767 b 4f
768
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +00007693: /* Calc vpn and put it in r29 */
770 sldi r29,r5,SID_SHIFT_1T - VPN_SHIFT
771 rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
772 or r29,r28,r29
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000773 /*
774 * calculate hash value for primary slot and
775 * store it in r28 for 1T segment
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000776 * r3 = va, r5 = vsid
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000777 */
Aneesh Kumar K.Veda8eeb2013-01-29 19:40:42 +0000778 sldi r28,r5,25 /* vsid << 25 */
779 /* r0 = (va >> 16) & ((1ul << (40 - 16)) -1) */
780 rldicl r0,r3,64-16,40
781 xor r28,r28,r5 /* vsid ^ ( vsid << 25) */
Paul Mackerras1189be62007-10-11 20:37:10 +1000782 xor r28,r28,r0 /* hash */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100783
784 /* Convert linux PTE bits into HW equivalents */
Paul Mackerras1189be62007-10-11 20:37:10 +10007854: andi. r3,r30,0x1fe /* Get basic set of flags */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100786 xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
787 rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
788 rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
789 and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
790 andc r0,r30,r0 /* r0 = pte & ~r0 */
791 rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
Benjamin Herrenschmidtc5cf0e32006-05-30 14:14:19 +1000792 ori r3,r3,HPTE_R_C /* Always add "C" bit for perf. */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100793
794 /* We eventually do the icache sync here (maybe inline that
795 * code rather than call a C function...)
796 */
797BEGIN_FTR_SECTION
798 mr r4,r30
799 mr r5,r7
800 bl .hash_page_do_lazy_icache
801END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
802
803 /* At this point, r3 contains new PP bits, save them in
804 * place of "access" in the param area (sic)
805 */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000806 std r3,STK_PARAM(R4)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100807
808 /* Get htab_hash_mask */
809 ld r4,htab_hash_mask@got(2)
810 ld r27,0(r4) /* htab_hash_mask -> r27 */
811
812 /* Check if we may already be in the hashtable, in this case, we
813 * go to out-of-line code to try to modify the HPTE
814 */
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000815 rldicl. r0,r31,64-12,48
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100816 bne ht64_modify_pte
817
818ht64_insert_pte:
819 /* Clear hpte bits in new pte (we also clear BUSY btw) and
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000820 * add _PAGE_HPTE_SUB0
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100821 */
822 lis r0,_PAGE_HPTEFLAGS@h
823 ori r0,r0,_PAGE_HPTEFLAGS@l
824 andc r30,r30,r0
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000825#ifdef CONFIG_PPC_64K_PAGES
826 oris r30,r30,_PAGE_HPTE_SUB0@h
827#else
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100828 ori r30,r30,_PAGE_HASHPTE
Benjamin Herrenschmidt41743a42008-06-11 15:37:10 +1000829#endif
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100830 /* Phyical address in r5 */
831 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
832 sldi r5,r5,PAGE_SHIFT
833
834 /* Calculate primary group hash */
835 and r0,r28,r27
836 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
837
838 /* Call ppc_md.hpte_insert */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000839 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000840 mr r4,r29 /* Retrieve vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100841 li r7,0 /* !bolted, !secondary */
842 li r8,MMU_PAGE_64K
Michael Neuling44ce6a52012-06-25 13:33:14 +0000843 ld r9,STK_PARAM(R9)(r1) /* segment size */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100844_GLOBAL(ht64_call_hpte_insert1)
845 bl . /* patched by htab_finish_init() */
846 cmpdi 0,r3,0
847 bge ht64_pte_insert_ok /* Insertion successful */
848 cmpdi 0,r3,-2 /* Critical failure */
849 beq- ht64_pte_insert_failure
850
851 /* Now try secondary slot */
852
853 /* Phyical address in r5 */
854 rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
855 sldi r5,r5,PAGE_SHIFT
856
857 /* Calculate secondary group hash */
858 andc r0,r27,r28
859 rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
860
861 /* Call ppc_md.hpte_insert */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000862 ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000863 mr r4,r29 /* Retrieve vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100864 li r7,HPTE_V_SECONDARY /* !bolted, secondary */
865 li r8,MMU_PAGE_64K
Michael Neuling44ce6a52012-06-25 13:33:14 +0000866 ld r9,STK_PARAM(R9)(r1) /* segment size */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100867_GLOBAL(ht64_call_hpte_insert2)
868 bl . /* patched by htab_finish_init() */
869 cmpdi 0,r3,0
870 bge+ ht64_pte_insert_ok /* Insertion successful */
871 cmpdi 0,r3,-2 /* Critical failure */
872 beq- ht64_pte_insert_failure
873
874 /* Both are full, we need to evict something */
875 mftb r0
876 /* Pick a random group based on TB */
877 andi. r0,r0,1
878 mr r5,r28
879 bne 2f
880 not r5,r5
8812: and r0,r5,r27
882 rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
883 /* Call ppc_md.hpte_remove */
884_GLOBAL(ht64_call_hpte_remove)
885 bl . /* patched by htab_finish_init() */
886
887 /* Try all again */
888 b ht64_insert_pte
889
890ht64_bail_ok:
891 li r3,0
892 b ht64_bail
893
894ht64_pte_insert_ok:
895 /* Insert slot number & secondary bit in PTE */
896 rldimi r30,r3,12,63-15
897
898 /* Write out the PTE with a normal write
899 * (maybe add eieio may be good still ?)
900 */
901ht64_write_out_pte:
Michael Neuling44ce6a52012-06-25 13:33:14 +0000902 ld r6,STK_PARAM(R6)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100903 std r30,0(r6)
904 li r3, 0
905ht64_bail:
Michael Neulingc75df6f2012-06-25 13:33:10 +0000906 ld r27,STK_REG(R27)(r1)
907 ld r28,STK_REG(R28)(r1)
908 ld r29,STK_REG(R29)(r1)
909 ld r30,STK_REG(R30)(r1)
910 ld r31,STK_REG(R31)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100911 addi r1,r1,STACKFRAMESIZE
912 ld r0,16(r1)
913 mtlr r0
914 blr
915
916ht64_modify_pte:
917 /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
918 mr r4,r3
919 rlwinm r3,r31,32-12,29,31
920
921 /* Secondary group ? if yes, get a inverted hash value */
922 mr r5,r28
923 andi. r0,r31,_PAGE_F_SECOND
924 beq 1f
925 not r5,r5
9261:
927 /* Calculate proper slot value for ppc_md.hpte_updatepp */
928 and r0,r5,r27
929 rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
930 add r3,r0,r3 /* add slot idx */
931
932 /* Call ppc_md.hpte_updatepp */
Aneesh Kumar K.V5524a272012-09-10 02:52:50 +0000933 mr r5,r29 /* vpn */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100934 li r6,MMU_PAGE_64K
Michael Neuling44ce6a52012-06-25 13:33:14 +0000935 ld r7,STK_PARAM(R9)(r1) /* segment size */
936 ld r8,STK_PARAM(R8)(r1) /* get "local" param */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100937_GLOBAL(ht64_call_hpte_updatepp)
938 bl . /* patched by htab_finish_init() */
939
940 /* if we failed because typically the HPTE wasn't really here
941 * we try an insertion.
942 */
943 cmpdi 0,r3,-1
944 beq- ht64_insert_pte
945
946 /* Clear the BUSY bit and Write out the PTE */
947 li r0,_PAGE_BUSY
948 andc r30,r30,r0
949 b ht64_write_out_pte
950
951ht64_wrong_access:
952 /* Bail out clearing reservation */
953 stdcx. r31,0,r6
954 li r3,1
955 b ht64_bail
956
957ht64_pte_insert_failure:
958 /* Bail out restoring old PTE */
Michael Neuling44ce6a52012-06-25 13:33:14 +0000959 ld r6,STK_PARAM(R6)(r1)
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100960 std r31,0(r6)
961 li r3,-1
962 b ht64_bail
963
964
Benjamin Herrenschmidt16c2d472007-05-08 16:27:28 +1000965#endif /* CONFIG_PPC_HAS_HASH_64K */
Benjamin Herrenschmidt3c726f82005-11-07 11:06:55 +1100966
967
968/*****************************************************************************
969 * *
970 * Huge pages implementation is in hugetlbpage.c *
971 * *
972 *****************************************************************************/