hash_low_64.S 26 KB

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