hash_low_64.S 25 KB

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