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