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