hash_low_64.S 23 KB

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