head.S 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * OpenRISC head.S
  4. *
  5. * Linux architectural port borrowing liberally from similar works of
  6. * others. All original copyrights apply as per the original source
  7. * declaration.
  8. *
  9. * Modifications for the OpenRISC architecture:
  10. * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
  11. * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
  12. */
  13. #include <linux/linkage.h>
  14. #include <linux/threads.h>
  15. #include <linux/errno.h>
  16. #include <linux/init.h>
  17. #include <linux/serial_reg.h>
  18. #include <linux/pgtable.h>
  19. #include <asm/processor.h>
  20. #include <asm/page.h>
  21. #include <asm/mmu.h>
  22. #include <asm/thread_info.h>
  23. #include <asm/cache.h>
  24. #include <asm/spr_defs.h>
  25. #include <asm/asm-offsets.h>
  26. #include <linux/of_fdt.h>
  27. #define tophys(rd,rs) \
  28. l.movhi rd,hi(-KERNELBASE) ;\
  29. l.add rd,rd,rs
  30. #define CLEAR_GPR(gpr) \
  31. l.movhi gpr,0x0
  32. #define LOAD_SYMBOL_2_GPR(gpr,symbol) \
  33. l.movhi gpr,hi(symbol) ;\
  34. l.ori gpr,gpr,lo(symbol)
  35. #define UART_BASE_ADD 0x90000000
  36. #define EXCEPTION_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
  37. #define SYSCALL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
  38. /* ============================================[ tmp store locations ]=== */
  39. #define SPR_SHADOW_GPR(x) ((x) + SPR_GPR_BASE + 32)
  40. /*
  41. * emergency_print temporary stores
  42. */
  43. #ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
  44. #define EMERGENCY_PRINT_STORE_GPR4 l.mtspr r0,r4,SPR_SHADOW_GPR(14)
  45. #define EMERGENCY_PRINT_LOAD_GPR4 l.mfspr r4,r0,SPR_SHADOW_GPR(14)
  46. #define EMERGENCY_PRINT_STORE_GPR5 l.mtspr r0,r5,SPR_SHADOW_GPR(15)
  47. #define EMERGENCY_PRINT_LOAD_GPR5 l.mfspr r5,r0,SPR_SHADOW_GPR(15)
  48. #define EMERGENCY_PRINT_STORE_GPR6 l.mtspr r0,r6,SPR_SHADOW_GPR(16)
  49. #define EMERGENCY_PRINT_LOAD_GPR6 l.mfspr r6,r0,SPR_SHADOW_GPR(16)
  50. #define EMERGENCY_PRINT_STORE_GPR7 l.mtspr r0,r7,SPR_SHADOW_GPR(7)
  51. #define EMERGENCY_PRINT_LOAD_GPR7 l.mfspr r7,r0,SPR_SHADOW_GPR(7)
  52. #define EMERGENCY_PRINT_STORE_GPR8 l.mtspr r0,r8,SPR_SHADOW_GPR(8)
  53. #define EMERGENCY_PRINT_LOAD_GPR8 l.mfspr r8,r0,SPR_SHADOW_GPR(8)
  54. #define EMERGENCY_PRINT_STORE_GPR9 l.mtspr r0,r9,SPR_SHADOW_GPR(9)
  55. #define EMERGENCY_PRINT_LOAD_GPR9 l.mfspr r9,r0,SPR_SHADOW_GPR(9)
  56. #else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
  57. #define EMERGENCY_PRINT_STORE_GPR4 l.sw 0x20(r0),r4
  58. #define EMERGENCY_PRINT_LOAD_GPR4 l.lwz r4,0x20(r0)
  59. #define EMERGENCY_PRINT_STORE_GPR5 l.sw 0x24(r0),r5
  60. #define EMERGENCY_PRINT_LOAD_GPR5 l.lwz r5,0x24(r0)
  61. #define EMERGENCY_PRINT_STORE_GPR6 l.sw 0x28(r0),r6
  62. #define EMERGENCY_PRINT_LOAD_GPR6 l.lwz r6,0x28(r0)
  63. #define EMERGENCY_PRINT_STORE_GPR7 l.sw 0x2c(r0),r7
  64. #define EMERGENCY_PRINT_LOAD_GPR7 l.lwz r7,0x2c(r0)
  65. #define EMERGENCY_PRINT_STORE_GPR8 l.sw 0x30(r0),r8
  66. #define EMERGENCY_PRINT_LOAD_GPR8 l.lwz r8,0x30(r0)
  67. #define EMERGENCY_PRINT_STORE_GPR9 l.sw 0x34(r0),r9
  68. #define EMERGENCY_PRINT_LOAD_GPR9 l.lwz r9,0x34(r0)
  69. #endif
  70. /*
  71. * TLB miss handlers temorary stores
  72. */
  73. #ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
  74. #define EXCEPTION_STORE_GPR2 l.mtspr r0,r2,SPR_SHADOW_GPR(2)
  75. #define EXCEPTION_LOAD_GPR2 l.mfspr r2,r0,SPR_SHADOW_GPR(2)
  76. #define EXCEPTION_STORE_GPR3 l.mtspr r0,r3,SPR_SHADOW_GPR(3)
  77. #define EXCEPTION_LOAD_GPR3 l.mfspr r3,r0,SPR_SHADOW_GPR(3)
  78. #define EXCEPTION_STORE_GPR4 l.mtspr r0,r4,SPR_SHADOW_GPR(4)
  79. #define EXCEPTION_LOAD_GPR4 l.mfspr r4,r0,SPR_SHADOW_GPR(4)
  80. #define EXCEPTION_STORE_GPR5 l.mtspr r0,r5,SPR_SHADOW_GPR(5)
  81. #define EXCEPTION_LOAD_GPR5 l.mfspr r5,r0,SPR_SHADOW_GPR(5)
  82. #define EXCEPTION_STORE_GPR6 l.mtspr r0,r6,SPR_SHADOW_GPR(6)
  83. #define EXCEPTION_LOAD_GPR6 l.mfspr r6,r0,SPR_SHADOW_GPR(6)
  84. #else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
  85. #define EXCEPTION_STORE_GPR2 l.sw 0x64(r0),r2
  86. #define EXCEPTION_LOAD_GPR2 l.lwz r2,0x64(r0)
  87. #define EXCEPTION_STORE_GPR3 l.sw 0x68(r0),r3
  88. #define EXCEPTION_LOAD_GPR3 l.lwz r3,0x68(r0)
  89. #define EXCEPTION_STORE_GPR4 l.sw 0x6c(r0),r4
  90. #define EXCEPTION_LOAD_GPR4 l.lwz r4,0x6c(r0)
  91. #define EXCEPTION_STORE_GPR5 l.sw 0x70(r0),r5
  92. #define EXCEPTION_LOAD_GPR5 l.lwz r5,0x70(r0)
  93. #define EXCEPTION_STORE_GPR6 l.sw 0x74(r0),r6
  94. #define EXCEPTION_LOAD_GPR6 l.lwz r6,0x74(r0)
  95. #endif
  96. /*
  97. * EXCEPTION_HANDLE temporary stores
  98. */
  99. #ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
  100. #define EXCEPTION_T_STORE_GPR30 l.mtspr r0,r30,SPR_SHADOW_GPR(30)
  101. #define EXCEPTION_T_LOAD_GPR30(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(30)
  102. #define EXCEPTION_T_STORE_GPR10 l.mtspr r0,r10,SPR_SHADOW_GPR(10)
  103. #define EXCEPTION_T_LOAD_GPR10(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(10)
  104. #define EXCEPTION_T_STORE_SP l.mtspr r0,r1,SPR_SHADOW_GPR(1)
  105. #define EXCEPTION_T_LOAD_SP(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(1)
  106. #else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
  107. #define EXCEPTION_T_STORE_GPR30 l.sw 0x78(r0),r30
  108. #define EXCEPTION_T_LOAD_GPR30(reg) l.lwz reg,0x78(r0)
  109. #define EXCEPTION_T_STORE_GPR10 l.sw 0x7c(r0),r10
  110. #define EXCEPTION_T_LOAD_GPR10(reg) l.lwz reg,0x7c(r0)
  111. #define EXCEPTION_T_STORE_SP l.sw 0x80(r0),r1
  112. #define EXCEPTION_T_LOAD_SP(reg) l.lwz reg,0x80(r0)
  113. #endif
  114. /* =========================================================[ macros ]=== */
  115. #ifdef CONFIG_SMP
  116. #define GET_CURRENT_PGD(reg,t1) \
  117. LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
  118. l.mfspr t1,r0,SPR_COREID ;\
  119. l.slli t1,t1,2 ;\
  120. l.add reg,reg,t1 ;\
  121. tophys (t1,reg) ;\
  122. l.lwz reg,0(t1)
  123. #else
  124. #define GET_CURRENT_PGD(reg,t1) \
  125. LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
  126. tophys (t1,reg) ;\
  127. l.lwz reg,0(t1)
  128. #endif
  129. /* Load r10 from current_thread_info_set - clobbers r1 and r30 */
  130. #ifdef CONFIG_SMP
  131. #define GET_CURRENT_THREAD_INFO \
  132. LOAD_SYMBOL_2_GPR(r1,current_thread_info_set) ;\
  133. tophys (r30,r1) ;\
  134. l.mfspr r10,r0,SPR_COREID ;\
  135. l.slli r10,r10,2 ;\
  136. l.add r30,r30,r10 ;\
  137. /* r10: current_thread_info */ ;\
  138. l.lwz r10,0(r30)
  139. #else
  140. #define GET_CURRENT_THREAD_INFO \
  141. LOAD_SYMBOL_2_GPR(r1,current_thread_info_set) ;\
  142. tophys (r30,r1) ;\
  143. /* r10: current_thread_info */ ;\
  144. l.lwz r10,0(r30)
  145. #endif
  146. /*
  147. * DSCR: this is a common hook for handling exceptions. it will save
  148. * the needed registers, set up stack and pointer to current
  149. * then jump to the handler while enabling MMU
  150. *
  151. * PRMS: handler - a function to jump to. it has to save the
  152. * remaining registers to kernel stack, call
  153. * appropriate arch-independant exception handler
  154. * and finaly jump to ret_from_except
  155. *
  156. * PREQ: unchanged state from the time exception happened
  157. *
  158. * POST: SAVED the following registers original value
  159. * to the new created exception frame pointed to by r1
  160. *
  161. * r1 - ksp pointing to the new (exception) frame
  162. * r4 - EEAR exception EA
  163. * r10 - current pointing to current_thread_info struct
  164. * r12 - syscall 0, since we didn't come from syscall
  165. * r30 - handler address of the handler we'll jump to
  166. *
  167. * handler has to save remaining registers to the exception
  168. * ksp frame *before* tainting them!
  169. *
  170. * NOTE: this function is not reentrant per se. reentrancy is guaranteed
  171. * by processor disabling all exceptions/interrupts when exception
  172. * accours.
  173. *
  174. * OPTM: no need to make it so wasteful to extract ksp when in user mode
  175. */
  176. #define EXCEPTION_HANDLE(handler) \
  177. EXCEPTION_T_STORE_GPR30 ;\
  178. l.mfspr r30,r0,SPR_ESR_BASE ;\
  179. l.andi r30,r30,SPR_SR_SM ;\
  180. l.sfeqi r30,0 ;\
  181. EXCEPTION_T_STORE_GPR10 ;\
  182. l.bnf 2f /* kernel_mode */ ;\
  183. EXCEPTION_T_STORE_SP /* delay slot */ ;\
  184. 1: /* user_mode: */ ;\
  185. GET_CURRENT_THREAD_INFO ;\
  186. tophys (r30,r10) ;\
  187. l.lwz r1,(TI_KSP)(r30) ;\
  188. /* fall through */ ;\
  189. 2: /* kernel_mode: */ ;\
  190. /* create new stack frame, save only needed gprs */ ;\
  191. /* r1: KSP, r10: current, r4: EEAR, r31: __pa(KSP) */ ;\
  192. /* r12: temp, syscall indicator */ ;\
  193. l.addi r1,r1,-(INT_FRAME_SIZE) ;\
  194. /* r1 is KSP, r30 is __pa(KSP) */ ;\
  195. tophys (r30,r1) ;\
  196. l.sw PT_GPR12(r30),r12 ;\
  197. /* r4 use for tmp before EA */ ;\
  198. l.mfspr r12,r0,SPR_EPCR_BASE ;\
  199. l.sw PT_PC(r30),r12 ;\
  200. l.mfspr r12,r0,SPR_ESR_BASE ;\
  201. l.sw PT_SR(r30),r12 ;\
  202. /* save r30 */ ;\
  203. EXCEPTION_T_LOAD_GPR30(r12) ;\
  204. l.sw PT_GPR30(r30),r12 ;\
  205. /* save r10 as was prior to exception */ ;\
  206. EXCEPTION_T_LOAD_GPR10(r12) ;\
  207. l.sw PT_GPR10(r30),r12 ;\
  208. /* save PT_SP as was prior to exception */ ;\
  209. EXCEPTION_T_LOAD_SP(r12) ;\
  210. l.sw PT_SP(r30),r12 ;\
  211. /* save exception r4, set r4 = EA */ ;\
  212. l.sw PT_GPR4(r30),r4 ;\
  213. l.mfspr r4,r0,SPR_EEAR_BASE ;\
  214. /* r12 == 1 if we come from syscall */ ;\
  215. CLEAR_GPR(r12) ;\
  216. /* ----- turn on MMU ----- */ ;\
  217. /* Carry DSX into exception SR */ ;\
  218. l.mfspr r30,r0,SPR_SR ;\
  219. l.andi r30,r30,SPR_SR_DSX ;\
  220. l.ori r30,r30,(EXCEPTION_SR) ;\
  221. l.mtspr r0,r30,SPR_ESR_BASE ;\
  222. /* r30: EA address of handler */ ;\
  223. LOAD_SYMBOL_2_GPR(r30,handler) ;\
  224. l.mtspr r0,r30,SPR_EPCR_BASE ;\
  225. l.rfe
  226. /*
  227. * this doesn't work
  228. *
  229. *
  230. * #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
  231. * #define UNHANDLED_EXCEPTION(handler) \
  232. * l.ori r3,r0,0x1 ;\
  233. * l.mtspr r0,r3,SPR_SR ;\
  234. * l.movhi r3,hi(0xf0000100) ;\
  235. * l.ori r3,r3,lo(0xf0000100) ;\
  236. * l.jr r3 ;\
  237. * l.nop 1
  238. *
  239. * #endif
  240. */
  241. /* DSCR: this is the same as EXCEPTION_HANDLE(), we are just
  242. * a bit more carefull (if we have a PT_SP or current pointer
  243. * corruption) and set them up from 'current_set'
  244. *
  245. */
  246. #define UNHANDLED_EXCEPTION(handler) \
  247. EXCEPTION_T_STORE_GPR30 ;\
  248. EXCEPTION_T_STORE_GPR10 ;\
  249. EXCEPTION_T_STORE_SP ;\
  250. /* temporary store r3, r9 into r1, r10 */ ;\
  251. l.addi r1,r3,0x0 ;\
  252. l.addi r10,r9,0x0 ;\
  253. /* the string referenced by r3 must be low enough */ ;\
  254. l.jal _emergency_print ;\
  255. l.ori r3,r0,lo(_string_unhandled_exception) ;\
  256. l.mfspr r3,r0,SPR_NPC ;\
  257. l.jal _emergency_print_nr ;\
  258. l.andi r3,r3,0x1f00 ;\
  259. /* the string referenced by r3 must be low enough */ ;\
  260. l.jal _emergency_print ;\
  261. l.ori r3,r0,lo(_string_epc_prefix) ;\
  262. l.jal _emergency_print_nr ;\
  263. l.mfspr r3,r0,SPR_EPCR_BASE ;\
  264. l.jal _emergency_print ;\
  265. l.ori r3,r0,lo(_string_nl) ;\
  266. /* end of printing */ ;\
  267. l.addi r3,r1,0x0 ;\
  268. l.addi r9,r10,0x0 ;\
  269. /* extract current, ksp from current_set */ ;\
  270. LOAD_SYMBOL_2_GPR(r1,_unhandled_stack_top) ;\
  271. LOAD_SYMBOL_2_GPR(r10,init_thread_union) ;\
  272. /* create new stack frame, save only needed gprs */ ;\
  273. /* r1: KSP, r10: current, r31: __pa(KSP) */ ;\
  274. /* r12: temp, syscall indicator, r13 temp */ ;\
  275. l.addi r1,r1,-(INT_FRAME_SIZE) ;\
  276. /* r1 is KSP, r30 is __pa(KSP) */ ;\
  277. tophys (r30,r1) ;\
  278. l.sw PT_GPR12(r30),r12 ;\
  279. l.mfspr r12,r0,SPR_EPCR_BASE ;\
  280. l.sw PT_PC(r30),r12 ;\
  281. l.mfspr r12,r0,SPR_ESR_BASE ;\
  282. l.sw PT_SR(r30),r12 ;\
  283. /* save r31 */ ;\
  284. EXCEPTION_T_LOAD_GPR30(r12) ;\
  285. l.sw PT_GPR30(r30),r12 ;\
  286. /* save r10 as was prior to exception */ ;\
  287. EXCEPTION_T_LOAD_GPR10(r12) ;\
  288. l.sw PT_GPR10(r30),r12 ;\
  289. /* save PT_SP as was prior to exception */ ;\
  290. EXCEPTION_T_LOAD_SP(r12) ;\
  291. l.sw PT_SP(r30),r12 ;\
  292. l.sw PT_GPR13(r30),r13 ;\
  293. /* --> */ ;\
  294. /* save exception r4, set r4 = EA */ ;\
  295. l.sw PT_GPR4(r30),r4 ;\
  296. l.mfspr r4,r0,SPR_EEAR_BASE ;\
  297. /* r12 == 1 if we come from syscall */ ;\
  298. CLEAR_GPR(r12) ;\
  299. /* ----- play a MMU trick ----- */ ;\
  300. l.ori r30,r0,(EXCEPTION_SR) ;\
  301. l.mtspr r0,r30,SPR_ESR_BASE ;\
  302. /* r31: EA address of handler */ ;\
  303. LOAD_SYMBOL_2_GPR(r30,handler) ;\
  304. l.mtspr r0,r30,SPR_EPCR_BASE ;\
  305. l.rfe
  306. /* =====================================================[ exceptions] === */
  307. /* ---[ 0x100: RESET exception ]----------------------------------------- */
  308. .org 0x100
  309. /* Jump to .init code at _start which lives in the .head section
  310. * and will be discarded after boot.
  311. */
  312. LOAD_SYMBOL_2_GPR(r15, _start)
  313. tophys (r13,r15) /* MMU disabled */
  314. l.jr r13
  315. l.nop
  316. /* ---[ 0x200: BUS exception ]------------------------------------------- */
  317. .org 0x200
  318. _dispatch_bus_fault:
  319. EXCEPTION_HANDLE(_bus_fault_handler)
  320. /* ---[ 0x300: Data Page Fault exception ]------------------------------- */
  321. .org 0x300
  322. _dispatch_do_dpage_fault:
  323. // totaly disable timer interrupt
  324. // l.mtspr r0,r0,SPR_TTMR
  325. // DEBUG_TLB_PROBE(0x300)
  326. // EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x300)
  327. EXCEPTION_HANDLE(_data_page_fault_handler)
  328. /* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
  329. .org 0x400
  330. _dispatch_do_ipage_fault:
  331. // totaly disable timer interrupt
  332. // l.mtspr r0,r0,SPR_TTMR
  333. // DEBUG_TLB_PROBE(0x400)
  334. // EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x400)
  335. EXCEPTION_HANDLE(_insn_page_fault_handler)
  336. /* ---[ 0x500: Timer exception ]----------------------------------------- */
  337. .org 0x500
  338. EXCEPTION_HANDLE(_timer_handler)
  339. /* ---[ 0x600: Alignment exception ]-------------------------------------- */
  340. .org 0x600
  341. EXCEPTION_HANDLE(_alignment_handler)
  342. /* ---[ 0x700: Illegal insn exception ]---------------------------------- */
  343. .org 0x700
  344. EXCEPTION_HANDLE(_illegal_instruction_handler)
  345. /* ---[ 0x800: External interrupt exception ]---------------------------- */
  346. .org 0x800
  347. EXCEPTION_HANDLE(_external_irq_handler)
  348. /* ---[ 0x900: DTLB miss exception ]------------------------------------- */
  349. .org 0x900
  350. l.j boot_dtlb_miss_handler
  351. l.nop
  352. /* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
  353. .org 0xa00
  354. l.j boot_itlb_miss_handler
  355. l.nop
  356. /* ---[ 0xb00: Range exception ]----------------------------------------- */
  357. .org 0xb00
  358. UNHANDLED_EXCEPTION(_vector_0xb00)
  359. /* ---[ 0xc00: Syscall exception ]--------------------------------------- */
  360. .org 0xc00
  361. EXCEPTION_HANDLE(_sys_call_handler)
  362. /* ---[ 0xd00: Trap exception ]------------------------------------------ */
  363. .org 0xd00
  364. UNHANDLED_EXCEPTION(_vector_0xd00)
  365. /* ---[ 0xe00: Trap exception ]------------------------------------------ */
  366. .org 0xe00
  367. // UNHANDLED_EXCEPTION(_vector_0xe00)
  368. EXCEPTION_HANDLE(_trap_handler)
  369. /* ---[ 0xf00: Reserved exception ]-------------------------------------- */
  370. .org 0xf00
  371. UNHANDLED_EXCEPTION(_vector_0xf00)
  372. /* ---[ 0x1000: Reserved exception ]------------------------------------- */
  373. .org 0x1000
  374. UNHANDLED_EXCEPTION(_vector_0x1000)
  375. /* ---[ 0x1100: Reserved exception ]------------------------------------- */
  376. .org 0x1100
  377. UNHANDLED_EXCEPTION(_vector_0x1100)
  378. /* ---[ 0x1200: Reserved exception ]------------------------------------- */
  379. .org 0x1200
  380. UNHANDLED_EXCEPTION(_vector_0x1200)
  381. /* ---[ 0x1300: Reserved exception ]------------------------------------- */
  382. .org 0x1300
  383. UNHANDLED_EXCEPTION(_vector_0x1300)
  384. /* ---[ 0x1400: Reserved exception ]------------------------------------- */
  385. .org 0x1400
  386. UNHANDLED_EXCEPTION(_vector_0x1400)
  387. /* ---[ 0x1500: Reserved exception ]------------------------------------- */
  388. .org 0x1500
  389. UNHANDLED_EXCEPTION(_vector_0x1500)
  390. /* ---[ 0x1600: Reserved exception ]------------------------------------- */
  391. .org 0x1600
  392. UNHANDLED_EXCEPTION(_vector_0x1600)
  393. /* ---[ 0x1700: Reserved exception ]------------------------------------- */
  394. .org 0x1700
  395. UNHANDLED_EXCEPTION(_vector_0x1700)
  396. /* ---[ 0x1800: Reserved exception ]------------------------------------- */
  397. .org 0x1800
  398. UNHANDLED_EXCEPTION(_vector_0x1800)
  399. /* ---[ 0x1900: Reserved exception ]------------------------------------- */
  400. .org 0x1900
  401. UNHANDLED_EXCEPTION(_vector_0x1900)
  402. /* ---[ 0x1a00: Reserved exception ]------------------------------------- */
  403. .org 0x1a00
  404. UNHANDLED_EXCEPTION(_vector_0x1a00)
  405. /* ---[ 0x1b00: Reserved exception ]------------------------------------- */
  406. .org 0x1b00
  407. UNHANDLED_EXCEPTION(_vector_0x1b00)
  408. /* ---[ 0x1c00: Reserved exception ]------------------------------------- */
  409. .org 0x1c00
  410. UNHANDLED_EXCEPTION(_vector_0x1c00)
  411. /* ---[ 0x1d00: Reserved exception ]------------------------------------- */
  412. .org 0x1d00
  413. UNHANDLED_EXCEPTION(_vector_0x1d00)
  414. /* ---[ 0x1e00: Reserved exception ]------------------------------------- */
  415. .org 0x1e00
  416. UNHANDLED_EXCEPTION(_vector_0x1e00)
  417. /* ---[ 0x1f00: Reserved exception ]------------------------------------- */
  418. .org 0x1f00
  419. UNHANDLED_EXCEPTION(_vector_0x1f00)
  420. .org 0x2000
  421. /* ===================================================[ kernel start ]=== */
  422. /* .text*/
  423. /* This early stuff belongs in HEAD, but some of the functions below definitely
  424. * don't... */
  425. __HEAD
  426. .global _start
  427. _start:
  428. /* Init r0 to zero as per spec */
  429. CLEAR_GPR(r0)
  430. /* save kernel parameters */
  431. l.or r25,r0,r3 /* pointer to fdt */
  432. /*
  433. * ensure a deterministic start
  434. */
  435. l.ori r3,r0,0x1
  436. l.mtspr r0,r3,SPR_SR
  437. CLEAR_GPR(r1)
  438. CLEAR_GPR(r2)
  439. CLEAR_GPR(r3)
  440. CLEAR_GPR(r4)
  441. CLEAR_GPR(r5)
  442. CLEAR_GPR(r6)
  443. CLEAR_GPR(r7)
  444. CLEAR_GPR(r8)
  445. CLEAR_GPR(r9)
  446. CLEAR_GPR(r10)
  447. CLEAR_GPR(r11)
  448. CLEAR_GPR(r12)
  449. CLEAR_GPR(r13)
  450. CLEAR_GPR(r14)
  451. CLEAR_GPR(r15)
  452. CLEAR_GPR(r16)
  453. CLEAR_GPR(r17)
  454. CLEAR_GPR(r18)
  455. CLEAR_GPR(r19)
  456. CLEAR_GPR(r20)
  457. CLEAR_GPR(r21)
  458. CLEAR_GPR(r22)
  459. CLEAR_GPR(r23)
  460. CLEAR_GPR(r24)
  461. CLEAR_GPR(r26)
  462. CLEAR_GPR(r27)
  463. CLEAR_GPR(r28)
  464. CLEAR_GPR(r29)
  465. CLEAR_GPR(r30)
  466. CLEAR_GPR(r31)
  467. #ifdef CONFIG_SMP
  468. l.mfspr r26,r0,SPR_COREID
  469. l.sfeq r26,r0
  470. l.bnf secondary_wait
  471. l.nop
  472. #endif
  473. /*
  474. * set up initial ksp and current
  475. */
  476. /* setup kernel stack */
  477. LOAD_SYMBOL_2_GPR(r1,init_thread_union + THREAD_SIZE)
  478. LOAD_SYMBOL_2_GPR(r10,init_thread_union) // setup current
  479. tophys (r31,r10)
  480. l.sw TI_KSP(r31), r1
  481. l.ori r4,r0,0x0
  482. /*
  483. * .data contains initialized data,
  484. * .bss contains uninitialized data - clear it up
  485. */
  486. clear_bss:
  487. LOAD_SYMBOL_2_GPR(r24, __bss_start)
  488. LOAD_SYMBOL_2_GPR(r26, _end)
  489. tophys(r28,r24)
  490. tophys(r30,r26)
  491. CLEAR_GPR(r24)
  492. CLEAR_GPR(r26)
  493. 1:
  494. l.sw (0)(r28),r0
  495. l.sfltu r28,r30
  496. l.bf 1b
  497. l.addi r28,r28,4
  498. enable_ic:
  499. l.jal _ic_enable
  500. l.nop
  501. enable_dc:
  502. l.jal _dc_enable
  503. l.nop
  504. flush_tlb:
  505. l.jal _flush_tlb
  506. l.nop
  507. /* The MMU needs to be enabled before or32_early_setup is called */
  508. enable_mmu:
  509. /*
  510. * enable dmmu & immu
  511. * SR[5] = 0, SR[6] = 0, 6th and 7th bit of SR set to 0
  512. */
  513. l.mfspr r30,r0,SPR_SR
  514. l.movhi r28,hi(SPR_SR_DME | SPR_SR_IME)
  515. l.ori r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
  516. l.or r30,r30,r28
  517. l.mtspr r0,r30,SPR_SR
  518. l.nop
  519. l.nop
  520. l.nop
  521. l.nop
  522. l.nop
  523. l.nop
  524. l.nop
  525. l.nop
  526. l.nop
  527. l.nop
  528. l.nop
  529. l.nop
  530. l.nop
  531. l.nop
  532. l.nop
  533. l.nop
  534. // reset the simulation counters
  535. l.nop 5
  536. /* check fdt header magic word */
  537. l.lwz r3,0(r25) /* load magic from fdt into r3 */
  538. l.movhi r4,hi(OF_DT_HEADER)
  539. l.ori r4,r4,lo(OF_DT_HEADER)
  540. l.sfeq r3,r4
  541. l.bf _fdt_found
  542. l.nop
  543. /* magic number mismatch, set fdt pointer to null */
  544. l.or r25,r0,r0
  545. _fdt_found:
  546. /* pass fdt pointer to or32_early_setup in r3 */
  547. l.or r3,r0,r25
  548. LOAD_SYMBOL_2_GPR(r24, or32_early_setup)
  549. l.jalr r24
  550. l.nop
  551. clear_regs:
  552. /*
  553. * clear all GPRS to increase determinism
  554. */
  555. CLEAR_GPR(r2)
  556. CLEAR_GPR(r3)
  557. CLEAR_GPR(r4)
  558. CLEAR_GPR(r5)
  559. CLEAR_GPR(r6)
  560. CLEAR_GPR(r7)
  561. CLEAR_GPR(r8)
  562. CLEAR_GPR(r9)
  563. CLEAR_GPR(r11)
  564. CLEAR_GPR(r12)
  565. CLEAR_GPR(r13)
  566. CLEAR_GPR(r14)
  567. CLEAR_GPR(r15)
  568. CLEAR_GPR(r16)
  569. CLEAR_GPR(r17)
  570. CLEAR_GPR(r18)
  571. CLEAR_GPR(r19)
  572. CLEAR_GPR(r20)
  573. CLEAR_GPR(r21)
  574. CLEAR_GPR(r22)
  575. CLEAR_GPR(r23)
  576. CLEAR_GPR(r24)
  577. CLEAR_GPR(r25)
  578. CLEAR_GPR(r26)
  579. CLEAR_GPR(r27)
  580. CLEAR_GPR(r28)
  581. CLEAR_GPR(r29)
  582. CLEAR_GPR(r30)
  583. CLEAR_GPR(r31)
  584. jump_start_kernel:
  585. /*
  586. * jump to kernel entry (start_kernel)
  587. */
  588. LOAD_SYMBOL_2_GPR(r30, start_kernel)
  589. l.jr r30
  590. l.nop
  591. _flush_tlb:
  592. /*
  593. * I N V A L I D A T E T L B e n t r i e s
  594. */
  595. LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
  596. LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
  597. l.addi r7,r0,128 /* Maximum number of sets */
  598. 1:
  599. l.mtspr r5,r0,0x0
  600. l.mtspr r6,r0,0x0
  601. l.addi r5,r5,1
  602. l.addi r6,r6,1
  603. l.sfeq r7,r0
  604. l.bnf 1b
  605. l.addi r7,r7,-1
  606. l.jr r9
  607. l.nop
  608. #ifdef CONFIG_SMP
  609. secondary_wait:
  610. /* Doze the cpu until we are asked to run */
  611. /* If we dont have power management skip doze */
  612. l.mfspr r25,r0,SPR_UPR
  613. l.andi r25,r25,SPR_UPR_PMP
  614. l.sfeq r25,r0
  615. l.bf secondary_check_release
  616. l.nop
  617. /* Setup special secondary exception handler */
  618. LOAD_SYMBOL_2_GPR(r3, _secondary_evbar)
  619. tophys(r25,r3)
  620. l.mtspr r0,r25,SPR_EVBAR
  621. /* Enable Interrupts */
  622. l.mfspr r25,r0,SPR_SR
  623. l.ori r25,r25,SPR_SR_IEE
  624. l.mtspr r0,r25,SPR_SR
  625. /* Unmask interrupts interrupts */
  626. l.mfspr r25,r0,SPR_PICMR
  627. l.ori r25,r25,0xffff
  628. l.mtspr r0,r25,SPR_PICMR
  629. /* Doze */
  630. l.mfspr r25,r0,SPR_PMR
  631. LOAD_SYMBOL_2_GPR(r3, SPR_PMR_DME)
  632. l.or r25,r25,r3
  633. l.mtspr r0,r25,SPR_PMR
  634. /* Wakeup - Restore exception handler */
  635. l.mtspr r0,r0,SPR_EVBAR
  636. secondary_check_release:
  637. /*
  638. * Check if we actually got the release signal, if not go-back to
  639. * sleep.
  640. */
  641. l.mfspr r25,r0,SPR_COREID
  642. LOAD_SYMBOL_2_GPR(r3, secondary_release)
  643. tophys(r4, r3)
  644. l.lwz r3,0(r4)
  645. l.sfeq r25,r3
  646. l.bnf secondary_wait
  647. l.nop
  648. /* fall through to secondary_init */
  649. secondary_init:
  650. /*
  651. * set up initial ksp and current
  652. */
  653. LOAD_SYMBOL_2_GPR(r10, secondary_thread_info)
  654. tophys (r30,r10)
  655. l.lwz r10,0(r30)
  656. l.addi r1,r10,THREAD_SIZE
  657. tophys (r30,r10)
  658. l.sw TI_KSP(r30),r1
  659. l.jal _ic_enable
  660. l.nop
  661. l.jal _dc_enable
  662. l.nop
  663. l.jal _flush_tlb
  664. l.nop
  665. /*
  666. * enable dmmu & immu
  667. */
  668. l.mfspr r30,r0,SPR_SR
  669. l.movhi r28,hi(SPR_SR_DME | SPR_SR_IME)
  670. l.ori r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
  671. l.or r30,r30,r28
  672. /*
  673. * This is a bit tricky, we need to switch over from physical addresses
  674. * to virtual addresses on the fly.
  675. * To do that, we first set up ESR with the IME and DME bits set.
  676. * Then EPCR is set to secondary_start and then a l.rfe is issued to
  677. * "jump" to that.
  678. */
  679. l.mtspr r0,r30,SPR_ESR_BASE
  680. LOAD_SYMBOL_2_GPR(r30, secondary_start)
  681. l.mtspr r0,r30,SPR_EPCR_BASE
  682. l.rfe
  683. secondary_start:
  684. LOAD_SYMBOL_2_GPR(r30, secondary_start_kernel)
  685. l.jr r30
  686. l.nop
  687. #endif
  688. /* ========================================[ cache ]=== */
  689. /* alignment here so we don't change memory offsets with
  690. * memory controller defined
  691. */
  692. .align 0x2000
  693. _ic_enable:
  694. /* Check if IC present and skip enabling otherwise */
  695. l.mfspr r24,r0,SPR_UPR
  696. l.andi r26,r24,SPR_UPR_ICP
  697. l.sfeq r26,r0
  698. l.bf 9f
  699. l.nop
  700. /* Disable IC */
  701. l.mfspr r6,r0,SPR_SR
  702. l.addi r5,r0,-1
  703. l.xori r5,r5,SPR_SR_ICE
  704. l.and r5,r6,r5
  705. l.mtspr r0,r5,SPR_SR
  706. /* Establish cache block size
  707. If BS=0, 16;
  708. If BS=1, 32;
  709. r14 contain block size
  710. */
  711. l.mfspr r24,r0,SPR_ICCFGR
  712. l.andi r26,r24,SPR_ICCFGR_CBS
  713. l.srli r28,r26,7
  714. l.ori r30,r0,16
  715. l.sll r14,r30,r28
  716. /* Establish number of cache sets
  717. r16 contains number of cache sets
  718. r28 contains log(# of cache sets)
  719. */
  720. l.andi r26,r24,SPR_ICCFGR_NCS
  721. l.srli r28,r26,3
  722. l.ori r30,r0,1
  723. l.sll r16,r30,r28
  724. /* Invalidate IC */
  725. l.addi r6,r0,0
  726. l.sll r5,r14,r28
  727. // l.mul r5,r14,r16
  728. // l.trap 1
  729. // l.addi r5,r0,IC_SIZE
  730. 1:
  731. l.mtspr r0,r6,SPR_ICBIR
  732. l.sfne r6,r5
  733. l.bf 1b
  734. l.add r6,r6,r14
  735. // l.addi r6,r6,IC_LINE
  736. /* Enable IC */
  737. l.mfspr r6,r0,SPR_SR
  738. l.ori r6,r6,SPR_SR_ICE
  739. l.mtspr r0,r6,SPR_SR
  740. l.nop
  741. l.nop
  742. l.nop
  743. l.nop
  744. l.nop
  745. l.nop
  746. l.nop
  747. l.nop
  748. l.nop
  749. l.nop
  750. 9:
  751. l.jr r9
  752. l.nop
  753. _dc_enable:
  754. /* Check if DC present and skip enabling otherwise */
  755. l.mfspr r24,r0,SPR_UPR
  756. l.andi r26,r24,SPR_UPR_DCP
  757. l.sfeq r26,r0
  758. l.bf 9f
  759. l.nop
  760. /* Disable DC */
  761. l.mfspr r6,r0,SPR_SR
  762. l.addi r5,r0,-1
  763. l.xori r5,r5,SPR_SR_DCE
  764. l.and r5,r6,r5
  765. l.mtspr r0,r5,SPR_SR
  766. /* Establish cache block size
  767. If BS=0, 16;
  768. If BS=1, 32;
  769. r14 contain block size
  770. */
  771. l.mfspr r24,r0,SPR_DCCFGR
  772. l.andi r26,r24,SPR_DCCFGR_CBS
  773. l.srli r28,r26,7
  774. l.ori r30,r0,16
  775. l.sll r14,r30,r28
  776. /* Establish number of cache sets
  777. r16 contains number of cache sets
  778. r28 contains log(# of cache sets)
  779. */
  780. l.andi r26,r24,SPR_DCCFGR_NCS
  781. l.srli r28,r26,3
  782. l.ori r30,r0,1
  783. l.sll r16,r30,r28
  784. /* Invalidate DC */
  785. l.addi r6,r0,0
  786. l.sll r5,r14,r28
  787. 1:
  788. l.mtspr r0,r6,SPR_DCBIR
  789. l.sfne r6,r5
  790. l.bf 1b
  791. l.add r6,r6,r14
  792. /* Enable DC */
  793. l.mfspr r6,r0,SPR_SR
  794. l.ori r6,r6,SPR_SR_DCE
  795. l.mtspr r0,r6,SPR_SR
  796. 9:
  797. l.jr r9
  798. l.nop
  799. /* ===============================================[ page table masks ]=== */
  800. #define DTLB_UP_CONVERT_MASK 0x3fa
  801. #define ITLB_UP_CONVERT_MASK 0x3a
  802. /* for SMP we'd have (this is a bit subtle, CC must be always set
  803. * for SMP, but since we have _PAGE_PRESENT bit always defined
  804. * we can just modify the mask)
  805. */
  806. #define DTLB_SMP_CONVERT_MASK 0x3fb
  807. #define ITLB_SMP_CONVERT_MASK 0x3b
  808. /* ---[ boot dtlb miss handler ]----------------------------------------- */
  809. boot_dtlb_miss_handler:
  810. /* mask for DTLB_MR register: - (0) sets V (valid) bit,
  811. * - (31-12) sets bits belonging to VPN (31-12)
  812. */
  813. #define DTLB_MR_MASK 0xfffff001
  814. /* mask for DTLB_TR register: - (2) sets CI (cache inhibit) bit,
  815. * - (4) sets A (access) bit,
  816. * - (5) sets D (dirty) bit,
  817. * - (8) sets SRE (superuser read) bit
  818. * - (9) sets SWE (superuser write) bit
  819. * - (31-12) sets bits belonging to VPN (31-12)
  820. */
  821. #define DTLB_TR_MASK 0xfffff332
  822. /* These are for masking out the VPN/PPN value from the MR/TR registers...
  823. * it's not the same as the PFN */
  824. #define VPN_MASK 0xfffff000
  825. #define PPN_MASK 0xfffff000
  826. EXCEPTION_STORE_GPR6
  827. #if 0
  828. l.mfspr r6,r0,SPR_ESR_BASE //
  829. l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
  830. l.sfeqi r6,0 // r6 == 0x1 --> SM
  831. l.bf exit_with_no_dtranslation //
  832. l.nop
  833. #endif
  834. /* this could be optimized by moving storing of
  835. * non r6 registers here, and jumping r6 restore
  836. * if not in supervisor mode
  837. */
  838. EXCEPTION_STORE_GPR2
  839. EXCEPTION_STORE_GPR3
  840. EXCEPTION_STORE_GPR4
  841. EXCEPTION_STORE_GPR5
  842. l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
  843. immediate_translation:
  844. CLEAR_GPR(r6)
  845. l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
  846. l.mfspr r6, r0, SPR_DMMUCFGR
  847. l.andi r6, r6, SPR_DMMUCFGR_NTS
  848. l.srli r6, r6, SPR_DMMUCFGR_NTS_OFF
  849. l.ori r5, r0, 0x1
  850. l.sll r5, r5, r6 // r5 = number DMMU sets
  851. l.addi r6, r5, -1 // r6 = nsets mask
  852. l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
  853. l.or r6,r6,r4 // r6 <- r4
  854. l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
  855. l.movhi r5,hi(DTLB_MR_MASK) // r5 <- ffff:0000.x000
  856. l.ori r5,r5,lo(DTLB_MR_MASK) // r5 <- ffff:1111.x001 - apply DTLB_MR_MASK
  857. l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have DTLBMR entry
  858. l.mtspr r2,r5,SPR_DTLBMR_BASE(0) // set DTLBMR
  859. /* set up DTLB with no translation for EA <= 0xbfffffff */
  860. LOAD_SYMBOL_2_GPR(r6,0xbfffffff)
  861. l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xbfffffff >= EA)
  862. l.bf 1f // goto out
  863. l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
  864. tophys(r3,r4) // r3 <- PA
  865. 1:
  866. l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
  867. l.movhi r5,hi(DTLB_TR_MASK) // r5 <- ffff:0000.x000
  868. l.ori r5,r5,lo(DTLB_TR_MASK) // r5 <- ffff:1111.x330 - apply DTLB_MR_MASK
  869. l.and r5,r5,r3 // r5 <- PPN :PPN .x330 - we have DTLBTR entry
  870. l.mtspr r2,r5,SPR_DTLBTR_BASE(0) // set DTLBTR
  871. EXCEPTION_LOAD_GPR6
  872. EXCEPTION_LOAD_GPR5
  873. EXCEPTION_LOAD_GPR4
  874. EXCEPTION_LOAD_GPR3
  875. EXCEPTION_LOAD_GPR2
  876. l.rfe // SR <- ESR, PC <- EPC
  877. exit_with_no_dtranslation:
  878. /* EA out of memory or not in supervisor mode */
  879. EXCEPTION_LOAD_GPR6
  880. EXCEPTION_LOAD_GPR4
  881. l.j _dispatch_bus_fault
  882. /* ---[ boot itlb miss handler ]----------------------------------------- */
  883. boot_itlb_miss_handler:
  884. /* mask for ITLB_MR register: - sets V (valid) bit,
  885. * - sets bits belonging to VPN (15-12)
  886. */
  887. #define ITLB_MR_MASK 0xfffff001
  888. /* mask for ITLB_TR register: - sets A (access) bit,
  889. * - sets SXE (superuser execute) bit
  890. * - sets bits belonging to VPN (15-12)
  891. */
  892. #define ITLB_TR_MASK 0xfffff050
  893. /*
  894. #define VPN_MASK 0xffffe000
  895. #define PPN_MASK 0xffffe000
  896. */
  897. EXCEPTION_STORE_GPR2
  898. EXCEPTION_STORE_GPR3
  899. EXCEPTION_STORE_GPR4
  900. EXCEPTION_STORE_GPR5
  901. EXCEPTION_STORE_GPR6
  902. #if 0
  903. l.mfspr r6,r0,SPR_ESR_BASE //
  904. l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
  905. l.sfeqi r6,0 // r6 == 0x1 --> SM
  906. l.bf exit_with_no_itranslation
  907. l.nop
  908. #endif
  909. l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
  910. earlyearly:
  911. CLEAR_GPR(r6)
  912. l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
  913. l.mfspr r6, r0, SPR_IMMUCFGR
  914. l.andi r6, r6, SPR_IMMUCFGR_NTS
  915. l.srli r6, r6, SPR_IMMUCFGR_NTS_OFF
  916. l.ori r5, r0, 0x1
  917. l.sll r5, r5, r6 // r5 = number IMMU sets from IMMUCFGR
  918. l.addi r6, r5, -1 // r6 = nsets mask
  919. l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
  920. l.or r6,r6,r4 // r6 <- r4
  921. l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
  922. l.movhi r5,hi(ITLB_MR_MASK) // r5 <- ffff:0000.x000
  923. l.ori r5,r5,lo(ITLB_MR_MASK) // r5 <- ffff:1111.x001 - apply ITLB_MR_MASK
  924. l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have ITLBMR entry
  925. l.mtspr r2,r5,SPR_ITLBMR_BASE(0) // set ITLBMR
  926. /*
  927. * set up ITLB with no translation for EA <= 0x0fffffff
  928. *
  929. * we need this for head.S mapping (EA = PA). if we move all functions
  930. * which run with mmu enabled into entry.S, we might be able to eliminate this.
  931. *
  932. */
  933. LOAD_SYMBOL_2_GPR(r6,0x0fffffff)
  934. l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xb0ffffff >= EA)
  935. l.bf 1f // goto out
  936. l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
  937. tophys(r3,r4) // r3 <- PA
  938. 1:
  939. l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
  940. l.movhi r5,hi(ITLB_TR_MASK) // r5 <- ffff:0000.x000
  941. l.ori r5,r5,lo(ITLB_TR_MASK) // r5 <- ffff:1111.x050 - apply ITLB_MR_MASK
  942. l.and r5,r5,r3 // r5 <- PPN :PPN .x050 - we have ITLBTR entry
  943. l.mtspr r2,r5,SPR_ITLBTR_BASE(0) // set ITLBTR
  944. EXCEPTION_LOAD_GPR6
  945. EXCEPTION_LOAD_GPR5
  946. EXCEPTION_LOAD_GPR4
  947. EXCEPTION_LOAD_GPR3
  948. EXCEPTION_LOAD_GPR2
  949. l.rfe // SR <- ESR, PC <- EPC
  950. exit_with_no_itranslation:
  951. EXCEPTION_LOAD_GPR4
  952. EXCEPTION_LOAD_GPR6
  953. l.j _dispatch_bus_fault
  954. l.nop
  955. /* ====================================================================== */
  956. /*
  957. * Stuff below here shouldn't go into .head section... maybe this stuff
  958. * can be moved to entry.S ???
  959. */
  960. /* ==============================================[ DTLB miss handler ]=== */
  961. /*
  962. * Comments:
  963. * Exception handlers are entered with MMU off so the following handler
  964. * needs to use physical addressing
  965. *
  966. */
  967. .text
  968. ENTRY(dtlb_miss_handler)
  969. EXCEPTION_STORE_GPR2
  970. EXCEPTION_STORE_GPR3
  971. EXCEPTION_STORE_GPR4
  972. /*
  973. * get EA of the miss
  974. */
  975. l.mfspr r2,r0,SPR_EEAR_BASE
  976. /*
  977. * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
  978. */
  979. GET_CURRENT_PGD(r3,r4) // r3 is current_pgd, r4 is temp
  980. l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
  981. l.slli r4,r4,0x2 // to get address << 2
  982. l.add r3,r4,r3 // r4 is pgd_index(daddr)
  983. /*
  984. * if (pmd_none(*pmd))
  985. * goto pmd_none:
  986. */
  987. tophys (r4,r3)
  988. l.lwz r3,0x0(r4) // get *pmd value
  989. l.sfne r3,r0
  990. l.bnf d_pmd_none
  991. l.addi r3,r0,0xffffe000 // PAGE_MASK
  992. d_pmd_good:
  993. /*
  994. * pte = *pte_offset(pmd, daddr);
  995. */
  996. l.lwz r4,0x0(r4) // get **pmd value
  997. l.and r4,r4,r3 // & PAGE_MASK
  998. l.srli r2,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
  999. l.andi r3,r2,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
  1000. l.slli r3,r3,0x2 // to get address << 2
  1001. l.add r3,r3,r4
  1002. l.lwz r3,0x0(r3) // this is pte at last
  1003. /*
  1004. * if (!pte_present(pte))
  1005. */
  1006. l.andi r4,r3,0x1
  1007. l.sfne r4,r0 // is pte present
  1008. l.bnf d_pte_not_present
  1009. l.addi r4,r0,0xffffe3fa // PAGE_MASK | DTLB_UP_CONVERT_MASK
  1010. /*
  1011. * fill DTLB TR register
  1012. */
  1013. l.and r4,r3,r4 // apply the mask
  1014. // Determine number of DMMU sets
  1015. l.mfspr r2, r0, SPR_DMMUCFGR
  1016. l.andi r2, r2, SPR_DMMUCFGR_NTS
  1017. l.srli r2, r2, SPR_DMMUCFGR_NTS_OFF
  1018. l.ori r3, r0, 0x1
  1019. l.sll r3, r3, r2 // r3 = number DMMU sets DMMUCFGR
  1020. l.addi r2, r3, -1 // r2 = nsets mask
  1021. l.mfspr r3, r0, SPR_EEAR_BASE
  1022. l.srli r3, r3, 0xd // >> PAGE_SHIFT
  1023. l.and r2, r3, r2 // calc offset: & (NUM_TLB_ENTRIES-1)
  1024. //NUM_TLB_ENTRIES
  1025. l.mtspr r2,r4,SPR_DTLBTR_BASE(0)
  1026. /*
  1027. * fill DTLB MR register
  1028. */
  1029. l.slli r3, r3, 0xd /* << PAGE_SHIFT => EA & PAGE_MASK */
  1030. l.ori r4,r3,0x1 // set hardware valid bit: DTBL_MR entry
  1031. l.mtspr r2,r4,SPR_DTLBMR_BASE(0)
  1032. EXCEPTION_LOAD_GPR2
  1033. EXCEPTION_LOAD_GPR3
  1034. EXCEPTION_LOAD_GPR4
  1035. l.rfe
  1036. d_pmd_none:
  1037. d_pte_not_present:
  1038. EXCEPTION_LOAD_GPR2
  1039. EXCEPTION_LOAD_GPR3
  1040. EXCEPTION_LOAD_GPR4
  1041. EXCEPTION_HANDLE(_dtlb_miss_page_fault_handler)
  1042. /* ==============================================[ ITLB miss handler ]=== */
  1043. ENTRY(itlb_miss_handler)
  1044. EXCEPTION_STORE_GPR2
  1045. EXCEPTION_STORE_GPR3
  1046. EXCEPTION_STORE_GPR4
  1047. /*
  1048. * get EA of the miss
  1049. */
  1050. l.mfspr r2,r0,SPR_EEAR_BASE
  1051. /*
  1052. * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
  1053. *
  1054. */
  1055. GET_CURRENT_PGD(r3,r4) // r3 is current_pgd, r5 is temp
  1056. l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
  1057. l.slli r4,r4,0x2 // to get address << 2
  1058. l.add r3,r4,r3 // r4 is pgd_index(daddr)
  1059. /*
  1060. * if (pmd_none(*pmd))
  1061. * goto pmd_none:
  1062. */
  1063. tophys (r4,r3)
  1064. l.lwz r3,0x0(r4) // get *pmd value
  1065. l.sfne r3,r0
  1066. l.bnf i_pmd_none
  1067. l.addi r3,r0,0xffffe000 // PAGE_MASK
  1068. i_pmd_good:
  1069. /*
  1070. * pte = *pte_offset(pmd, iaddr);
  1071. *
  1072. */
  1073. l.lwz r4,0x0(r4) // get **pmd value
  1074. l.and r4,r4,r3 // & PAGE_MASK
  1075. l.srli r2,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
  1076. l.andi r3,r2,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
  1077. l.slli r3,r3,0x2 // to get address << 2
  1078. l.add r3,r3,r4
  1079. l.lwz r3,0x0(r3) // this is pte at last
  1080. /*
  1081. * if (!pte_present(pte))
  1082. *
  1083. */
  1084. l.andi r4,r3,0x1
  1085. l.sfne r4,r0 // is pte present
  1086. l.bnf i_pte_not_present
  1087. l.addi r4,r0,0xffffe03a // PAGE_MASK | ITLB_UP_CONVERT_MASK
  1088. /*
  1089. * fill ITLB TR register
  1090. */
  1091. l.and r4,r3,r4 // apply the mask
  1092. l.andi r3,r3,0x7c0 // _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE | _PAGE_URE | _PAGE_UWE
  1093. l.sfeq r3,r0
  1094. l.bf itlb_tr_fill //_workaround
  1095. // Determine number of IMMU sets
  1096. l.mfspr r2, r0, SPR_IMMUCFGR
  1097. l.andi r2, r2, SPR_IMMUCFGR_NTS
  1098. l.srli r2, r2, SPR_IMMUCFGR_NTS_OFF
  1099. l.ori r3, r0, 0x1
  1100. l.sll r3, r3, r2 // r3 = number IMMU sets IMMUCFGR
  1101. l.addi r2, r3, -1 // r2 = nsets mask
  1102. l.mfspr r3, r0, SPR_EEAR_BASE
  1103. l.srli r3, r3, 0xd // >> PAGE_SHIFT
  1104. l.and r2, r3, r2 // calc offset: & (NUM_TLB_ENTRIES-1)
  1105. /*
  1106. * __PHX__ :: fixme
  1107. * we should not just blindly set executable flags,
  1108. * but it does help with ping. the clean way would be to find out
  1109. * (and fix it) why stack doesn't have execution permissions
  1110. */
  1111. itlb_tr_fill_workaround:
  1112. l.ori r4,r4,0xc0 // | (SPR_ITLBTR_UXE | ITLBTR_SXE)
  1113. itlb_tr_fill:
  1114. l.mtspr r2,r4,SPR_ITLBTR_BASE(0)
  1115. /*
  1116. * fill DTLB MR register
  1117. */
  1118. l.slli r3, r3, 0xd /* << PAGE_SHIFT => EA & PAGE_MASK */
  1119. l.ori r4,r3,0x1 // set hardware valid bit: ITBL_MR entry
  1120. l.mtspr r2,r4,SPR_ITLBMR_BASE(0)
  1121. EXCEPTION_LOAD_GPR2
  1122. EXCEPTION_LOAD_GPR3
  1123. EXCEPTION_LOAD_GPR4
  1124. l.rfe
  1125. i_pmd_none:
  1126. i_pte_not_present:
  1127. EXCEPTION_LOAD_GPR2
  1128. EXCEPTION_LOAD_GPR3
  1129. EXCEPTION_LOAD_GPR4
  1130. EXCEPTION_HANDLE(_itlb_miss_page_fault_handler)
  1131. /* ==============================================[ boot tlb handlers ]=== */
  1132. /* =================================================[ debugging aids ]=== */
  1133. .align 64
  1134. _immu_trampoline:
  1135. .space 64
  1136. _immu_trampoline_top:
  1137. #define TRAMP_SLOT_0 (0x0)
  1138. #define TRAMP_SLOT_1 (0x4)
  1139. #define TRAMP_SLOT_2 (0x8)
  1140. #define TRAMP_SLOT_3 (0xc)
  1141. #define TRAMP_SLOT_4 (0x10)
  1142. #define TRAMP_SLOT_5 (0x14)
  1143. #define TRAMP_FRAME_SIZE (0x18)
  1144. ENTRY(_immu_trampoline_workaround)
  1145. // r2 EEA
  1146. // r6 is physical EEA
  1147. tophys(r6,r2)
  1148. LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
  1149. tophys (r3,r5) // r3 is trampoline (physical)
  1150. LOAD_SYMBOL_2_GPR(r4,0x15000000)
  1151. l.sw TRAMP_SLOT_0(r3),r4
  1152. l.sw TRAMP_SLOT_1(r3),r4
  1153. l.sw TRAMP_SLOT_4(r3),r4
  1154. l.sw TRAMP_SLOT_5(r3),r4
  1155. // EPC = EEA - 0x4
  1156. l.lwz r4,0x0(r6) // load op @ EEA + 0x0 (fc address)
  1157. l.sw TRAMP_SLOT_3(r3),r4 // store it to _immu_trampoline_data
  1158. l.lwz r4,-0x4(r6) // load op @ EEA - 0x4 (f8 address)
  1159. l.sw TRAMP_SLOT_2(r3),r4 // store it to _immu_trampoline_data
  1160. l.srli r5,r4,26 // check opcode for write access
  1161. l.sfeqi r5,0 // l.j
  1162. l.bf 0f
  1163. l.sfeqi r5,0x11 // l.jr
  1164. l.bf 1f
  1165. l.sfeqi r5,1 // l.jal
  1166. l.bf 2f
  1167. l.sfeqi r5,0x12 // l.jalr
  1168. l.bf 3f
  1169. l.sfeqi r5,3 // l.bnf
  1170. l.bf 4f
  1171. l.sfeqi r5,4 // l.bf
  1172. l.bf 5f
  1173. 99:
  1174. l.nop
  1175. l.j 99b // should never happen
  1176. l.nop 1
  1177. // r2 is EEA
  1178. // r3 is trampoline address (physical)
  1179. // r4 is instruction
  1180. // r6 is physical(EEA)
  1181. //
  1182. // r5
  1183. 2: // l.jal
  1184. /* 19 20 aa aa l.movhi r9,0xaaaa
  1185. * a9 29 bb bb l.ori r9,0xbbbb
  1186. *
  1187. * where 0xaaaabbbb is EEA + 0x4 shifted right 2
  1188. */
  1189. l.addi r6,r2,0x4 // this is 0xaaaabbbb
  1190. // l.movhi r9,0xaaaa
  1191. l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
  1192. l.sh (TRAMP_SLOT_0+0x0)(r3),r5
  1193. l.srli r5,r6,16
  1194. l.sh (TRAMP_SLOT_0+0x2)(r3),r5
  1195. // l.ori r9,0xbbbb
  1196. l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
  1197. l.sh (TRAMP_SLOT_1+0x0)(r3),r5
  1198. l.andi r5,r6,0xffff
  1199. l.sh (TRAMP_SLOT_1+0x2)(r3),r5
  1200. /* falthrough, need to set up new jump offset */
  1201. 0: // l.j
  1202. l.slli r6,r4,6 // original offset shifted left 6 - 2
  1203. // l.srli r6,r6,6 // original offset shifted right 2
  1204. l.slli r4,r2,4 // old jump position: EEA shifted left 4
  1205. // l.srli r4,r4,6 // old jump position: shifted right 2
  1206. l.addi r5,r3,0xc // new jump position (physical)
  1207. l.slli r5,r5,4 // new jump position: shifted left 4
  1208. // calculate new jump offset
  1209. // new_off = old_off + (old_jump - new_jump)
  1210. l.sub r5,r4,r5 // old_jump - new_jump
  1211. l.add r5,r6,r5 // orig_off + (old_jump - new_jump)
  1212. l.srli r5,r5,6 // new offset shifted right 2
  1213. // r5 is new jump offset
  1214. // l.j has opcode 0x0...
  1215. l.sw TRAMP_SLOT_2(r3),r5 // write it back
  1216. l.j trampoline_out
  1217. l.nop
  1218. /* ----------------------------- */
  1219. 3: // l.jalr
  1220. /* 19 20 aa aa l.movhi r9,0xaaaa
  1221. * a9 29 bb bb l.ori r9,0xbbbb
  1222. *
  1223. * where 0xaaaabbbb is EEA + 0x4 shifted right 2
  1224. */
  1225. l.addi r6,r2,0x4 // this is 0xaaaabbbb
  1226. // l.movhi r9,0xaaaa
  1227. l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
  1228. l.sh (TRAMP_SLOT_0+0x0)(r3),r5
  1229. l.srli r5,r6,16
  1230. l.sh (TRAMP_SLOT_0+0x2)(r3),r5
  1231. // l.ori r9,0xbbbb
  1232. l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
  1233. l.sh (TRAMP_SLOT_1+0x0)(r3),r5
  1234. l.andi r5,r6,0xffff
  1235. l.sh (TRAMP_SLOT_1+0x2)(r3),r5
  1236. l.lhz r5,(TRAMP_SLOT_2+0x0)(r3) // load hi part of jump instruction
  1237. l.andi r5,r5,0x3ff // clear out opcode part
  1238. l.ori r5,r5,0x4400 // opcode changed from l.jalr -> l.jr
  1239. l.sh (TRAMP_SLOT_2+0x0)(r3),r5 // write it back
  1240. /* falthrough */
  1241. 1: // l.jr
  1242. l.j trampoline_out
  1243. l.nop
  1244. /* ----------------------------- */
  1245. 4: // l.bnf
  1246. 5: // l.bf
  1247. l.slli r6,r4,6 // original offset shifted left 6 - 2
  1248. // l.srli r6,r6,6 // original offset shifted right 2
  1249. l.slli r4,r2,4 // old jump position: EEA shifted left 4
  1250. // l.srli r4,r4,6 // old jump position: shifted right 2
  1251. l.addi r5,r3,0xc // new jump position (physical)
  1252. l.slli r5,r5,4 // new jump position: shifted left 4
  1253. // calculate new jump offset
  1254. // new_off = old_off + (old_jump - new_jump)
  1255. l.add r6,r6,r4 // (orig_off + old_jump)
  1256. l.sub r6,r6,r5 // (orig_off + old_jump) - new_jump
  1257. l.srli r6,r6,6 // new offset shifted right 2
  1258. // r6 is new jump offset
  1259. l.lwz r4,(TRAMP_SLOT_2+0x0)(r3) // load jump instruction
  1260. l.srli r4,r4,16
  1261. l.andi r4,r4,0xfc00 // get opcode part
  1262. l.slli r4,r4,16
  1263. l.or r6,r4,r6 // l.b(n)f new offset
  1264. l.sw TRAMP_SLOT_2(r3),r6 // write it back
  1265. /* we need to add l.j to EEA + 0x8 */
  1266. tophys (r4,r2) // may not be needed (due to shifts down_
  1267. l.addi r4,r4,(0x8 - 0x8) // jump target = r2 + 0x8 (compensate for 0x8)
  1268. // jump position = r5 + 0x8 (0x8 compensated)
  1269. l.sub r4,r4,r5 // jump offset = target - new_position + 0x8
  1270. l.slli r4,r4,4 // the amount of info in imediate of jump
  1271. l.srli r4,r4,6 // jump instruction with offset
  1272. l.sw TRAMP_SLOT_4(r3),r4 // write it to 4th slot
  1273. /* fallthrough */
  1274. trampoline_out:
  1275. // set up new EPC to point to our trampoline code
  1276. LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
  1277. l.mtspr r0,r5,SPR_EPCR_BASE
  1278. // immu_trampoline is (4x) CACHE_LINE aligned
  1279. // and only 6 instructions long,
  1280. // so we need to invalidate only 2 lines
  1281. /* Establish cache block size
  1282. If BS=0, 16;
  1283. If BS=1, 32;
  1284. r14 contain block size
  1285. */
  1286. l.mfspr r21,r0,SPR_ICCFGR
  1287. l.andi r21,r21,SPR_ICCFGR_CBS
  1288. l.srli r21,r21,7
  1289. l.ori r23,r0,16
  1290. l.sll r14,r23,r21
  1291. l.mtspr r0,r5,SPR_ICBIR
  1292. l.add r5,r5,r14
  1293. l.mtspr r0,r5,SPR_ICBIR
  1294. l.jr r9
  1295. l.nop
  1296. /*
  1297. * DSCR: prints a string referenced by r3.
  1298. *
  1299. * PRMS: r3 - address of the first character of null
  1300. * terminated string to be printed
  1301. *
  1302. * PREQ: UART at UART_BASE_ADD has to be initialized
  1303. *
  1304. * POST: caller should be aware that r3, r9 are changed
  1305. */
  1306. ENTRY(_emergency_print)
  1307. EMERGENCY_PRINT_STORE_GPR4
  1308. EMERGENCY_PRINT_STORE_GPR5
  1309. EMERGENCY_PRINT_STORE_GPR6
  1310. EMERGENCY_PRINT_STORE_GPR7
  1311. 2:
  1312. l.lbz r7,0(r3)
  1313. l.sfeq r7,r0
  1314. l.bf 9f
  1315. l.nop
  1316. // putc:
  1317. l.movhi r4,hi(UART_BASE_ADD)
  1318. l.addi r6,r0,0x20
  1319. 1: l.lbz r5,5(r4)
  1320. l.andi r5,r5,0x20
  1321. l.sfeq r5,r6
  1322. l.bnf 1b
  1323. l.nop
  1324. l.sb 0(r4),r7
  1325. l.addi r6,r0,0x60
  1326. 1: l.lbz r5,5(r4)
  1327. l.andi r5,r5,0x60
  1328. l.sfeq r5,r6
  1329. l.bnf 1b
  1330. l.nop
  1331. /* next character */
  1332. l.j 2b
  1333. l.addi r3,r3,0x1
  1334. 9:
  1335. EMERGENCY_PRINT_LOAD_GPR7
  1336. EMERGENCY_PRINT_LOAD_GPR6
  1337. EMERGENCY_PRINT_LOAD_GPR5
  1338. EMERGENCY_PRINT_LOAD_GPR4
  1339. l.jr r9
  1340. l.nop
  1341. ENTRY(_emergency_print_nr)
  1342. EMERGENCY_PRINT_STORE_GPR4
  1343. EMERGENCY_PRINT_STORE_GPR5
  1344. EMERGENCY_PRINT_STORE_GPR6
  1345. EMERGENCY_PRINT_STORE_GPR7
  1346. EMERGENCY_PRINT_STORE_GPR8
  1347. l.addi r8,r0,32 // shift register
  1348. 1: /* remove leading zeros */
  1349. l.addi r8,r8,-0x4
  1350. l.srl r7,r3,r8
  1351. l.andi r7,r7,0xf
  1352. /* don't skip the last zero if number == 0x0 */
  1353. l.sfeqi r8,0x4
  1354. l.bf 2f
  1355. l.nop
  1356. l.sfeq r7,r0
  1357. l.bf 1b
  1358. l.nop
  1359. 2:
  1360. l.srl r7,r3,r8
  1361. l.andi r7,r7,0xf
  1362. l.sflts r8,r0
  1363. l.bf 9f
  1364. l.sfgtui r7,0x9
  1365. l.bnf 8f
  1366. l.nop
  1367. l.addi r7,r7,0x27
  1368. 8:
  1369. l.addi r7,r7,0x30
  1370. // putc:
  1371. l.movhi r4,hi(UART_BASE_ADD)
  1372. l.addi r6,r0,0x20
  1373. 1: l.lbz r5,5(r4)
  1374. l.andi r5,r5,0x20
  1375. l.sfeq r5,r6
  1376. l.bnf 1b
  1377. l.nop
  1378. l.sb 0(r4),r7
  1379. l.addi r6,r0,0x60
  1380. 1: l.lbz r5,5(r4)
  1381. l.andi r5,r5,0x60
  1382. l.sfeq r5,r6
  1383. l.bnf 1b
  1384. l.nop
  1385. /* next character */
  1386. l.j 2b
  1387. l.addi r8,r8,-0x4
  1388. 9:
  1389. EMERGENCY_PRINT_LOAD_GPR8
  1390. EMERGENCY_PRINT_LOAD_GPR7
  1391. EMERGENCY_PRINT_LOAD_GPR6
  1392. EMERGENCY_PRINT_LOAD_GPR5
  1393. EMERGENCY_PRINT_LOAD_GPR4
  1394. l.jr r9
  1395. l.nop
  1396. /*
  1397. * This should be used for debugging only.
  1398. * It messes up the Linux early serial output
  1399. * somehow, so use it sparingly and essentially
  1400. * only if you need to debug something that goes wrong
  1401. * before Linux gets the early serial going.
  1402. *
  1403. * Furthermore, you'll have to make sure you set the
  1404. * UART_DEVISOR correctly according to the system
  1405. * clock rate.
  1406. *
  1407. *
  1408. */
  1409. #define SYS_CLK 20000000
  1410. //#define SYS_CLK 1843200
  1411. #define OR32_CONSOLE_BAUD 115200
  1412. #define UART_DIVISOR SYS_CLK/(16*OR32_CONSOLE_BAUD)
  1413. ENTRY(_early_uart_init)
  1414. l.movhi r3,hi(UART_BASE_ADD)
  1415. l.addi r4,r0,0x7
  1416. l.sb 0x2(r3),r4
  1417. l.addi r4,r0,0x0
  1418. l.sb 0x1(r3),r4
  1419. l.addi r4,r0,0x3
  1420. l.sb 0x3(r3),r4
  1421. l.lbz r5,3(r3)
  1422. l.ori r4,r5,0x80
  1423. l.sb 0x3(r3),r4
  1424. l.addi r4,r0,((UART_DIVISOR>>8) & 0x000000ff)
  1425. l.sb UART_DLM(r3),r4
  1426. l.addi r4,r0,((UART_DIVISOR) & 0x000000ff)
  1427. l.sb UART_DLL(r3),r4
  1428. l.sb 0x3(r3),r5
  1429. l.jr r9
  1430. l.nop
  1431. .align 0x1000
  1432. .global _secondary_evbar
  1433. _secondary_evbar:
  1434. .space 0x800
  1435. /* Just disable interrupts and Return */
  1436. l.ori r3,r0,SPR_SR_SM
  1437. l.mtspr r0,r3,SPR_ESR_BASE
  1438. l.rfe
  1439. .section .rodata
  1440. _string_unhandled_exception:
  1441. .string "\n\rRunarunaround: Unhandled exception 0x\0"
  1442. _string_epc_prefix:
  1443. .string ": EPC=0x\0"
  1444. _string_nl:
  1445. .string "\n\r\0"
  1446. /* ========================================[ page aligned structures ]=== */
  1447. /*
  1448. * .data section should be page aligned
  1449. * (look into arch/openrisc/kernel/vmlinux.lds.S)
  1450. */
  1451. .section .data,"aw"
  1452. .align 8192
  1453. .global empty_zero_page
  1454. empty_zero_page:
  1455. .space 8192
  1456. .global swapper_pg_dir
  1457. swapper_pg_dir:
  1458. .space 8192
  1459. .global _unhandled_stack
  1460. _unhandled_stack:
  1461. .space 8192
  1462. _unhandled_stack_top:
  1463. /* ============================================================[ EOF ]=== */