trap_subr.S 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. /*-
  2. * Copyright (C) 2006-2009 Semihalf, Rafal Jaworowski <raj@semihalf.com>
  3. * Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
  4. * Copyright (C) 2006 Juniper Networks, Inc.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. The name of the author may not be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  21. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  22. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  23. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  24. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  25. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  26. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * $FreeBSD$
  30. */
  31. /*-
  32. * Copyright (C) 1995, 1996 Wolfgang Solfrank.
  33. * Copyright (C) 1995, 1996 TooLs GmbH.
  34. * All rights reserved.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. * 1. Redistributions of source code must retain the above copyright
  40. * notice, this list of conditions and the following disclaimer.
  41. * 2. Redistributions in binary form must reproduce the above copyright
  42. * notice, this list of conditions and the following disclaimer in the
  43. * documentation and/or other materials provided with the distribution.
  44. * 3. All advertising materials mentioning features or use of this software
  45. * must display the following acknowledgement:
  46. * This product includes software developed by TooLs GmbH.
  47. * 4. The name of TooLs GmbH may not be used to endorse or promote products
  48. * derived from this software without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
  51. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  52. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  53. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  54. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  55. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  56. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  57. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  58. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  59. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60. *
  61. * from: $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $
  62. */
  63. /*
  64. * NOTICE: This is not a standalone file. to use it, #include it in
  65. * your port's locore.S, like so:
  66. *
  67. * #include <powerpc/booke/trap_subr.S>
  68. */
  69. /*
  70. * SPRG usage notes
  71. *
  72. * SPRG0 - pcpu pointer
  73. * SPRG1 - all interrupts except TLB miss, critical, machine check
  74. * SPRG2 - critical
  75. * SPRG3 - machine check
  76. * SPRG4-6 - scratch
  77. *
  78. */
  79. /* Get the per-CPU data structure */
  80. #define GET_CPUINFO(r) mfsprg0 r
  81. #define RES_GRANULE 64
  82. #define RES_LOCK 0 /* offset to the 'lock' word */
  83. #ifdef __powerpc64__
  84. #define RES_RECURSE 8 /* offset to the 'recurse' word */
  85. #else
  86. #define RES_RECURSE 4 /* offset to the 'recurse' word */
  87. #endif
  88. /*
  89. * Standard interrupt prolog
  90. *
  91. * sprg_sp - SPRG{1-3} reg used to temporarily store the SP
  92. * savearea - temp save area (pc_{tempsave, disisave, critsave, mchksave})
  93. * isrr0-1 - save restore registers with CPU state at interrupt time (may be
  94. * SRR0-1, CSRR0-1, MCSRR0-1
  95. *
  96. * 1. saves in the given savearea:
  97. * - R30-31
  98. * - DEAR, ESR
  99. * - xSRR0-1
  100. *
  101. * 2. saves CR -> R30
  102. *
  103. * 3. switches to kstack if needed
  104. *
  105. * 4. notes:
  106. * - R31 can be used as scratch register until a new frame is layed on
  107. * the stack with FRAME_SETUP
  108. *
  109. * - potential TLB miss: NO. Saveareas are always acessible via TLB1
  110. * permanent entries, and within this prolog we do not dereference any
  111. * locations potentially not in the TLB
  112. */
  113. #define STANDARD_PROLOG(sprg_sp, savearea, isrr0, isrr1) \
  114. mtspr sprg_sp, %r1; /* Save SP */ \
  115. GET_CPUINFO(%r1); /* Per-cpu structure */ \
  116. STORE %r30, (savearea+CPUSAVE_R30)(%r1); \
  117. STORE %r31, (savearea+CPUSAVE_R31)(%r1); \
  118. mfspr %r30, SPR_DEAR; \
  119. mfspr %r31, SPR_ESR; \
  120. STORE %r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); \
  121. STORE %r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); \
  122. mfspr %r30, isrr0; \
  123. mfspr %r31, isrr1; /* MSR at interrupt time */ \
  124. STORE %r30, (savearea+CPUSAVE_SRR0)(%r1); \
  125. STORE %r31, (savearea+CPUSAVE_SRR1)(%r1); \
  126. isync; \
  127. mfspr %r1, sprg_sp; /* Restore SP */ \
  128. mfcr %r30; /* Save CR */ \
  129. /* switch to per-thread kstack if intr taken in user mode */ \
  130. mtcr %r31; /* MSR at interrupt time */ \
  131. bf 17, 1f; \
  132. GET_CPUINFO(%r1); /* Per-cpu structure */ \
  133. LOAD %r1, PC_CURPCB(%r1); /* Per-thread kernel stack */ \
  134. 1:
  135. #define STANDARD_CRIT_PROLOG(sprg_sp, savearea, isrr0, isrr1) \
  136. mtspr sprg_sp, %r1; /* Save SP */ \
  137. GET_CPUINFO(%r1); /* Per-cpu structure */ \
  138. STORE %r30, (savearea+CPUSAVE_R30)(%r1); \
  139. STORE %r31, (savearea+CPUSAVE_R31)(%r1); \
  140. mfspr %r30, SPR_DEAR; \
  141. mfspr %r31, SPR_ESR; \
  142. STORE %r30, (savearea+CPUSAVE_BOOKE_DEAR)(%r1); \
  143. STORE %r31, (savearea+CPUSAVE_BOOKE_ESR)(%r1); \
  144. mfspr %r30, isrr0; \
  145. mfspr %r31, isrr1; /* MSR at interrupt time */ \
  146. STORE %r30, (savearea+CPUSAVE_SRR0)(%r1); \
  147. STORE %r31, (savearea+CPUSAVE_SRR1)(%r1); \
  148. mfspr %r30, SPR_SRR0; \
  149. mfspr %r31, SPR_SRR1; /* MSR at interrupt time */ \
  150. STORE %r30, (savearea+BOOKE_CRITSAVE_SRR0)(%r1); \
  151. STORE %r31, (savearea+BOOKE_CRITSAVE_SRR1)(%r1); \
  152. isync; \
  153. mfspr %r1, sprg_sp; /* Restore SP */ \
  154. mfcr %r30; /* Save CR */ \
  155. /* switch to per-thread kstack if intr taken in user mode */ \
  156. mtcr %r31; /* MSR at interrupt time */ \
  157. bf 17, 1f; \
  158. GET_CPUINFO(%r1); /* Per-cpu structure */ \
  159. LOAD %r1, PC_CURPCB(%r1); /* Per-thread kernel stack */ \
  160. 1:
  161. /*
  162. * FRAME_SETUP assumes:
  163. * SPRG{1-3} SP at the time interrupt occured
  164. * savearea r30-r31, DEAR, ESR, xSRR0-1
  165. * r30 CR
  166. * r31 scratch
  167. * r1 kernel stack
  168. *
  169. * sprg_sp - SPRG reg containing SP at the time interrupt occured
  170. * savearea - temp save
  171. * exc - exception number (EXC_xxx)
  172. *
  173. * 1. sets a new frame
  174. * 2. saves in the frame:
  175. * - R0, R1 (SP at the time of interrupt), R2, LR, CR
  176. * - R3-31 (R30-31 first restored from savearea)
  177. * - XER, CTR, DEAR, ESR (from savearea), xSRR0-1
  178. *
  179. * Notes:
  180. * - potential TLB miss: YES, since we make dereferences to kstack, which
  181. * can happen not covered (we can have up to two DTLB misses if fortunate
  182. * enough i.e. when kstack crosses page boundary and both pages are
  183. * untranslated)
  184. */
  185. #ifdef __powerpc64__
  186. #define SAVE_REGS(r) \
  187. std %r3, FRAME_3+CALLSIZE(r); \
  188. std %r4, FRAME_4+CALLSIZE(r); \
  189. std %r5, FRAME_5+CALLSIZE(r); \
  190. std %r6, FRAME_6+CALLSIZE(r); \
  191. std %r7, FRAME_7+CALLSIZE(r); \
  192. std %r8, FRAME_8+CALLSIZE(r); \
  193. std %r9, FRAME_9+CALLSIZE(r); \
  194. std %r10, FRAME_10+CALLSIZE(r); \
  195. std %r11, FRAME_11+CALLSIZE(r); \
  196. std %r12, FRAME_12+CALLSIZE(r); \
  197. std %r13, FRAME_13+CALLSIZE(r); \
  198. std %r14, FRAME_14+CALLSIZE(r); \
  199. std %r15, FRAME_15+CALLSIZE(r); \
  200. std %r16, FRAME_16+CALLSIZE(r); \
  201. std %r17, FRAME_17+CALLSIZE(r); \
  202. std %r18, FRAME_18+CALLSIZE(r); \
  203. std %r19, FRAME_19+CALLSIZE(r); \
  204. std %r20, FRAME_20+CALLSIZE(r); \
  205. std %r21, FRAME_21+CALLSIZE(r); \
  206. std %r22, FRAME_22+CALLSIZE(r); \
  207. std %r23, FRAME_23+CALLSIZE(r); \
  208. std %r24, FRAME_24+CALLSIZE(r); \
  209. std %r25, FRAME_25+CALLSIZE(r); \
  210. std %r26, FRAME_26+CALLSIZE(r); \
  211. std %r27, FRAME_27+CALLSIZE(r); \
  212. std %r28, FRAME_28+CALLSIZE(r); \
  213. std %r29, FRAME_29+CALLSIZE(r); \
  214. std %r30, FRAME_30+CALLSIZE(r); \
  215. std %r31, FRAME_31+CALLSIZE(r)
  216. #define LD_REGS(r) \
  217. ld %r3, FRAME_3+CALLSIZE(r); \
  218. ld %r4, FRAME_4+CALLSIZE(r); \
  219. ld %r5, FRAME_5+CALLSIZE(r); \
  220. ld %r6, FRAME_6+CALLSIZE(r); \
  221. ld %r7, FRAME_7+CALLSIZE(r); \
  222. ld %r8, FRAME_8+CALLSIZE(r); \
  223. ld %r9, FRAME_9+CALLSIZE(r); \
  224. ld %r10, FRAME_10+CALLSIZE(r); \
  225. ld %r11, FRAME_11+CALLSIZE(r); \
  226. ld %r12, FRAME_12+CALLSIZE(r); \
  227. ld %r13, FRAME_13+CALLSIZE(r); \
  228. ld %r14, FRAME_14+CALLSIZE(r); \
  229. ld %r15, FRAME_15+CALLSIZE(r); \
  230. ld %r16, FRAME_16+CALLSIZE(r); \
  231. ld %r17, FRAME_17+CALLSIZE(r); \
  232. ld %r18, FRAME_18+CALLSIZE(r); \
  233. ld %r19, FRAME_19+CALLSIZE(r); \
  234. ld %r20, FRAME_20+CALLSIZE(r); \
  235. ld %r21, FRAME_21+CALLSIZE(r); \
  236. ld %r22, FRAME_22+CALLSIZE(r); \
  237. ld %r23, FRAME_23+CALLSIZE(r); \
  238. ld %r24, FRAME_24+CALLSIZE(r); \
  239. ld %r25, FRAME_25+CALLSIZE(r); \
  240. ld %r26, FRAME_26+CALLSIZE(r); \
  241. ld %r27, FRAME_27+CALLSIZE(r); \
  242. ld %r28, FRAME_28+CALLSIZE(r); \
  243. ld %r29, FRAME_29+CALLSIZE(r); \
  244. ld %r30, FRAME_30+CALLSIZE(r); \
  245. ld %r31, FRAME_31+CALLSIZE(r)
  246. #else
  247. #define SAVE_REGS(r) \
  248. stmw %r3, FRAME_3+CALLSIZE(r)
  249. #define LD_REGS(r) \
  250. lmw %r3, FRAME_3+CALLSIZE(r)
  251. #endif
  252. #define FRAME_SETUP(sprg_sp, savearea, exc) \
  253. mfspr %r31, sprg_sp; /* get saved SP */ \
  254. /* establish a new stack frame and put everything on it */ \
  255. STU %r31, -(FRAMELEN+REDZONE)(%r1); \
  256. STORE %r0, FRAME_0+CALLSIZE(%r1); /* save r0 in the trapframe */ \
  257. STORE %r31, FRAME_1+CALLSIZE(%r1); /* save SP " " */ \
  258. STORE %r2, FRAME_2+CALLSIZE(%r1); /* save r2 " " */ \
  259. mflr %r31; \
  260. STORE %r31, FRAME_LR+CALLSIZE(%r1); /* save LR " " */ \
  261. STORE %r30, FRAME_CR+CALLSIZE(%r1); /* save CR " " */ \
  262. GET_CPUINFO(%r2); \
  263. LOAD %r30, (savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \
  264. LOAD %r31, (savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \
  265. /* save R3-31 */ \
  266. SAVE_REGS(%r1); \
  267. /* save DEAR, ESR */ \
  268. LOAD %r28, (savearea+CPUSAVE_BOOKE_DEAR)(%r2); \
  269. LOAD %r29, (savearea+CPUSAVE_BOOKE_ESR)(%r2); \
  270. STORE %r28, FRAME_BOOKE_DEAR+CALLSIZE(%r1); \
  271. STORE %r29, FRAME_BOOKE_ESR+CALLSIZE(%r1); \
  272. /* save XER, CTR, exc number */ \
  273. mfxer %r3; \
  274. mfctr %r4; \
  275. STORE %r3, FRAME_XER+CALLSIZE(%r1); \
  276. STORE %r4, FRAME_CTR+CALLSIZE(%r1); \
  277. li %r5, exc; \
  278. STORE %r5, FRAME_EXC+CALLSIZE(%r1); \
  279. /* save DBCR0 */ \
  280. mfspr %r3, SPR_DBCR0; \
  281. STORE %r3, FRAME_BOOKE_DBCR0+CALLSIZE(%r1); \
  282. /* save xSSR0-1 */ \
  283. LOAD %r30, (savearea+CPUSAVE_SRR0)(%r2); \
  284. LOAD %r31, (savearea+CPUSAVE_SRR1)(%r2); \
  285. STORE %r30, FRAME_SRR0+CALLSIZE(%r1); \
  286. STORE %r31, FRAME_SRR1+CALLSIZE(%r1); \
  287. LOAD THREAD_REG, PC_CURTHREAD(%r2); \
  288. /*
  289. *
  290. * isrr0-1 - save restore registers to restore CPU state to (may be
  291. * SRR0-1, CSRR0-1, MCSRR0-1
  292. *
  293. * Notes:
  294. * - potential TLB miss: YES. The deref'd kstack may be not covered
  295. */
  296. #define FRAME_LEAVE(isrr0, isrr1) \
  297. wrteei 0; \
  298. /* restore CTR, XER, LR, CR */ \
  299. LOAD %r4, FRAME_CTR+CALLSIZE(%r1); \
  300. LOAD %r5, FRAME_XER+CALLSIZE(%r1); \
  301. LOAD %r6, FRAME_LR+CALLSIZE(%r1); \
  302. LOAD %r7, FRAME_CR+CALLSIZE(%r1); \
  303. mtctr %r4; \
  304. mtxer %r5; \
  305. mtlr %r6; \
  306. mtcr %r7; \
  307. /* restore DBCR0 */ \
  308. LOAD %r4, FRAME_BOOKE_DBCR0+CALLSIZE(%r1); \
  309. mtspr SPR_DBCR0, %r4; \
  310. /* restore xSRR0-1 */ \
  311. LOAD %r30, FRAME_SRR0+CALLSIZE(%r1); \
  312. LOAD %r31, FRAME_SRR1+CALLSIZE(%r1); \
  313. mtspr isrr0, %r30; \
  314. mtspr isrr1, %r31; \
  315. /* restore R2-31, SP */ \
  316. LD_REGS(%r1); \
  317. LOAD %r2, FRAME_2+CALLSIZE(%r1); \
  318. LOAD %r0, FRAME_0+CALLSIZE(%r1); \
  319. LOAD %r1, FRAME_1+CALLSIZE(%r1); \
  320. isync
  321. /*
  322. * TLB miss prolog
  323. *
  324. * saves LR, CR, SRR0-1, R20-31 in the TLBSAVE area
  325. *
  326. * Notes:
  327. * - potential TLB miss: NO. It is crucial that we do not generate a TLB
  328. * miss within the TLB prolog itself!
  329. * - TLBSAVE is always translated
  330. */
  331. #ifdef __powerpc64__
  332. #define TLB_SAVE_REGS(br) \
  333. std %r20, (TLBSAVE_BOOKE_R20)(br); \
  334. std %r21, (TLBSAVE_BOOKE_R21)(br); \
  335. std %r22, (TLBSAVE_BOOKE_R22)(br); \
  336. std %r23, (TLBSAVE_BOOKE_R23)(br); \
  337. std %r24, (TLBSAVE_BOOKE_R24)(br); \
  338. std %r25, (TLBSAVE_BOOKE_R25)(br); \
  339. std %r26, (TLBSAVE_BOOKE_R26)(br); \
  340. std %r27, (TLBSAVE_BOOKE_R27)(br); \
  341. std %r28, (TLBSAVE_BOOKE_R28)(br); \
  342. std %r29, (TLBSAVE_BOOKE_R29)(br); \
  343. std %r30, (TLBSAVE_BOOKE_R30)(br); \
  344. std %r31, (TLBSAVE_BOOKE_R31)(br);
  345. #define TLB_RESTORE_REGS(br) \
  346. ld %r20, (TLBSAVE_BOOKE_R20)(br); \
  347. ld %r21, (TLBSAVE_BOOKE_R21)(br); \
  348. ld %r22, (TLBSAVE_BOOKE_R22)(br); \
  349. ld %r23, (TLBSAVE_BOOKE_R23)(br); \
  350. ld %r24, (TLBSAVE_BOOKE_R24)(br); \
  351. ld %r25, (TLBSAVE_BOOKE_R25)(br); \
  352. ld %r26, (TLBSAVE_BOOKE_R26)(br); \
  353. ld %r27, (TLBSAVE_BOOKE_R27)(br); \
  354. ld %r28, (TLBSAVE_BOOKE_R28)(br); \
  355. ld %r29, (TLBSAVE_BOOKE_R29)(br); \
  356. ld %r30, (TLBSAVE_BOOKE_R30)(br); \
  357. ld %r31, (TLBSAVE_BOOKE_R31)(br);
  358. #define TLB_NEST(outr,inr) \
  359. rlwinm outr, inr, 7, 23, 24; /* 8 x TLBSAVE_LEN */
  360. #else
  361. #define TLB_SAVE_REGS(br) \
  362. stmw %r20, TLBSAVE_BOOKE_R20(br)
  363. #define TLB_RESTORE_REGS(br) \
  364. lmw %r20, TLBSAVE_BOOKE_R20(br)
  365. #define TLB_NEST(outr,inr) \
  366. rlwinm outr, inr, 6, 24, 25; /* 4 x TLBSAVE_LEN */
  367. #endif
  368. #define TLB_PROLOG \
  369. mtspr SPR_SPRG4, %r1; /* Save SP */ \
  370. mtspr SPR_SPRG5, %r28; \
  371. mtspr SPR_SPRG6, %r29; \
  372. /* calculate TLB nesting level and TLBSAVE instance address */ \
  373. GET_CPUINFO(%r1); /* Per-cpu structure */ \
  374. LOAD %r28, PC_BOOKE_TLB_LEVEL(%r1); \
  375. TLB_NEST(%r29,%r28); \
  376. addi %r28, %r28, 1; \
  377. STORE %r28, PC_BOOKE_TLB_LEVEL(%r1); \
  378. addi %r29, %r29, PC_BOOKE_TLBSAVE@l; \
  379. add %r1, %r1, %r29; /* current TLBSAVE ptr */ \
  380. \
  381. /* save R20-31 */ \
  382. mfspr %r28, SPR_SPRG5; \
  383. mfspr %r29, SPR_SPRG6; \
  384. TLB_SAVE_REGS(%r1); \
  385. /* save LR, CR */ \
  386. mflr %r30; \
  387. mfcr %r31; \
  388. STORE %r30, (TLBSAVE_BOOKE_LR)(%r1); \
  389. STORE %r31, (TLBSAVE_BOOKE_CR)(%r1); \
  390. /* save SRR0-1 */ \
  391. mfsrr0 %r30; /* execution addr at interrupt time */ \
  392. mfsrr1 %r31; /* MSR at interrupt time*/ \
  393. STORE %r30, (TLBSAVE_BOOKE_SRR0)(%r1); /* save SRR0 */ \
  394. STORE %r31, (TLBSAVE_BOOKE_SRR1)(%r1); /* save SRR1 */ \
  395. isync; \
  396. mfspr %r1, SPR_SPRG4
  397. /*
  398. * restores LR, CR, SRR0-1, R20-31 from the TLBSAVE area
  399. *
  400. * same notes as for the TLB_PROLOG
  401. */
  402. #define TLB_RESTORE \
  403. mtspr SPR_SPRG4, %r1; /* Save SP */ \
  404. GET_CPUINFO(%r1); /* Per-cpu structure */ \
  405. /* calculate TLB nesting level and TLBSAVE instance addr */ \
  406. LOAD %r28, PC_BOOKE_TLB_LEVEL(%r1); \
  407. subi %r28, %r28, 1; \
  408. STORE %r28, PC_BOOKE_TLB_LEVEL(%r1); \
  409. TLB_NEST(%r29,%r28); \
  410. addi %r29, %r29, PC_BOOKE_TLBSAVE@l; \
  411. add %r1, %r1, %r29; \
  412. \
  413. /* restore LR, CR */ \
  414. LOAD %r30, (TLBSAVE_BOOKE_LR)(%r1); \
  415. LOAD %r31, (TLBSAVE_BOOKE_CR)(%r1); \
  416. mtlr %r30; \
  417. mtcr %r31; \
  418. /* restore SRR0-1 */ \
  419. LOAD %r30, (TLBSAVE_BOOKE_SRR0)(%r1); \
  420. LOAD %r31, (TLBSAVE_BOOKE_SRR1)(%r1); \
  421. mtsrr0 %r30; \
  422. mtsrr1 %r31; \
  423. /* restore R20-31 */ \
  424. TLB_RESTORE_REGS(%r1); \
  425. mfspr %r1, SPR_SPRG4
  426. #ifdef SMP
  427. #define TLB_LOCK \
  428. GET_CPUINFO(%r20); \
  429. LOAD %r21, PC_CURTHREAD(%r20); \
  430. LOAD %r22, PC_BOOKE_TLB_LOCK(%r20); \
  431. \
  432. 1: LOADX %r23, 0, %r22; \
  433. CMPI %r23, TLB_UNLOCKED; \
  434. beq 2f; \
  435. \
  436. /* check if this is recursion */ \
  437. CMPL cr0, %r21, %r23; \
  438. bne- 1b; \
  439. \
  440. 2: /* try to acquire lock */ \
  441. STOREX %r21, 0, %r22; \
  442. bne- 1b; \
  443. \
  444. /* got it, update recursion counter */ \
  445. lwz %r21, RES_RECURSE(%r22); \
  446. addi %r21, %r21, 1; \
  447. stw %r21, RES_RECURSE(%r22); \
  448. isync; \
  449. msync
  450. #define TLB_UNLOCK \
  451. GET_CPUINFO(%r20); \
  452. LOAD %r21, PC_CURTHREAD(%r20); \
  453. LOAD %r22, PC_BOOKE_TLB_LOCK(%r20); \
  454. \
  455. /* update recursion counter */ \
  456. lwz %r23, RES_RECURSE(%r22); \
  457. subi %r23, %r23, 1; \
  458. stw %r23, RES_RECURSE(%r22); \
  459. \
  460. cmplwi %r23, 0; \
  461. bne 1f; \
  462. isync; \
  463. msync; \
  464. \
  465. /* release the lock */ \
  466. li %r23, TLB_UNLOCKED; \
  467. STORE %r23, 0(%r22); \
  468. 1: isync; \
  469. msync
  470. #else
  471. #define TLB_LOCK
  472. #define TLB_UNLOCK
  473. #endif /* SMP */
  474. #define INTERRUPT(label) \
  475. .globl label; \
  476. .align 5; \
  477. CNAME(label):
  478. /*
  479. * Interrupt handling routines in BookE can be flexibly placed and do not have
  480. * to live in pre-defined vectors location. Note they need to be TLB-mapped at
  481. * all times in order to be able to handle exceptions. We thus arrange for
  482. * them to be part of kernel text which is always TLB-accessible.
  483. *
  484. * The interrupt handling routines have to be 16 bytes aligned: we align them
  485. * to 32 bytes (cache line length) which supposedly performs better.
  486. *
  487. */
  488. .text
  489. .globl CNAME(interrupt_vector_base)
  490. .align 5
  491. interrupt_vector_base:
  492. /*****************************************************************************
  493. * Catch-all handler to handle uninstalled IVORs
  494. ****************************************************************************/
  495. INTERRUPT(int_unknown)
  496. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  497. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_RSVD)
  498. b trap_common
  499. /*****************************************************************************
  500. * Critical input interrupt
  501. ****************************************************************************/
  502. INTERRUPT(int_critical_input)
  503. STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
  504. FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_CRIT)
  505. GET_TOCBASE(%r2)
  506. addi %r3, %r1, CALLSIZE
  507. bl CNAME(powerpc_interrupt)
  508. TOC_RESTORE
  509. FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
  510. rfci
  511. /*****************************************************************************
  512. * Machine check interrupt
  513. ****************************************************************************/
  514. INTERRUPT(int_machine_check)
  515. STANDARD_PROLOG(SPR_SPRG3, PC_BOOKE_MCHKSAVE, SPR_MCSRR0, SPR_MCSRR1)
  516. FRAME_SETUP(SPR_SPRG3, PC_BOOKE_MCHKSAVE, EXC_MCHK)
  517. GET_TOCBASE(%r2)
  518. addi %r3, %r1, CALLSIZE
  519. bl CNAME(powerpc_interrupt)
  520. TOC_RESTORE
  521. FRAME_LEAVE(SPR_MCSRR0, SPR_MCSRR1)
  522. rfmci
  523. /*****************************************************************************
  524. * Data storage interrupt
  525. ****************************************************************************/
  526. INTERRUPT(int_data_storage)
  527. STANDARD_PROLOG(SPR_SPRG1, PC_DISISAVE, SPR_SRR0, SPR_SRR1)
  528. FRAME_SETUP(SPR_SPRG1, PC_DISISAVE, EXC_DSI)
  529. b trap_common
  530. /*****************************************************************************
  531. * Instruction storage interrupt
  532. ****************************************************************************/
  533. INTERRUPT(int_instr_storage)
  534. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  535. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ISI)
  536. b trap_common
  537. /*****************************************************************************
  538. * External input interrupt
  539. ****************************************************************************/
  540. INTERRUPT(int_external_input)
  541. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  542. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI)
  543. b trap_common
  544. INTERRUPT(int_alignment)
  545. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  546. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ALI)
  547. b trap_common
  548. INTERRUPT(int_program)
  549. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  550. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_PGM)
  551. b trap_common
  552. INTERRUPT(int_fpu)
  553. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  554. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FPU)
  555. b trap_common
  556. /*****************************************************************************
  557. * System call
  558. ****************************************************************************/
  559. INTERRUPT(int_syscall)
  560. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  561. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SC)
  562. b trap_common
  563. /*****************************************************************************
  564. * Decrementer interrupt
  565. ****************************************************************************/
  566. INTERRUPT(int_decrementer)
  567. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  568. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_DECR)
  569. b trap_common
  570. /*****************************************************************************
  571. * Fixed interval timer
  572. ****************************************************************************/
  573. INTERRUPT(int_fixed_interval_timer)
  574. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  575. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FIT)
  576. b trap_common
  577. /*****************************************************************************
  578. * Watchdog interrupt
  579. ****************************************************************************/
  580. INTERRUPT(int_watchdog)
  581. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  582. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_WDOG)
  583. b trap_common
  584. /*****************************************************************************
  585. * Altivec Unavailable interrupt
  586. ****************************************************************************/
  587. INTERRUPT(int_vec)
  588. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  589. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_VEC)
  590. b trap_common
  591. /*****************************************************************************
  592. * Altivec Assist interrupt
  593. ****************************************************************************/
  594. INTERRUPT(int_vecast)
  595. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  596. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_VECAST_E)
  597. b trap_common
  598. #ifdef __SPE__
  599. /*****************************************************************************
  600. * Floating point Assist interrupt
  601. ****************************************************************************/
  602. INTERRUPT(int_spe_fpdata)
  603. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  604. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPD)
  605. addi %r3, %r1, CALLSIZE
  606. bl spe_handle_fpdata
  607. FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
  608. rfi
  609. INTERRUPT(int_spe_fpround)
  610. STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  611. FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SPFPR)
  612. addi %r3, %r1, CALLSIZE
  613. bl spe_handle_fpround
  614. FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
  615. rfi
  616. #endif
  617. #ifdef HWPMC_HOOKS
  618. /*****************************************************************************
  619. * PMC Interrupt
  620. ****************************************************************************/
  621. INTERRUPT(int_performance_counter)
  622. STANDARD_PROLOG(SPR_SPRG3, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
  623. FRAME_SETUP(SPR_SPRG3, PC_TEMPSAVE, EXC_PERF)
  624. b trap_common
  625. #endif
  626. /*****************************************************************************
  627. * Data TLB miss interrupt
  628. *
  629. * There can be nested TLB misses - while handling a TLB miss we reference
  630. * data structures that may be not covered by translations. We support up to
  631. * TLB_NESTED_MAX-1 nested misses.
  632. *
  633. * Registers use:
  634. * r31 - dear
  635. * r30 - unused
  636. * r29 - saved mas0
  637. * r28 - saved mas1
  638. * r27 - saved mas2
  639. * r26 - pmap address
  640. * r25 - pte address
  641. *
  642. * r20:r23 - scratch registers
  643. ****************************************************************************/
  644. INTERRUPT(int_data_tlb_error)
  645. TLB_PROLOG
  646. TLB_LOCK
  647. mfspr %r31, SPR_DEAR
  648. /*
  649. * Save MAS0-MAS2 registers. There might be another tlb miss during
  650. * pte lookup overwriting current contents (which was hw filled).
  651. */
  652. mfspr %r29, SPR_MAS0
  653. mfspr %r28, SPR_MAS1
  654. mfspr %r27, SPR_MAS2
  655. /* Check faulting address. */
  656. LOAD_ADDR(%r21, VM_MAXUSER_ADDRESS)
  657. CMPL cr0, %r31, %r21
  658. blt search_user_pmap
  659. /* If it's kernel address, allow only supervisor mode misses. */
  660. mfsrr1 %r21
  661. mtcr %r21
  662. bt 17, search_failed /* check MSR[PR] */
  663. #ifdef __powerpc64__
  664. srdi %r21, %r31, 48
  665. cmpldi cr0, %r21, VM_MIN_KERNEL_ADDRESS@highest
  666. #else
  667. lis %r21, VM_MIN_KERNEL_ADDRESS@h
  668. cmplw cr0, %r31, %r21
  669. #endif
  670. blt search_failed
  671. search_kernel_pmap:
  672. /* Load r26 with kernel_pmap address */
  673. bl 1f
  674. #ifdef __powerpc64__
  675. .llong kernel_pmap_store-.
  676. #else
  677. .long kernel_pmap_store-.
  678. #endif
  679. 1: mflr %r21
  680. LOAD %r26, 0(%r21)
  681. add %r26, %r21, %r26 /* kernel_pmap_store in r26 */
  682. /* Force kernel tid, set TID to 0 in MAS1. */
  683. li %r21, 0
  684. rlwimi %r28, %r21, 0, 8, 15 /* clear TID bits */
  685. tlb_miss_handle:
  686. /* This may result in nested tlb miss. */
  687. bl pte_lookup /* returns PTE address in R25 */
  688. CMPI %r25, 0 /* pte found? */
  689. beq search_failed
  690. /* Finish up, write TLB entry. */
  691. bl tlb_fill_entry
  692. tlb_miss_return:
  693. TLB_UNLOCK
  694. TLB_RESTORE
  695. rfi
  696. search_user_pmap:
  697. /* Load r26 with current user space process pmap */
  698. GET_CPUINFO(%r26)
  699. LOAD %r26, PC_CURPMAP(%r26)
  700. b tlb_miss_handle
  701. search_failed:
  702. /*
  703. * Whenever we don't find a TLB mapping in PT, set a TLB0 entry with
  704. * the faulting virtual address anyway, but put a fake RPN and no
  705. * access rights. This should cause a following {D,I}SI exception.
  706. */
  707. lis %r23, 0xffff0000@h /* revoke all permissions */
  708. /* Load MAS registers. */
  709. mtspr SPR_MAS0, %r29
  710. mtspr SPR_MAS1, %r28
  711. mtspr SPR_MAS2, %r27
  712. mtspr SPR_MAS3, %r23
  713. li %r23, 0
  714. mtspr SPR_MAS7, %r23
  715. isync
  716. tlbwe
  717. msync
  718. isync
  719. b tlb_miss_return
  720. /*****************************************************************************
  721. *
  722. * Return pte address that corresponds to given pmap/va. If there is no valid
  723. * entry return 0.
  724. *
  725. * input: r26 - pmap
  726. * input: r31 - dear
  727. * output: r25 - pte address
  728. *
  729. * scratch regs used: r21
  730. *
  731. ****************************************************************************/
  732. pte_lookup:
  733. CMPI %r26, 0
  734. beq 1f /* fail quickly if pmap is invalid */
  735. #ifdef __powerpc64__
  736. rldicl %r21, %r31, (64 - PG_ROOT_L), (64 - PG_ROOT_NUM) /* pp2d offset */
  737. slwi %r21, %r21, PG_ROOT_ENTRY_SHIFT /* multiply by pp2d entry size */
  738. ld %r25, PM_ROOT(%r26) /* pmap pm_pp2d[] address */
  739. ldx %r25, %r25, %r21 /* get pdir address, i.e. pmap->pm_pp2d[pp2d_idx] * */
  740. cmpdi %r25, 0
  741. beq 2f
  742. rldicl %r21, %r31, (64 - PDIR_L1_L), (64 - PDIR_L1_NUM) /* pp2d offset */
  743. slwi %r21, %r21, PDIR_L1_ENTRY_SHIFT /* multiply by pp2d entry size */
  744. ldx %r25, %r25, %r21 /* get pdir address, i.e. pmap->pm_pp2d[pp2d_idx] * */
  745. cmpdi %r25, 0
  746. beq 2f
  747. rldicl %r21, %r31, (64 - PDIR_L), (64 - PDIR_NUM) /* pdir offset */
  748. slwi %r21, %r21, PDIR_ENTRY_SHIFT /* multiply by pdir entry size */
  749. ldx %r25, %r25, %r21 /* get ptbl address, i.e. pmap->pm_pp2d[pp2d_idx][pdir_idx] */
  750. cmpdi %r25, 0
  751. beq 2f
  752. rldicl %r21, %r31, (64 - PTBL_L), (64 - PTBL_NUM) /* ptbl offset */
  753. slwi %r21, %r21, PTBL_ENTRY_SHIFT /* multiply by pte entry size */
  754. #else
  755. srwi %r21, %r31, PDIR_SHIFT /* pdir offset */
  756. slwi %r21, %r21, PDIR_ENTRY_SHIFT /* multiply by pdir entry size */
  757. lwz %r25, PM_PDIR(%r26) /* pmap pm_dir[] address */
  758. /*
  759. * Get ptbl address, i.e. pmap->pm_pdir[pdir_idx]
  760. * This load may cause a Data TLB miss for non-kernel pmap!
  761. */
  762. lwzx %r25, %r25, %r21 /* offset within pm_pdir[] table */
  763. cmpwi %r25, 0
  764. beq 2f
  765. lis %r21, PTBL_MASK@h
  766. ori %r21, %r21, PTBL_MASK@l
  767. and %r21, %r21, %r31
  768. /* ptbl offset, multiply by ptbl entry size */
  769. srwi %r21, %r21, (PTBL_SHIFT - PTBL_ENTRY_SHIFT)
  770. #endif
  771. add %r25, %r25, %r21 /* address of pte entry */
  772. /*
  773. * Get pte->flags
  774. * This load may cause a Data TLB miss for non-kernel pmap!
  775. */
  776. lwz %r21, PTE_FLAGS(%r25)
  777. andi. %r21, %r21, PTE_VALID@l
  778. bne 2f
  779. 1:
  780. li %r25, 0
  781. 2:
  782. blr
  783. /*****************************************************************************
  784. *
  785. * Load MAS1-MAS3 registers with data, write TLB entry
  786. *
  787. * input:
  788. * r29 - mas0
  789. * r28 - mas1
  790. * r27 - mas2
  791. * r25 - pte
  792. *
  793. * output: none
  794. *
  795. * scratch regs: r21-r23
  796. *
  797. ****************************************************************************/
  798. tlb_fill_entry:
  799. /*
  800. * Update PTE flags: we have to do it atomically, as pmap_protect()
  801. * running on other CPUs could attempt to update the flags at the same
  802. * time.
  803. */
  804. li %r23, PTE_FLAGS
  805. 1:
  806. lwarx %r21, %r23, %r25 /* get pte->flags */
  807. oris %r21, %r21, PTE_REFERENCED@h /* set referenced bit */
  808. andi. %r22, %r21, (PTE_SW | PTE_UW)@l /* check if writable */
  809. beq 2f
  810. ori %r21, %r21, PTE_MODIFIED@l /* set modified bit */
  811. 2:
  812. stwcx. %r21, %r23, %r25 /* write it back */
  813. bne- 1b
  814. /* Update MAS2. */
  815. rlwimi %r27, %r21, 13, 27, 30 /* insert WIMG bits from pte */
  816. /* Setup MAS3 value in r23. */
  817. LOAD %r23, PTE_RPN(%r25) /* get pte->rpn */
  818. #ifdef __powerpc64__
  819. rldicr %r22, %r23, 52, 51 /* extract MAS3 portion of RPN */
  820. rldicl %r23, %r23, 20, 54 /* extract MAS7 portion of RPN */
  821. rlwimi %r22, %r21, 30, 26, 31 /* insert protection bits from pte */
  822. #else
  823. rlwinm %r22, %r23, 20, 0, 11 /* extract MAS3 portion of RPN */
  824. rlwimi %r22, %r21, 30, 26, 31 /* insert protection bits from pte */
  825. rlwimi %r22, %r21, 20, 12, 19 /* insert lower 8 RPN bits to MAS3 */
  826. rlwinm %r23, %r23, 20, 24, 31 /* MAS7 portion of RPN */
  827. #endif
  828. /* Load MAS registers. */
  829. mtspr SPR_MAS0, %r29
  830. mtspr SPR_MAS1, %r28
  831. mtspr SPR_MAS2, %r27
  832. mtspr SPR_MAS3, %r22
  833. mtspr SPR_MAS7, %r23
  834. isync
  835. tlbwe
  836. isync
  837. msync
  838. blr
  839. /*****************************************************************************
  840. * Instruction TLB miss interrupt
  841. *
  842. * Same notes as for the Data TLB miss
  843. ****************************************************************************/
  844. INTERRUPT(int_inst_tlb_error)
  845. TLB_PROLOG
  846. TLB_LOCK
  847. mfsrr0 %r31 /* faulting address */
  848. /*
  849. * Save MAS0-MAS2 registers. There might be another tlb miss during pte
  850. * lookup overwriting current contents (which was hw filled).
  851. */
  852. mfspr %r29, SPR_MAS0
  853. mfspr %r28, SPR_MAS1
  854. mfspr %r27, SPR_MAS2
  855. mfsrr1 %r21
  856. mtcr %r21
  857. /* check MSR[PR] */
  858. bt 17, search_user_pmap
  859. b search_kernel_pmap
  860. .globl interrupt_vector_top
  861. interrupt_vector_top:
  862. /*****************************************************************************
  863. * Debug interrupt
  864. ****************************************************************************/
  865. INTERRUPT(int_debug)
  866. STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
  867. FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
  868. bl int_debug_int
  869. FRAME_LEAVE(SPR_CSRR0, SPR_CSRR1)
  870. rfci
  871. INTERRUPT(int_debug_ed)
  872. STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_DSRR0, SPR_DSRR1)
  873. FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
  874. bl int_debug_int
  875. FRAME_LEAVE(SPR_DSRR0, SPR_DSRR1)
  876. rfdi
  877. /* .long 0x4c00004e */
  878. /* Internal helper for debug interrupt handling. */
  879. /* Common code between e500v1/v2 and e500mc-based cores. */
  880. int_debug_int:
  881. mflr %r14
  882. GET_CPUINFO(%r3)
  883. LOAD %r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0)(%r3)
  884. bl 0f
  885. ADDR(interrupt_vector_base-.)
  886. ADDR(interrupt_vector_top-.)
  887. 0: mflr %r5
  888. LOAD %r4,0(%r5) /* interrupt_vector_base in r4 */
  889. add %r4,%r4,%r5
  890. CMPL cr0, %r3, %r4
  891. blt trap_common
  892. LOAD %r4,WORD_SIZE(%r5) /* interrupt_vector_top in r4 */
  893. add %r4,%r4,%r5
  894. addi %r4,%r4,4
  895. CMPL cr0, %r3, %r4
  896. bge trap_common
  897. /* Disable single-stepping for the interrupt handlers. */
  898. LOAD %r3, FRAME_SRR1+CALLSIZE(%r1);
  899. rlwinm %r3, %r3, 0, 23, 21
  900. STORE %r3, FRAME_SRR1+CALLSIZE(%r1);
  901. /* Restore srr0 and srr1 as they could have been clobbered. */
  902. GET_CPUINFO(%r4)
  903. LOAD %r3, (PC_BOOKE_CRITSAVE+BOOKE_CRITSAVE_SRR0)(%r4);
  904. mtspr SPR_SRR0, %r3
  905. LOAD %r4, (PC_BOOKE_CRITSAVE+BOOKE_CRITSAVE_SRR1)(%r4);
  906. mtspr SPR_SRR1, %r4
  907. mtlr %r14
  908. blr
  909. /*****************************************************************************
  910. * Common trap code
  911. ****************************************************************************/
  912. trap_common:
  913. /* Call C trap dispatcher */
  914. GET_TOCBASE(%r2)
  915. addi %r3, %r1, CALLSIZE
  916. bl CNAME(powerpc_interrupt)
  917. TOC_RESTORE
  918. .globl CNAME(trapexit) /* exported for db_backtrace use */
  919. CNAME(trapexit):
  920. /* disable interrupts */
  921. wrteei 0
  922. /* Test AST pending - makes sense for user process only */
  923. LOAD %r5, FRAME_SRR1+CALLSIZE(%r1)
  924. mtcr %r5
  925. bf 17, 1f
  926. GET_CPUINFO(%r3)
  927. LOAD %r4, PC_CURTHREAD(%r3)
  928. lwz %r4, TD_FLAGS(%r4)
  929. lis %r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@h
  930. ori %r5, %r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@l
  931. and. %r4, %r4, %r5
  932. beq 1f
  933. /* re-enable interrupts before calling ast() */
  934. wrteei 1
  935. addi %r3, %r1, CALLSIZE
  936. bl CNAME(ast)
  937. TOC_RESTORE
  938. .globl CNAME(asttrapexit) /* db_backtrace code sentinel #2 */
  939. CNAME(asttrapexit):
  940. b trapexit /* test ast ret value ? */
  941. 1:
  942. FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
  943. rfi
  944. #if defined(KDB)
  945. /*
  946. * Deliberate entry to dbtrap
  947. */
  948. /* .globl CNAME(breakpoint)*/
  949. ASENTRY_NOPROF(breakpoint)
  950. mtsprg1 %r1
  951. mfmsr %r3
  952. mtsrr1 %r3
  953. li %r4, ~(PSL_EE | PSL_ME)@l
  954. oris %r4, %r4, ~(PSL_EE | PSL_ME)@h
  955. and %r3, %r3, %r4
  956. mtmsr %r3 /* disable interrupts */
  957. isync
  958. GET_CPUINFO(%r3)
  959. STORE %r30, (PC_DBSAVE+CPUSAVE_R30)(%r3)
  960. STORE %r31, (PC_DBSAVE+CPUSAVE_R31)(%r3)
  961. mflr %r31
  962. mtsrr0 %r31
  963. mfspr %r30, SPR_DEAR
  964. mfspr %r31, SPR_ESR
  965. STORE %r30, (PC_DBSAVE+CPUSAVE_BOOKE_DEAR)(%r3)
  966. STORE %r31, (PC_DBSAVE+CPUSAVE_BOOKE_ESR)(%r3)
  967. mfsrr0 %r30
  968. mfsrr1 %r31
  969. STORE %r30, (PC_DBSAVE+CPUSAVE_SRR0)(%r3)
  970. STORE %r31, (PC_DBSAVE+CPUSAVE_SRR1)(%r3)
  971. isync
  972. mfcr %r30
  973. /*
  974. * Now the kdb trap catching code.
  975. */
  976. dbtrap:
  977. FRAME_SETUP(SPR_SPRG1, PC_DBSAVE, EXC_DEBUG)
  978. /* Call C trap code: */
  979. GET_TOCBASE(%r2)
  980. addi %r3, %r1, CALLSIZE
  981. bl CNAME(db_trap_glue)
  982. TOC_RESTORE
  983. or. %r3, %r3, %r3
  984. bne dbleave
  985. /* This wasn't for KDB, so switch to real trap: */
  986. b trap_common
  987. dbleave:
  988. FRAME_LEAVE(SPR_SRR0, SPR_SRR1)
  989. rfi
  990. ASEND(breakpoint)
  991. #endif /* KDB */
  992. #ifdef SMP
  993. ENTRY(tlb_lock)
  994. GET_CPUINFO(%r5)
  995. LOAD %r5, PC_CURTHREAD(%r5)
  996. 1: LOADX %r4, 0, %r3
  997. CMPI %r4, TLB_UNLOCKED
  998. bne 1b
  999. STOREX %r5, 0, %r3
  1000. bne- 1b
  1001. isync
  1002. msync
  1003. blr
  1004. END(tlb_lock)
  1005. ENTRY(tlb_unlock)
  1006. isync
  1007. msync
  1008. li %r4, TLB_UNLOCKED
  1009. STORE %r4, 0(%r3)
  1010. isync
  1011. msync
  1012. blr
  1013. END(tlb_unlock)
  1014. /*
  1015. * TLB miss spin locks. For each CPU we have a reservation granule (32 bytes);
  1016. * only a single word from this granule will actually be used as a spin lock
  1017. * for mutual exclusion between TLB miss handler and pmap layer that
  1018. * manipulates page table contents.
  1019. */
  1020. .data
  1021. .align 5
  1022. GLOBAL(tlb0_miss_locks)
  1023. .space RES_GRANULE * MAXCPU
  1024. #endif