hash_low_64.S 25 KB

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