start.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. /*
  3. * (C) Copyright 2008 - 2013 Tensilica Inc.
  4. * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
  5. */
  6. #include <config.h>
  7. #include <asm/asmmacro.h>
  8. #include <asm/cacheasm.h>
  9. #include <asm/regs.h>
  10. #include <asm/arch/tie.h>
  11. #include <asm-offsets.h>
  12. /*
  13. * Offsets into the the pt_regs struture.
  14. * Make sure these always match with the structure defined in ptrace.h!
  15. */
  16. #define PT_PC 0
  17. #define PT_PS 4
  18. #define PT_DEPC 8
  19. #define PT_EXCCAUSE 12
  20. #define PT_EXCVADDR 16
  21. #define PT_DEBUGCAUSE 20
  22. #define PT_WMASK 24
  23. #define PT_LBEG 28
  24. #define PT_LEND 32
  25. #define PT_LCOUNT 36
  26. #define PT_SAR 40
  27. #define PT_WINDOWBASE 44
  28. #define PT_WINDOWSTART 48
  29. #define PT_SYSCALL 52
  30. #define PT_ICOUNTLEVEL 56
  31. #define PT_RESERVED 60
  32. #define PT_AREG 64
  33. #define PT_SIZE (64 + 64)
  34. /*
  35. * Cache attributes are different for full MMU and region protection.
  36. */
  37. #if XCHAL_HAVE_PTP_MMU
  38. #define CA_WRITEBACK (0x7)
  39. #else
  40. #define CA_WRITEBACK (0x4)
  41. #endif
  42. /*
  43. * Reset vector.
  44. * Only a trampoline to jump to _start
  45. * (Note that we have to mark the section writable as the section contains
  46. * a relocatable literal)
  47. */
  48. .section .ResetVector.text, "awx"
  49. .global _ResetVector
  50. _ResetVector:
  51. j 1f
  52. .align 4
  53. 2: .long _start
  54. 1: l32r a2, 2b
  55. jx a2
  56. /*
  57. * Processor initialization. We still run in rom space.
  58. *
  59. * NOTE: Running in ROM
  60. * For Xtensa, we currently don't allow to run some code from ROM but
  61. * unpack the data immediately to memory. This requires, for example,
  62. * that DDR has been set up before running U-Boot. (See also comments
  63. * inline for ways to change it)
  64. */
  65. .section .reset.text, "ax"
  66. .global _start
  67. .align 4
  68. _start:
  69. /* Keep a0 = 0 for various initializations */
  70. movi a0, 0
  71. /*
  72. * For full MMU cores, put page table at unmapped virtual address.
  73. * This ensures that accesses outside the static maps result
  74. * in miss exceptions rather than random behaviour.
  75. */
  76. #if XCHAL_HAVE_PTP_MMU
  77. wsr a0, PTEVADDR
  78. #endif
  79. /* Disable dbreak debug exceptions */
  80. #if XCHAL_HAVE_DEBUG && XCHAL_NUM_DBREAK > 0
  81. .set _index, 0
  82. .rept XCHAL_NUM_DBREAK
  83. wsr a0, DBREAKC + _index
  84. .set _index, _index + 1
  85. .endr
  86. #endif
  87. /* Reset windowbase and windowstart */
  88. #if XCHAL_HAVE_WINDOWED
  89. movi a3, 1
  90. wsr a3, windowstart
  91. wsr a0, windowbase
  92. rsync
  93. movi a0, 0 /* windowbase might have changed */
  94. #endif
  95. /*
  96. * Vecbase in bitstream may differ from header files
  97. * set or check it.
  98. */
  99. #if XCHAL_HAVE_VECBASE
  100. movi a3, XCHAL_VECBASE_RESET_VADDR /* VECBASE reset value */
  101. wsr a3, VECBASE
  102. #endif
  103. #if XCHAL_HAVE_LOOPS
  104. /* Disable loops */
  105. wsr a0, LCOUNT
  106. #endif
  107. /* Set PS.WOE = 0, PS.EXCM = 0 (for loop), PS.INTLEVEL = EXCM level */
  108. #if XCHAL_HAVE_XEA1
  109. movi a2, 1
  110. #else
  111. movi a2, XCHAL_EXCM_LEVEL
  112. #endif
  113. wsr a2, PS
  114. rsync
  115. /* Unlock and invalidate caches */
  116. ___unlock_dcache_all a2, a3
  117. ___invalidate_dcache_all a2, a3
  118. ___unlock_icache_all a2, a3
  119. ___invalidate_icache_all a2, a3
  120. isync
  121. /* Unpack data sections */
  122. movi a2, __reloc_table_start
  123. movi a3, __reloc_table_end
  124. 1: beq a2, a3, 3f # no more entries?
  125. l32i a4, a2, 0 # start destination (in RAM)
  126. l32i a5, a2, 4 # end destination (in RAM)
  127. l32i a6, a2, 8 # start source (in ROM)
  128. addi a2, a2, 12 # next entry
  129. beq a4, a5, 1b # skip, empty entry
  130. beq a4, a6, 1b # skip, source and destination are the same
  131. /* If there's memory protection option with 512MB TLB regions and
  132. * cache attributes in TLB entries and caching is not inhibited,
  133. * enable data/instruction cache for relocated image.
  134. */
  135. #if XCHAL_HAVE_SPANNING_WAY && \
  136. !(CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && \
  137. CONFIG_IS_ENABLED(SYS_ICACHE_OFF))
  138. srli a7, a4, 29
  139. slli a7, a7, 29
  140. addi a7, a7, XCHAL_SPANNING_WAY
  141. #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
  142. rdtlb1 a8, a7
  143. srli a8, a8, 4
  144. slli a8, a8, 4
  145. addi a8, a8, CA_WRITEBACK
  146. wdtlb a8, a7
  147. #endif
  148. #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
  149. ritlb1 a8, a7
  150. srli a8, a8, 4
  151. slli a8, a8, 4
  152. addi a8, a8, CA_WRITEBACK
  153. witlb a8, a7
  154. #endif
  155. isync
  156. #endif
  157. 2: l32i a7, a6, 0
  158. addi a6, a6, 4
  159. s32i a7, a4, 0
  160. addi a4, a4, 4
  161. bltu a4, a5, 2b
  162. j 1b
  163. 3: /* All code and initalized data segments have been copied */
  164. /* Setup PS, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
  165. #if __XTENSA_CALL0_ABI__
  166. movi a2, XCHAL_EXCM_LEVEL
  167. #else
  168. movi a2, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
  169. #endif
  170. wsr a2, PS
  171. rsync
  172. /* Writeback */
  173. ___flush_dcache_all a2, a3
  174. #ifdef __XTENSA_WINDOWED_ABI__
  175. /*
  176. * In windowed ABI caller and call target need to be within the same
  177. * gigabyte. Put the rest of the code into the text segment and jump
  178. * there.
  179. */
  180. movi a4, .Lboard_init_code
  181. jx a4
  182. .text
  183. .align 4
  184. .Lboard_init_code:
  185. #endif
  186. movi a0, 0
  187. movi sp, (XTENSA_SYS_TEXT_ADDR - 16) & 0xfffffff0
  188. #ifdef CONFIG_DEBUG_UART
  189. movi a4, debug_uart_init
  190. #ifdef __XTENSA_CALL0_ABI__
  191. callx0 a4
  192. #else
  193. callx4 a4
  194. #endif
  195. #endif
  196. movi a4, board_init_f_alloc_reserve
  197. #ifdef __XTENSA_CALL0_ABI__
  198. mov a2, sp
  199. callx0 a4
  200. mov sp, a2
  201. #else
  202. mov a6, sp
  203. callx4 a4
  204. movsp sp, a6
  205. #endif
  206. movi a4, board_init_f_init_reserve
  207. #ifdef __XTENSA_CALL0_ABI__
  208. callx0 a4
  209. #else
  210. callx4 a4
  211. #endif
  212. /*
  213. * Call board initialization routine (never returns).
  214. */
  215. movi a4, board_init_f
  216. #ifdef __XTENSA_CALL0_ABI__
  217. movi a2, 0
  218. callx0 a4
  219. #else
  220. movi a6, 0
  221. callx4 a4
  222. #endif
  223. /* Never Returns */
  224. ill
  225. /*
  226. * void relocate_code(addr_sp, gd, addr_moni)
  227. *
  228. * This "function" does not return, instead it continues in RAM
  229. * after relocating the monitor code.
  230. *
  231. * a2 = addr_sp
  232. * a3 = gd
  233. * a4 = destination address
  234. */
  235. .text
  236. .globl relocate_code
  237. .align 4
  238. relocate_code:
  239. abi_entry
  240. #ifdef __XTENSA_CALL0_ABI__
  241. mov a1, a2
  242. mov a2, a3
  243. mov a3, a4
  244. movi a0, board_init_r
  245. callx0 a0
  246. #else
  247. /* We can't movsp here, because the chain of stack frames may cross
  248. * the now reserved memory. We need to toss all window frames except
  249. * the current, create new pristine stack frame and start from scratch.
  250. */
  251. rsr a0, windowbase
  252. ssl a0
  253. movi a0, 1
  254. sll a0, a0
  255. wsr a0, windowstart
  256. rsync
  257. movi a0, 0
  258. /* Reserve 16-byte save area */
  259. addi sp, a2, -16
  260. mov a6, a3
  261. mov a7, a4
  262. movi a4, board_init_r
  263. callx4 a4
  264. #endif
  265. ill
  266. #if XCHAL_HAVE_EXCEPTIONS
  267. /*
  268. * Exception vectors.
  269. *
  270. * Various notes:
  271. * - We currently don't use the user exception vector (PS.UM is always 0),
  272. * but do define such a vector, just in case. They both jump to the
  273. * same exception handler, though.
  274. * - We currently only save the bare minimum number of registers:
  275. * a0...a15, sar, loop-registers, exception register (epc1, excvaddr,
  276. * exccause, depc)
  277. * - WINDOWSTART is only saved to identify if registers have been spilled
  278. * to the wrong stack (exception stack) while executing the exception
  279. * handler.
  280. */
  281. .section .KernelExceptionVector.text, "ax"
  282. .global _KernelExceptionVector
  283. _KernelExceptionVector:
  284. wsr a2, EXCSAVE1
  285. movi a2, ExceptionHandler
  286. jx a2
  287. .section .UserExceptionVector.text, "ax"
  288. .global _UserExceptionVector
  289. _UserExceptionVector:
  290. wsr a2, EXCSAVE1
  291. movi a2, ExceptionHandler
  292. jx a2
  293. #if !XCHAL_HAVE_XEA1
  294. .section .DoubleExceptionVector.text, "ax"
  295. .global _DoubleExceptionVector
  296. _DoubleExceptionVector:
  297. #ifdef __XTENSA_CALL0_ABI__
  298. wsr a0, EXCSAVE1
  299. movi a0, hang # report and ask user to reset board
  300. callx0 a0
  301. #else
  302. wsr a4, EXCSAVE1
  303. movi a4, hang # report and ask user to reset board
  304. callx4 a4
  305. #endif
  306. #endif
  307. /* Does not return here */
  308. .text
  309. .align 4
  310. ExceptionHandler:
  311. rsr a2, EXCCAUSE # find handler
  312. #if XCHAL_HAVE_WINDOWED
  313. /* Special case for alloca handler */
  314. bnei a2, 5, 1f # jump if not alloca exception
  315. addi a1, a1, -16 - 4 # create a small stack frame
  316. s32i a3, a1, 0 # and save a3 (a2 still in excsave1)
  317. movi a2, fast_alloca_exception
  318. jx a2 # jump to fast_alloca_exception
  319. #endif
  320. /* All other exceptions go here: */
  321. /* Create ptrace stack and save a0...a3 */
  322. 1: addi a2, a1, - PT_SIZE - 16
  323. s32i a0, a2, PT_AREG + 0 * 4
  324. s32i a1, a2, PT_AREG + 1 * 4
  325. s32i a3, a2, PT_AREG + 3 * 4
  326. rsr a3, EXCSAVE1
  327. s32i a3, a2, PT_AREG + 2 * 4
  328. mov a1, a2
  329. /* Save remaining AR registers */
  330. s32i a4, a1, PT_AREG + 4 * 4
  331. s32i a5, a1, PT_AREG + 5 * 4
  332. s32i a6, a1, PT_AREG + 6 * 4
  333. s32i a7, a1, PT_AREG + 7 * 4
  334. s32i a8, a1, PT_AREG + 8 * 4
  335. s32i a9, a1, PT_AREG + 9 * 4
  336. s32i a10, a1, PT_AREG + 10 * 4
  337. s32i a11, a1, PT_AREG + 11 * 4
  338. s32i a12, a1, PT_AREG + 12 * 4
  339. s32i a13, a1, PT_AREG + 13 * 4
  340. s32i a14, a1, PT_AREG + 14 * 4
  341. s32i a15, a1, PT_AREG + 15 * 4
  342. /* Save SRs */
  343. #if XCHAL_HAVE_WINDOWED
  344. rsr a2, WINDOWSTART
  345. s32i a2, a1, PT_WINDOWSTART
  346. #endif
  347. rsr a2, SAR
  348. rsr a3, EPC1
  349. rsr a4, EXCVADDR
  350. s32i a2, a1, PT_SAR
  351. s32i a3, a1, PT_PC
  352. s32i a4, a1, PT_EXCVADDR
  353. #if XCHAL_HAVE_LOOPS
  354. movi a2, 0
  355. rsr a3, LBEG
  356. xsr a2, LCOUNT
  357. s32i a3, a1, PT_LBEG
  358. rsr a3, LEND
  359. s32i a2, a1, PT_LCOUNT
  360. s32i a3, a1, PT_LEND
  361. #endif
  362. /* Set up C environment and call registered handler */
  363. /* Setup stack, PS.WOE = 1, PS.EXCM = 0, PS.INTLEVEL = EXCM level. */
  364. rsr a2, EXCCAUSE
  365. #if XCHAL_HAVE_XEA1
  366. movi a3, (1<<PS_WOE_BIT) | 1
  367. #elif __XTENSA_CALL0_ABI__
  368. movi a3, XCHAL_EXCM_LEVEL
  369. #else
  370. movi a3, (1<<PS_WOE_BIT) | XCHAL_EXCM_LEVEL
  371. #endif
  372. xsr a3, PS
  373. rsync
  374. s32i a2, a1, PT_EXCCAUSE
  375. s32i a3, a1, PT_PS
  376. movi a0, exc_table
  377. addx4 a0, a2, a0
  378. l32i a0, a0, 0
  379. #ifdef __XTENSA_CALL0_ABI__
  380. mov a2, a1 # Provide stack frame as only argument
  381. callx0 a0
  382. l32i a3, a1, PT_PS
  383. #else
  384. mov a6, a1 # Provide stack frame as only argument
  385. callx4 a0
  386. #endif
  387. /* Restore PS and go to exception mode (PS.EXCM=1) */
  388. wsr a3, PS
  389. /* Restore SR registers */
  390. #if XCHAL_HAVE_LOOPS
  391. l32i a2, a1, PT_LBEG
  392. l32i a3, a1, PT_LEND
  393. l32i a4, a1, PT_LCOUNT
  394. wsr a2, LBEG
  395. wsr a3, LEND
  396. wsr a4, LCOUNT
  397. #endif
  398. l32i a2, a1, PT_SAR
  399. l32i a3, a1, PT_PC
  400. wsr a2, SAR
  401. wsr a3, EPC1
  402. #if XCHAL_HAVE_WINDOWED
  403. /* Do we need to simulate a MOVSP? */
  404. l32i a2, a1, PT_WINDOWSTART
  405. addi a3, a2, -1
  406. and a2, a2, a3
  407. beqz a2, 1f # Skip if regs were spilled before exc.
  408. rsr a2, WINDOWSTART
  409. addi a3, a2, -1
  410. and a2, a2, a3
  411. bnez a2, 1f # Skip if registers aren't spilled now
  412. addi a2, a1, -16
  413. l32i a4, a2, 0
  414. l32i a5, a2, 4
  415. s32i a4, a1, PT_SIZE + 0
  416. s32i a5, a1, PT_SIZE + 4
  417. l32i a4, a2, 8
  418. l32i a5, a2, 12
  419. s32i a4, a1, PT_SIZE + 8
  420. s32i a5, a1, PT_SIZE + 12
  421. #endif
  422. /* Restore address register */
  423. 1: l32i a15, a1, PT_AREG + 15 * 4
  424. l32i a14, a1, PT_AREG + 14 * 4
  425. l32i a13, a1, PT_AREG + 13 * 4
  426. l32i a12, a1, PT_AREG + 12 * 4
  427. l32i a11, a1, PT_AREG + 11 * 4
  428. l32i a10, a1, PT_AREG + 10 * 4
  429. l32i a9, a1, PT_AREG + 9 * 4
  430. l32i a8, a1, PT_AREG + 8 * 4
  431. l32i a7, a1, PT_AREG + 7 * 4
  432. l32i a6, a1, PT_AREG + 6 * 4
  433. l32i a5, a1, PT_AREG + 5 * 4
  434. l32i a4, a1, PT_AREG + 4 * 4
  435. l32i a3, a1, PT_AREG + 3 * 4
  436. l32i a2, a1, PT_AREG + 2 * 4
  437. l32i a0, a1, PT_AREG + 0 * 4
  438. l32i a1, a1, PT_AREG + 1 * 4 # Remove ptrace stack frame
  439. rfe
  440. #endif /* XCHAL_HAVE_EXCEPTIONS */
  441. #if XCHAL_HAVE_WINDOWED
  442. /*
  443. * Window overflow and underflow handlers.
  444. * The handlers must be 64 bytes apart, first starting with the underflow
  445. * handlers underflow-4 to underflow-12, then the overflow handlers
  446. * overflow-4 to overflow-12.
  447. *
  448. * Note: We rerun the underflow handlers if we hit an exception, so
  449. * we try to access any page that would cause a page fault early.
  450. */
  451. .section .WindowVectors.text, "ax"
  452. /* 4-Register Window Overflow Vector (Handler) */
  453. .align 64
  454. .global _WindowOverflow4
  455. _WindowOverflow4:
  456. s32e a0, a5, -16
  457. s32e a1, a5, -12
  458. s32e a2, a5, -8
  459. s32e a3, a5, -4
  460. rfwo
  461. /* 4-Register Window Underflow Vector (Handler) */
  462. .align 64
  463. .global _WindowUnderflow4
  464. _WindowUnderflow4:
  465. l32e a0, a5, -16
  466. l32e a1, a5, -12
  467. l32e a2, a5, -8
  468. l32e a3, a5, -4
  469. rfwu
  470. /*
  471. * a0: a0
  472. * a1: new stack pointer = a1 - 16 - 4
  473. * a2: available, saved in excsave1
  474. * a3: available, saved on stack *a1
  475. */
  476. /* 15*/ .byte 0xff
  477. fast_alloca_exception: /* must be at _WindowUnderflow4 + 16 */
  478. /* 16*/ rsr a2, PS
  479. /* 19*/ rsr a3, WINDOWBASE
  480. /* 22*/ extui a2, a2, PS_OWB_SHIFT, PS_OWB_SHIFT
  481. /* 25*/ xor a2, a2, a3
  482. /* 28*/ rsr a3, PS
  483. /* 31*/ slli a2, a2, PS_OWB_SHIFT
  484. /* 34*/ xor a2, a3, a2
  485. /* 37*/ wsr a2, PS
  486. /* 40*/ _l32i a3, a1, 0
  487. /* 43*/ addi a1, a1, 16 + 4
  488. /* 46*/ rsr a2, EXCSAVE1
  489. /* 49*/ rotw -1
  490. /* 52*/ _bbci.l a4, 31, _WindowUnderflow4 /* 0x: call4 */
  491. /* 55*/ rotw -1
  492. /* 58*/ _bbci.l a8, 30, _WindowUnderflow8 /* 10: call8 */
  493. /* 61*/ _j __WindowUnderflow12 /* 11: call12 */
  494. /* 64*/
  495. /* 8-Register Window Overflow Vector (Handler) */
  496. .align 64
  497. .global _WindowOverflow8
  498. _WindowOverflow8:
  499. s32e a0, a9, -16
  500. l32e a0, a1, -12
  501. s32e a2, a9, -8
  502. s32e a1, a9, -12
  503. s32e a3, a9, -4
  504. s32e a4, a0, -32
  505. s32e a5, a0, -28
  506. s32e a6, a0, -24
  507. s32e a7, a0, -20
  508. rfwo
  509. /* 8-Register Window Underflow Vector (Handler) */
  510. .align 64
  511. .global _WindowUnderflow8
  512. _WindowUnderflow8:
  513. l32e a1, a9, -12
  514. l32e a0, a9, -16
  515. l32e a7, a1, -12
  516. l32e a2, a9, -8
  517. l32e a4, a7, -32
  518. l32e a3, a9, -4
  519. l32e a5, a7, -28
  520. l32e a6, a7, -24
  521. l32e a7, a7, -20
  522. rfwu
  523. /* 12-Register Window Overflow Vector (Handler) */
  524. .align 64
  525. .global _WindowOverflow12
  526. _WindowOverflow12:
  527. s32e a0, a13, -16
  528. l32e a0, a1, -12
  529. s32e a1, a13, -12
  530. s32e a2, a13, -8
  531. s32e a3, a13, -4
  532. s32e a4, a0, -48
  533. s32e a5, a0, -44
  534. s32e a6, a0, -40
  535. s32e a7, a0, -36
  536. s32e a8, a0, -32
  537. s32e a9, a0, -28
  538. s32e a10, a0, -24
  539. s32e a11, a0, -20
  540. rfwo
  541. /* 12-Register Window Underflow Vector (Handler) */
  542. .org _WindowOverflow12 + 64 - 3
  543. __WindowUnderflow12:
  544. rotw -1
  545. .global _WindowUnderflow12
  546. _WindowUnderflow12:
  547. l32e a1, a13, -12
  548. l32e a0, a13, -16
  549. l32e a11, a1, -12
  550. l32e a2, a13, -8
  551. l32e a4, a11, -48
  552. l32e a8, a11, -32
  553. l32e a3, a13, -4
  554. l32e a5, a11, -44
  555. l32e a6, a11, -40
  556. l32e a7, a11, -36
  557. l32e a9, a11, -28
  558. l32e a10, a11, -24
  559. l32e a11, a11, -20
  560. rfwu
  561. #endif /* XCHAL_HAVE_WINDOWED */