hash_low_64.S 26 KB

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