hash_low_64.S 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. /*
  2. * ppc64 MMU hashtable management routines
  3. *
  4. * (c) Copyright IBM Corp. 2003, 2005
  5. *
  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. #include <asm/reg.h>
  13. #include <asm/pgtable.h>
  14. #include <asm/mmu.h>
  15. #include <asm/page.h>
  16. #include <asm/types.h>
  17. #include <asm/ppc_asm.h>
  18. #include <asm/asm-offsets.h>
  19. #include <asm/cputable.h>
  20. .text
  21. /*
  22. * Stackframe:
  23. *
  24. * +-> Back chain (SP + 256)
  25. * | General register save area (SP + 112)
  26. * | Parameter save area (SP + 48)
  27. * | TOC save area (SP + 40)
  28. * | link editor doubleword (SP + 32)
  29. * | compiler doubleword (SP + 24)
  30. * | LR save area (SP + 16)
  31. * | CR save area (SP + 8)
  32. * SP ---> +-- Back chain (SP + 0)
  33. */
  34. #ifndef CONFIG_PPC_64K_PAGES
  35. /*****************************************************************************
  36. * *
  37. * 4K SW & 4K HW pages implementation *
  38. * *
  39. *****************************************************************************/
  40. /*
  41. * _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
  42. * pte_t *ptep, unsigned long trap, unsigned long flags,
  43. * int ssize)
  44. *
  45. * Adds a 4K page to the hash table in a segment of 4K pages only
  46. */
  47. _GLOBAL(__hash_page_4K)
  48. mflr r0
  49. std r0,16(r1)
  50. stdu r1,-STACKFRAMESIZE(r1)
  51. /* Save all params that we need after a function call */
  52. std r6,STK_PARAM(R6)(r1)
  53. std r8,STK_PARAM(R8)(r1)
  54. std r9,STK_PARAM(R9)(r1)
  55. /* Save non-volatile registers.
  56. * r31 will hold "old PTE"
  57. * r30 is "new PTE"
  58. * r29 is vpn
  59. * r28 is a hash value
  60. * r27 is hashtab mask (maybe dynamic patched instead ?)
  61. */
  62. std r27,STK_REG(R27)(r1)
  63. std r28,STK_REG(R28)(r1)
  64. std r29,STK_REG(R29)(r1)
  65. std r30,STK_REG(R30)(r1)
  66. std r31,STK_REG(R31)(r1)
  67. /* Step 1:
  68. *
  69. * Check permissions, atomically mark the linux PTE busy
  70. * and hashed.
  71. */
  72. 1:
  73. ldarx r31,0,r6
  74. /* Check access rights (access & ~(pte_val(*ptep))) */
  75. andc. r0,r4,r31
  76. bne- htab_wrong_access
  77. /* Check if PTE is busy */
  78. andi. r0,r31,_PAGE_BUSY
  79. /* If so, just bail out and refault if needed. Someone else
  80. * is changing this PTE anyway and might hash it.
  81. */
  82. bne- htab_bail_ok
  83. /* Prepare new PTE value (turn access RW into DIRTY, then
  84. * add BUSY,HASHPTE and ACCESSED)
  85. */
  86. rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
  87. or r30,r30,r31
  88. ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
  89. /* Write the linux PTE atomically (setting busy) */
  90. stdcx. r30,0,r6
  91. bne- 1b
  92. isync
  93. /* Step 2:
  94. *
  95. * Insert/Update the HPTE in the hash table. At this point,
  96. * r4 (access) is re-useable, we use it for the new HPTE flags
  97. */
  98. BEGIN_FTR_SECTION
  99. cmpdi r9,0 /* check segment size */
  100. bne 3f
  101. END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
  102. /* Calc vpn and put it in r29 */
  103. sldi r29,r5,SID_SHIFT - VPN_SHIFT
  104. rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
  105. or r29,r28,r29
  106. /*
  107. * Calculate hash value for primary slot and store it in r28
  108. * r3 = va, r5 = vsid
  109. * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
  110. */
  111. rldicl r0,r3,64-12,48
  112. xor r28,r5,r0 /* hash */
  113. b 4f
  114. 3: /* Calc vpn and put it in r29 */
  115. sldi r29,r5,SID_SHIFT_1T - VPN_SHIFT
  116. rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
  117. or r29,r28,r29
  118. /*
  119. * calculate hash value for primary slot and
  120. * store it in r28 for 1T segment
  121. * r3 = va, r5 = vsid
  122. */
  123. sldi r28,r5,25 /* vsid << 25 */
  124. /* r0 = (va >> 12) & ((1ul << (40 - 12)) -1) */
  125. rldicl r0,r3,64-12,36
  126. xor r28,r28,r5 /* vsid ^ ( vsid << 25) */
  127. xor r28,r28,r0 /* hash */
  128. /* Convert linux PTE bits into HW equivalents */
  129. 4: andi. r3,r30,0x1fe /* Get basic set of flags */
  130. xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
  131. rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
  132. rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
  133. and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
  134. andc r0,r30,r0 /* r0 = pte & ~r0 */
  135. rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
  136. /*
  137. * Always add "C" bit for perf. Memory coherence is always enabled
  138. */
  139. ori r3,r3,HPTE_R_C | HPTE_R_M
  140. /* We eventually do the icache sync here (maybe inline that
  141. * code rather than call a C function...)
  142. */
  143. BEGIN_FTR_SECTION
  144. mr r4,r30
  145. mr r5,r7
  146. bl hash_page_do_lazy_icache
  147. END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
  148. /* At this point, r3 contains new PP bits, save them in
  149. * place of "access" in the param area (sic)
  150. */
  151. std r3,STK_PARAM(R4)(r1)
  152. /* Get htab_hash_mask */
  153. ld r4,htab_hash_mask@got(2)
  154. ld r27,0(r4) /* htab_hash_mask -> r27 */
  155. /* Check if we may already be in the hashtable, in this case, we
  156. * go to out-of-line code to try to modify the HPTE
  157. */
  158. andi. r0,r31,_PAGE_HASHPTE
  159. bne htab_modify_pte
  160. htab_insert_pte:
  161. /* Clear hpte bits in new pte (we also clear BUSY btw) and
  162. * add _PAGE_HASHPTE
  163. */
  164. lis r0,_PAGE_HPTEFLAGS@h
  165. ori r0,r0,_PAGE_HPTEFLAGS@l
  166. andc r30,r30,r0
  167. ori r30,r30,_PAGE_HASHPTE
  168. /* physical address r5 */
  169. rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
  170. sldi r5,r5,PAGE_SHIFT
  171. /* Calculate primary group hash */
  172. and r0,r28,r27
  173. rldicr r3,r0,3,63-3 /* r3 = (hash & mask) << 3 */
  174. /* Call ppc_md.hpte_insert */
  175. ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
  176. mr r4,r29 /* Retrieve vpn */
  177. li r7,0 /* !bolted, !secondary */
  178. li r8,MMU_PAGE_4K /* page size */
  179. li r9,MMU_PAGE_4K /* actual page size */
  180. ld r10,STK_PARAM(R9)(r1) /* segment size */
  181. .globl htab_call_hpte_insert1
  182. htab_call_hpte_insert1:
  183. bl . /* Patched by htab_finish_init() */
  184. cmpdi 0,r3,0
  185. bge htab_pte_insert_ok /* Insertion successful */
  186. cmpdi 0,r3,-2 /* Critical failure */
  187. beq- htab_pte_insert_failure
  188. /* Now try secondary slot */
  189. /* physical address r5 */
  190. rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
  191. sldi r5,r5,PAGE_SHIFT
  192. /* Calculate secondary group hash */
  193. andc r0,r27,r28
  194. rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
  195. /* Call ppc_md.hpte_insert */
  196. ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
  197. mr r4,r29 /* Retrieve vpn */
  198. li r7,HPTE_V_SECONDARY /* !bolted, secondary */
  199. li r8,MMU_PAGE_4K /* page size */
  200. li r9,MMU_PAGE_4K /* actual page size */
  201. ld r10,STK_PARAM(R9)(r1) /* segment size */
  202. .globl htab_call_hpte_insert2
  203. htab_call_hpte_insert2:
  204. bl . /* Patched by htab_finish_init() */
  205. cmpdi 0,r3,0
  206. bge+ htab_pte_insert_ok /* Insertion successful */
  207. cmpdi 0,r3,-2 /* Critical failure */
  208. beq- htab_pte_insert_failure
  209. /* Both are full, we need to evict something */
  210. mftb r0
  211. /* Pick a random group based on TB */
  212. andi. r0,r0,1
  213. mr r5,r28
  214. bne 2f
  215. not r5,r5
  216. 2: and r0,r5,r27
  217. rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  218. /* Call ppc_md.hpte_remove */
  219. .globl htab_call_hpte_remove
  220. htab_call_hpte_remove:
  221. bl . /* Patched by htab_finish_init() */
  222. /* Try all again */
  223. b htab_insert_pte
  224. htab_bail_ok:
  225. li r3,0
  226. b htab_bail
  227. htab_pte_insert_ok:
  228. /* Insert slot number & secondary bit in PTE */
  229. rldimi r30,r3,12,63-15
  230. /* Write out the PTE with a normal write
  231. * (maybe add eieio may be good still ?)
  232. */
  233. htab_write_out_pte:
  234. ld r6,STK_PARAM(R6)(r1)
  235. std r30,0(r6)
  236. li r3, 0
  237. htab_bail:
  238. ld r27,STK_REG(R27)(r1)
  239. ld r28,STK_REG(R28)(r1)
  240. ld r29,STK_REG(R29)(r1)
  241. ld r30,STK_REG(R30)(r1)
  242. ld r31,STK_REG(R31)(r1)
  243. addi r1,r1,STACKFRAMESIZE
  244. ld r0,16(r1)
  245. mtlr r0
  246. blr
  247. htab_modify_pte:
  248. /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
  249. mr r4,r3
  250. rlwinm r3,r31,32-12,29,31
  251. /* Secondary group ? if yes, get a inverted hash value */
  252. mr r5,r28
  253. andi. r0,r31,_PAGE_SECONDARY
  254. beq 1f
  255. not r5,r5
  256. 1:
  257. /* Calculate proper slot value for ppc_md.hpte_updatepp */
  258. and r0,r5,r27
  259. rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  260. add r3,r0,r3 /* add slot idx */
  261. /* Call ppc_md.hpte_updatepp */
  262. mr r5,r29 /* vpn */
  263. li r6,MMU_PAGE_4K /* base page size */
  264. li r7,MMU_PAGE_4K /* actual page size */
  265. ld r8,STK_PARAM(R9)(r1) /* segment size */
  266. ld r9,STK_PARAM(R8)(r1) /* get "flags" param */
  267. .globl htab_call_hpte_updatepp
  268. htab_call_hpte_updatepp:
  269. bl . /* Patched by htab_finish_init() */
  270. /* if we failed because typically the HPTE wasn't really here
  271. * we try an insertion.
  272. */
  273. cmpdi 0,r3,-1
  274. beq- htab_insert_pte
  275. /* Clear the BUSY bit and Write out the PTE */
  276. li r0,_PAGE_BUSY
  277. andc r30,r30,r0
  278. b htab_write_out_pte
  279. htab_wrong_access:
  280. /* Bail out clearing reservation */
  281. stdcx. r31,0,r6
  282. li r3,1
  283. b htab_bail
  284. htab_pte_insert_failure:
  285. /* Bail out restoring old PTE */
  286. ld r6,STK_PARAM(R6)(r1)
  287. std r31,0(r6)
  288. li r3,-1
  289. b htab_bail
  290. #else /* CONFIG_PPC_64K_PAGES */
  291. /*****************************************************************************
  292. * *
  293. * 64K SW & 4K or 64K HW in a 4K segment pages implementation *
  294. * *
  295. *****************************************************************************/
  296. /* _hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
  297. * pte_t *ptep, unsigned long trap, unsigned local flags,
  298. * int ssize, int subpg_prot)
  299. */
  300. /*
  301. * For now, we do NOT implement Admixed pages
  302. */
  303. _GLOBAL(__hash_page_4K)
  304. mflr r0
  305. std r0,16(r1)
  306. stdu r1,-STACKFRAMESIZE(r1)
  307. /* Save all params that we need after a function call */
  308. std r6,STK_PARAM(R6)(r1)
  309. std r8,STK_PARAM(R8)(r1)
  310. std r9,STK_PARAM(R9)(r1)
  311. /* Save non-volatile registers.
  312. * r31 will hold "old PTE"
  313. * r30 is "new PTE"
  314. * r29 is vpn
  315. * r28 is a hash value
  316. * r27 is hashtab mask (maybe dynamic patched instead ?)
  317. * r26 is the hidx mask
  318. * r25 is the index in combo page
  319. */
  320. std r25,STK_REG(R25)(r1)
  321. std r26,STK_REG(R26)(r1)
  322. std r27,STK_REG(R27)(r1)
  323. std r28,STK_REG(R28)(r1)
  324. std r29,STK_REG(R29)(r1)
  325. std r30,STK_REG(R30)(r1)
  326. std r31,STK_REG(R31)(r1)
  327. /* Step 1:
  328. *
  329. * Check permissions, atomically mark the linux PTE busy
  330. * and hashed.
  331. */
  332. 1:
  333. ldarx r31,0,r6
  334. /* Check access rights (access & ~(pte_val(*ptep))) */
  335. andc. r0,r4,r31
  336. bne- htab_wrong_access
  337. /* Check if PTE is busy */
  338. andi. r0,r31,_PAGE_BUSY
  339. /* If so, just bail out and refault if needed. Someone else
  340. * is changing this PTE anyway and might hash it.
  341. */
  342. bne- htab_bail_ok
  343. /* Prepare new PTE value (turn access RW into DIRTY, then
  344. * add BUSY and ACCESSED)
  345. */
  346. rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
  347. or r30,r30,r31
  348. ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED
  349. oris r30,r30,_PAGE_COMBO@h
  350. /* Write the linux PTE atomically (setting busy) */
  351. stdcx. r30,0,r6
  352. bne- 1b
  353. isync
  354. /* Step 2:
  355. *
  356. * Insert/Update the HPTE in the hash table. At this point,
  357. * r4 (access) is re-useable, we use it for the new HPTE flags
  358. */
  359. /* Load the hidx index */
  360. rldicl r25,r3,64-12,60
  361. BEGIN_FTR_SECTION
  362. cmpdi r9,0 /* check segment size */
  363. bne 3f
  364. END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
  365. /* Calc vpn and put it in r29 */
  366. sldi r29,r5,SID_SHIFT - VPN_SHIFT
  367. /*
  368. * clrldi r3,r3,64 - SID_SHIFT --> ea & 0xfffffff
  369. * srdi r28,r3,VPN_SHIFT
  370. */
  371. rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
  372. or r29,r28,r29
  373. /*
  374. * Calculate hash value for primary slot and store it in r28
  375. * r3 = va, r5 = vsid
  376. * r0 = (va >> 12) & ((1ul << (28 - 12)) -1)
  377. */
  378. rldicl r0,r3,64-12,48
  379. xor r28,r5,r0 /* hash */
  380. b 4f
  381. 3: /* Calc vpn and put it in r29 */
  382. sldi r29,r5,SID_SHIFT_1T - VPN_SHIFT
  383. /*
  384. * clrldi r3,r3,64 - SID_SHIFT_1T --> ea & 0xffffffffff
  385. * srdi r28,r3,VPN_SHIFT
  386. */
  387. rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
  388. or r29,r28,r29
  389. /*
  390. * Calculate hash value for primary slot and
  391. * store it in r28 for 1T segment
  392. * r3 = va, r5 = vsid
  393. */
  394. sldi r28,r5,25 /* vsid << 25 */
  395. /* r0 = (va >> 12) & ((1ul << (40 - 12)) -1) */
  396. rldicl r0,r3,64-12,36
  397. xor r28,r28,r5 /* vsid ^ ( vsid << 25) */
  398. xor r28,r28,r0 /* hash */
  399. /* Convert linux PTE bits into HW equivalents */
  400. 4:
  401. #ifdef CONFIG_PPC_SUBPAGE_PROT
  402. andc r10,r30,r10
  403. andi. r3,r10,0x1fe /* Get basic set of flags */
  404. rlwinm r0,r10,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
  405. #else
  406. andi. r3,r30,0x1fe /* Get basic set of flags */
  407. rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
  408. #endif
  409. xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
  410. rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
  411. and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
  412. andc r0,r3,r0 /* r0 = pte & ~r0 */
  413. rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
  414. /*
  415. * Always add "C" bit for perf. Memory coherence is always enabled
  416. */
  417. ori r3,r3,HPTE_R_C | HPTE_R_M
  418. /* We eventually do the icache sync here (maybe inline that
  419. * code rather than call a C function...)
  420. */
  421. BEGIN_FTR_SECTION
  422. mr r4,r30
  423. mr r5,r7
  424. bl hash_page_do_lazy_icache
  425. END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
  426. /* At this point, r3 contains new PP bits, save them in
  427. * place of "access" in the param area (sic)
  428. */
  429. std r3,STK_PARAM(R4)(r1)
  430. /* Get htab_hash_mask */
  431. ld r4,htab_hash_mask@got(2)
  432. ld r27,0(r4) /* htab_hash_mask -> r27 */
  433. /* Check if we may already be in the hashtable, in this case, we
  434. * go to out-of-line code to try to modify the HPTE. We look for
  435. * the bit at (1 >> (index + 32))
  436. */
  437. rldicl. r0,r31,64-12,48
  438. li r26,0 /* Default hidx */
  439. beq htab_insert_pte
  440. /*
  441. * Check if the pte was already inserted into the hash table
  442. * as a 64k HW page, and invalidate the 64k HPTE if so.
  443. */
  444. andis. r0,r31,_PAGE_COMBO@h
  445. beq htab_inval_old_hpte
  446. ld r6,STK_PARAM(R6)(r1)
  447. ori r26,r6,PTE_PAGE_HIDX_OFFSET /* Load the hidx mask. */
  448. ld r26,0(r26)
  449. addi r5,r25,36 /* Check actual HPTE_SUB bit, this */
  450. rldcr. r0,r31,r5,0 /* must match pgtable.h definition */
  451. bne htab_modify_pte
  452. htab_insert_pte:
  453. /* real page number in r5, PTE RPN value + index */
  454. andis. r0,r31,_PAGE_4K_PFN@h
  455. srdi r5,r31,PTE_RPN_SHIFT
  456. bne- htab_special_pfn
  457. sldi r5,r5,PAGE_FACTOR
  458. add r5,r5,r25
  459. htab_special_pfn:
  460. sldi r5,r5,HW_PAGE_SHIFT
  461. /* Calculate primary group hash */
  462. and r0,r28,r27
  463. rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  464. /* Call ppc_md.hpte_insert */
  465. ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
  466. mr r4,r29 /* Retrieve vpn */
  467. li r7,0 /* !bolted, !secondary */
  468. li r8,MMU_PAGE_4K /* page size */
  469. li r9,MMU_PAGE_4K /* actual page size */
  470. ld r10,STK_PARAM(R9)(r1) /* segment size */
  471. .globl htab_call_hpte_insert1
  472. htab_call_hpte_insert1:
  473. bl . /* patched by htab_finish_init() */
  474. cmpdi 0,r3,0
  475. bge htab_pte_insert_ok /* Insertion successful */
  476. cmpdi 0,r3,-2 /* Critical failure */
  477. beq- htab_pte_insert_failure
  478. /* Now try secondary slot */
  479. /* real page number in r5, PTE RPN value + index */
  480. andis. r0,r31,_PAGE_4K_PFN@h
  481. srdi r5,r31,PTE_RPN_SHIFT
  482. bne- 3f
  483. sldi r5,r5,PAGE_FACTOR
  484. add r5,r5,r25
  485. 3: sldi r5,r5,HW_PAGE_SHIFT
  486. /* Calculate secondary group hash */
  487. andc r0,r27,r28
  488. 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 vpn */
  492. li r7,HPTE_V_SECONDARY /* !bolted, secondary */
  493. li r8,MMU_PAGE_4K /* page size */
  494. li r9,MMU_PAGE_4K /* actual page size */
  495. ld r10,STK_PARAM(R9)(r1) /* segment size */
  496. .globl htab_call_hpte_insert2
  497. htab_call_hpte_insert2:
  498. bl . /* patched by htab_finish_init() */
  499. cmpdi 0,r3,0
  500. bge+ htab_pte_insert_ok /* Insertion successful */
  501. cmpdi 0,r3,-2 /* Critical failure */
  502. beq- htab_pte_insert_failure
  503. /* Both are full, we need to evict something */
  504. mftb r0
  505. /* Pick a random group based on TB */
  506. andi. r0,r0,1
  507. mr r5,r28
  508. bne 2f
  509. not r5,r5
  510. 2: and r0,r5,r27
  511. rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  512. /* Call ppc_md.hpte_remove */
  513. .globl htab_call_hpte_remove
  514. htab_call_hpte_remove:
  515. bl . /* patched by htab_finish_init() */
  516. /* Try all again */
  517. b htab_insert_pte
  518. /*
  519. * Call out to C code to invalidate an 64k HW HPTE that is
  520. * useless now that the segment has been switched to 4k pages.
  521. */
  522. htab_inval_old_hpte:
  523. mr r3,r29 /* vpn */
  524. mr r4,r31 /* PTE.pte */
  525. li r5,0 /* PTE.hidx */
  526. li r6,MMU_PAGE_64K /* psize */
  527. ld r7,STK_PARAM(R9)(r1) /* ssize */
  528. ld r8,STK_PARAM(R8)(r1) /* flags */
  529. bl flush_hash_page
  530. /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */
  531. lis r0,_PAGE_HPTE_SUB@h
  532. ori r0,r0,_PAGE_HPTE_SUB@l
  533. andc r30,r30,r0
  534. b htab_insert_pte
  535. htab_bail_ok:
  536. li r3,0
  537. b htab_bail
  538. htab_pte_insert_ok:
  539. /* Insert slot number & secondary bit in PTE second half,
  540. * clear _PAGE_BUSY and set approriate HPTE slot bit
  541. */
  542. ld r6,STK_PARAM(R6)(r1)
  543. li r0,_PAGE_BUSY
  544. andc r30,r30,r0
  545. /* HPTE SUB bit */
  546. li r0,1
  547. subfic r5,r25,27 /* Must match bit position in */
  548. sld r0,r0,r5 /* pgtable.h */
  549. or r30,r30,r0
  550. /* hindx */
  551. sldi r5,r25,2
  552. sld r3,r3,r5
  553. li r4,0xf
  554. sld r4,r4,r5
  555. andc r26,r26,r4
  556. or r26,r26,r3
  557. ori r5,r6,PTE_PAGE_HIDX_OFFSET
  558. std r26,0(r5)
  559. lwsync
  560. std r30,0(r6)
  561. li r3, 0
  562. htab_bail:
  563. ld r25,STK_REG(R25)(r1)
  564. ld r26,STK_REG(R26)(r1)
  565. ld r27,STK_REG(R27)(r1)
  566. ld r28,STK_REG(R28)(r1)
  567. ld r29,STK_REG(R29)(r1)
  568. ld r30,STK_REG(R30)(r1)
  569. ld r31,STK_REG(R31)(r1)
  570. addi r1,r1,STACKFRAMESIZE
  571. ld r0,16(r1)
  572. mtlr r0
  573. blr
  574. htab_modify_pte:
  575. /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
  576. mr r4,r3
  577. sldi r5,r25,2
  578. srd r3,r26,r5
  579. /* Secondary group ? if yes, get a inverted hash value */
  580. mr r5,r28
  581. andi. r0,r3,0x8 /* page secondary ? */
  582. beq 1f
  583. not r5,r5
  584. 1: andi. r3,r3,0x7 /* extract idx alone */
  585. /* Calculate proper slot value for ppc_md.hpte_updatepp */
  586. and r0,r5,r27
  587. rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  588. add r3,r0,r3 /* add slot idx */
  589. /* Call ppc_md.hpte_updatepp */
  590. mr r5,r29 /* vpn */
  591. li r6,MMU_PAGE_4K /* base page size */
  592. li r7,MMU_PAGE_4K /* actual page size */
  593. ld r8,STK_PARAM(R9)(r1) /* segment size */
  594. ld r9,STK_PARAM(R8)(r1) /* get "flags" param */
  595. .globl htab_call_hpte_updatepp
  596. htab_call_hpte_updatepp:
  597. bl . /* patched by htab_finish_init() */
  598. /* if we failed because typically the HPTE wasn't really here
  599. * we try an insertion.
  600. */
  601. cmpdi 0,r3,-1
  602. beq- htab_insert_pte
  603. /* Clear the BUSY bit and Write out the PTE */
  604. li r0,_PAGE_BUSY
  605. andc r30,r30,r0
  606. ld r6,STK_PARAM(R6)(r1)
  607. std r30,0(r6)
  608. li r3,0
  609. b htab_bail
  610. htab_wrong_access:
  611. /* Bail out clearing reservation */
  612. stdcx. r31,0,r6
  613. li r3,1
  614. b htab_bail
  615. htab_pte_insert_failure:
  616. /* Bail out restoring old PTE */
  617. ld r6,STK_PARAM(R6)(r1)
  618. std r31,0(r6)
  619. li r3,-1
  620. b htab_bail
  621. #endif /* CONFIG_PPC_64K_PAGES */
  622. #ifdef CONFIG_PPC_64K_PAGES
  623. /*****************************************************************************
  624. * *
  625. * 64K SW & 64K HW in a 64K segment pages implementation *
  626. * *
  627. *****************************************************************************/
  628. _GLOBAL(__hash_page_64K)
  629. mflr r0
  630. std r0,16(r1)
  631. stdu r1,-STACKFRAMESIZE(r1)
  632. /* Save all params that we need after a function call */
  633. std r6,STK_PARAM(R6)(r1)
  634. std r8,STK_PARAM(R8)(r1)
  635. std r9,STK_PARAM(R9)(r1)
  636. /* Save non-volatile registers.
  637. * r31 will hold "old PTE"
  638. * r30 is "new PTE"
  639. * r29 is vpn
  640. * r28 is a hash value
  641. * r27 is hashtab mask (maybe dynamic patched instead ?)
  642. */
  643. std r27,STK_REG(R27)(r1)
  644. std r28,STK_REG(R28)(r1)
  645. std r29,STK_REG(R29)(r1)
  646. std r30,STK_REG(R30)(r1)
  647. std r31,STK_REG(R31)(r1)
  648. /* Step 1:
  649. *
  650. * Check permissions, atomically mark the linux PTE busy
  651. * and hashed.
  652. */
  653. 1:
  654. ldarx r31,0,r6
  655. /* Check access rights (access & ~(pte_val(*ptep))) */
  656. andc. r0,r4,r31
  657. bne- ht64_wrong_access
  658. /* Check if PTE is busy */
  659. andi. r0,r31,_PAGE_BUSY
  660. /* If so, just bail out and refault if needed. Someone else
  661. * is changing this PTE anyway and might hash it.
  662. */
  663. bne- ht64_bail_ok
  664. BEGIN_FTR_SECTION
  665. /* Check if PTE has the cache-inhibit bit set */
  666. andi. r0,r31,_PAGE_NO_CACHE
  667. /* If so, bail out and refault as a 4k page */
  668. bne- ht64_bail_ok
  669. END_MMU_FTR_SECTION_IFCLR(MMU_FTR_CI_LARGE_PAGE)
  670. /* Prepare new PTE value (turn access RW into DIRTY, then
  671. * add BUSY and ACCESSED)
  672. */
  673. rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
  674. or r30,r30,r31
  675. ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED
  676. /* Write the linux PTE atomically (setting busy) */
  677. stdcx. r30,0,r6
  678. bne- 1b
  679. isync
  680. /* Step 2:
  681. *
  682. * Insert/Update the HPTE in the hash table. At this point,
  683. * r4 (access) is re-useable, we use it for the new HPTE flags
  684. */
  685. BEGIN_FTR_SECTION
  686. cmpdi r9,0 /* check segment size */
  687. bne 3f
  688. END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
  689. /* Calc vpn and put it in r29 */
  690. sldi r29,r5,SID_SHIFT - VPN_SHIFT
  691. rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
  692. or r29,r28,r29
  693. /* Calculate hash value for primary slot and store it in r28
  694. * r3 = va, r5 = vsid
  695. * r0 = (va >> 16) & ((1ul << (28 - 16)) -1)
  696. */
  697. rldicl r0,r3,64-16,52
  698. xor r28,r5,r0 /* hash */
  699. b 4f
  700. 3: /* Calc vpn and put it in r29 */
  701. sldi r29,r5,SID_SHIFT_1T - VPN_SHIFT
  702. rldicl r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
  703. or r29,r28,r29
  704. /*
  705. * calculate hash value for primary slot and
  706. * store it in r28 for 1T segment
  707. * r3 = va, r5 = vsid
  708. */
  709. sldi r28,r5,25 /* vsid << 25 */
  710. /* r0 = (va >> 16) & ((1ul << (40 - 16)) -1) */
  711. rldicl r0,r3,64-16,40
  712. xor r28,r28,r5 /* vsid ^ ( vsid << 25) */
  713. xor r28,r28,r0 /* hash */
  714. /* Convert linux PTE bits into HW equivalents */
  715. 4: andi. r3,r30,0x1fe /* Get basic set of flags */
  716. xori r3,r3,HPTE_R_N /* _PAGE_EXEC -> NOEXEC */
  717. rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
  718. rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
  719. and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
  720. andc r0,r30,r0 /* r0 = pte & ~r0 */
  721. rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */
  722. /*
  723. * Always add "C" bit for perf. Memory coherence is always enabled
  724. */
  725. ori r3,r3,HPTE_R_C | HPTE_R_M
  726. /* We eventually do the icache sync here (maybe inline that
  727. * code rather than call a C function...)
  728. */
  729. BEGIN_FTR_SECTION
  730. mr r4,r30
  731. mr r5,r7
  732. bl hash_page_do_lazy_icache
  733. END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
  734. /* At this point, r3 contains new PP bits, save them in
  735. * place of "access" in the param area (sic)
  736. */
  737. std r3,STK_PARAM(R4)(r1)
  738. /* Get htab_hash_mask */
  739. ld r4,htab_hash_mask@got(2)
  740. ld r27,0(r4) /* htab_hash_mask -> r27 */
  741. /* Check if we may already be in the hashtable, in this case, we
  742. * go to out-of-line code to try to modify the HPTE
  743. */
  744. rldicl. r0,r31,64-12,48
  745. bne ht64_modify_pte
  746. ht64_insert_pte:
  747. /* Clear hpte bits in new pte (we also clear BUSY btw) and
  748. * add _PAGE_HPTE_SUB0
  749. */
  750. lis r0,_PAGE_HPTEFLAGS@h
  751. ori r0,r0,_PAGE_HPTEFLAGS@l
  752. andc r30,r30,r0
  753. #ifdef CONFIG_PPC_64K_PAGES
  754. oris r30,r30,_PAGE_HPTE_SUB0@h
  755. #else
  756. ori r30,r30,_PAGE_HASHPTE
  757. #endif
  758. /* Phyical address in r5 */
  759. rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
  760. sldi r5,r5,PAGE_SHIFT
  761. /* Calculate primary group hash */
  762. and r0,r28,r27
  763. rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  764. /* Call ppc_md.hpte_insert */
  765. ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
  766. mr r4,r29 /* Retrieve vpn */
  767. li r7,0 /* !bolted, !secondary */
  768. li r8,MMU_PAGE_64K
  769. li r9,MMU_PAGE_64K /* actual page size */
  770. ld r10,STK_PARAM(R9)(r1) /* segment size */
  771. .globl ht64_call_hpte_insert1
  772. ht64_call_hpte_insert1:
  773. bl . /* patched by htab_finish_init() */
  774. cmpdi 0,r3,0
  775. bge ht64_pte_insert_ok /* Insertion successful */
  776. cmpdi 0,r3,-2 /* Critical failure */
  777. beq- ht64_pte_insert_failure
  778. /* Now try secondary slot */
  779. /* Phyical address in r5 */
  780. rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
  781. sldi r5,r5,PAGE_SHIFT
  782. /* Calculate secondary group hash */
  783. andc r0,r27,r28
  784. rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */
  785. /* Call ppc_md.hpte_insert */
  786. ld r6,STK_PARAM(R4)(r1) /* Retrieve new pp bits */
  787. mr r4,r29 /* Retrieve vpn */
  788. li r7,HPTE_V_SECONDARY /* !bolted, secondary */
  789. li r8,MMU_PAGE_64K
  790. li r9,MMU_PAGE_64K /* actual page size */
  791. ld r10,STK_PARAM(R9)(r1) /* segment size */
  792. .globl ht64_call_hpte_insert2
  793. ht64_call_hpte_insert2:
  794. bl . /* patched by htab_finish_init() */
  795. cmpdi 0,r3,0
  796. bge+ ht64_pte_insert_ok /* Insertion successful */
  797. cmpdi 0,r3,-2 /* Critical failure */
  798. beq- ht64_pte_insert_failure
  799. /* Both are full, we need to evict something */
  800. mftb r0
  801. /* Pick a random group based on TB */
  802. andi. r0,r0,1
  803. mr r5,r28
  804. bne 2f
  805. not r5,r5
  806. 2: and r0,r5,r27
  807. rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  808. /* Call ppc_md.hpte_remove */
  809. .globl ht64_call_hpte_remove
  810. ht64_call_hpte_remove:
  811. bl . /* patched by htab_finish_init() */
  812. /* Try all again */
  813. b ht64_insert_pte
  814. ht64_bail_ok:
  815. li r3,0
  816. b ht64_bail
  817. ht64_pte_insert_ok:
  818. /* Insert slot number & secondary bit in PTE */
  819. rldimi r30,r3,12,63-15
  820. /* Write out the PTE with a normal write
  821. * (maybe add eieio may be good still ?)
  822. */
  823. ht64_write_out_pte:
  824. ld r6,STK_PARAM(R6)(r1)
  825. std r30,0(r6)
  826. li r3, 0
  827. ht64_bail:
  828. ld r27,STK_REG(R27)(r1)
  829. ld r28,STK_REG(R28)(r1)
  830. ld r29,STK_REG(R29)(r1)
  831. ld r30,STK_REG(R30)(r1)
  832. ld r31,STK_REG(R31)(r1)
  833. addi r1,r1,STACKFRAMESIZE
  834. ld r0,16(r1)
  835. mtlr r0
  836. blr
  837. ht64_modify_pte:
  838. /* Keep PP bits in r4 and slot idx from the PTE around in r3 */
  839. mr r4,r3
  840. rlwinm r3,r31,32-12,29,31
  841. /* Secondary group ? if yes, get a inverted hash value */
  842. mr r5,r28
  843. andi. r0,r31,_PAGE_F_SECOND
  844. beq 1f
  845. not r5,r5
  846. 1:
  847. /* Calculate proper slot value for ppc_md.hpte_updatepp */
  848. and r0,r5,r27
  849. rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */
  850. add r3,r0,r3 /* add slot idx */
  851. /* Call ppc_md.hpte_updatepp */
  852. mr r5,r29 /* vpn */
  853. li r6,MMU_PAGE_64K /* base page size */
  854. li r7,MMU_PAGE_64K /* actual page size */
  855. ld r8,STK_PARAM(R9)(r1) /* segment size */
  856. ld r9,STK_PARAM(R8)(r1) /* get "flags" param */
  857. .globl ht64_call_hpte_updatepp
  858. ht64_call_hpte_updatepp:
  859. bl . /* patched by htab_finish_init() */
  860. /* if we failed because typically the HPTE wasn't really here
  861. * we try an insertion.
  862. */
  863. cmpdi 0,r3,-1
  864. beq- ht64_insert_pte
  865. /* Clear the BUSY bit and Write out the PTE */
  866. li r0,_PAGE_BUSY
  867. andc r30,r30,r0
  868. b ht64_write_out_pte
  869. ht64_wrong_access:
  870. /* Bail out clearing reservation */
  871. stdcx. r31,0,r6
  872. li r3,1
  873. b ht64_bail
  874. ht64_pte_insert_failure:
  875. /* Bail out restoring old PTE */
  876. ld r6,STK_PARAM(R6)(r1)
  877. std r31,0(r6)
  878. li r3,-1
  879. b ht64_bail
  880. #endif /* CONFIG_PPC_64K_PAGES */
  881. /*****************************************************************************
  882. * *
  883. * Huge pages implementation is in hugetlbpage.c *
  884. * *
  885. *****************************************************************************/