hash_low_64.S 23 KB

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