hash_low_64.S 26 KB

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