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