blob: 0fafb1c4f8e6df9999274774452afbc3bc6ec2d5 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
Chris Zankelc978b522016-08-10 18:36:44 +03002/*
3 * (C) Copyright 2008 - 2013 Tensilica Inc.
4 * (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
Chris Zankelc978b522016-08-10 18:36:44 +03005 */
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
612: .long _start
621: 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
1541: 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 && \
Trevor Woernerb7b4af02019-05-03 09:40:56 -0400167 !(defined(CONFIG_SYS_DCACHE_OFF) && defined(CONFIG_SYS_ICACHE_OFF))
Chris Zankelc978b522016-08-10 18:36:44 +0300168 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
1882: 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
1953: /* 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
Max Filippov10117a22018-02-12 15:39:19 -0800227 movi sp, (XTENSA_SYS_TEXT_ADDR - 16) & 0xfffffff0
Chris Zankelc978b522016-08-10 18:36:44 +0300228
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
287relocate_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
372ExceptionHandler:
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
3901: 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
5111: 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
579fast_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 */