xtensa: clean up CONFIG_SYS_TEXT_ADDR
[platform/kernel/u-boot.git] / arch / xtensa / cpu / start.S
1 /*
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
62 2:      .long   _start
63 1:      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
155 1:      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
190 2:      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
197 3:      /* 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, (XTENSA_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
289 relocate_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
374 ExceptionHandler:
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
392 1:      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
513 1:      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
581 fast_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 */