head.S 39 KB

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