hash_low_64.S 26 KB

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