hash_low_64.S 25 KB

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