hash_low_64.S 26 KB

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