hash_low_64.S 26 KB

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