hash_low_64.S 26 KB

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