Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / tests / tcg / arm / system / boot.S
blob7d43372c66e0d019072df4edd0b696c56bec5a1a
1 /*
2  * Minimal ArmV7 system boot code.
3  *
4  * Using semihosting for serial output and exit functions.
5  */
7 /*
8  * Semihosting interface on ARM AArch32
9  * R0 - semihosting call number
10  * R1 - semihosting parameter
11  */
12 #define semihosting_call svc 0x123456
13 #define SYS_WRITEC      0x03    /* character to debug channel */
14 #define SYS_WRITE0      0x04    /* string to debug channel */
15 #define SYS_EXIT        0x18
17 #define ADP_Stopped_ApplicationExit     0x20026
18 #define ADP_Stopped_InternalError       0x20024
21  * Helper macro for annotating functions with elf type and size.
22  */
23 .macro endf name
24         .global \name
25         .type           \name, %function
26         .size           \name, . - \name
27 .endm
29         .section        .interrupt_vector, "ax"
30         .align  5
32 vector_table:
33         b   reset               /* reset vector */
34         b   undef_instr        /* undefined instruction vector */
35         b   software_intr       /* software interrupt vector */
36         b   prefetch_abort              /* prefetch abort vector */
37         b   data_abort          /* data abort vector */
38         nop                                 /* reserved */
39         b   IRQ_handler         /* IRQ vector */
40         b   FIQ_handler         /* FIQ vector */
42 endf    vector_table
44         .text
45 __start:
46         ldr     r0, =vector_table
47         mcr     p15, 0, r0, c12, c0, 0  /* Set up VBAR */
49         ldr     sp, =stack_end          /* Set up the stack */
50         bl      mmu_setup               /* Set up the MMU */
51         bl      main                    /* Jump to main */
53 endf    __start
55 _exit:
56         cmp r0, #0
57         ite EQ  // if-then-else. "EQ" is for if equal, else otherwise
58         ldreq r1, =ADP_Stopped_ApplicationExit // if r0 == 0
59         ldrne r1, =ADP_Stopped_InternalError   // else
60         mov r0, #SYS_EXIT
61         semihosting_call
63 endf    _exit
66  * Helper Functions
67  */
69 mmu_setup:
70         /*
71          * The MMU setup for this is very simple using two stage one
72          * translations. The first 1Mb section points to the text
73          * section and the second points to the data and rss.
74          * Currently the fattest test only needs ~50k for that so we
75          * have plenty of space.
76          *
77          * The short descriptor Section format is as follows:
78          *
79          *  PA[31:20] - Section Base Address
80          *  NS[19] - Non-secure bit
81          *  0[18] - Section (1 for Super Section)
82          *  nG[17] - Not global bit
83          *  S[16] - Shareable
84          *  TEX[14:12] - Memory Region Attributes
85          *  AP[15, 11:10] - Access Permission Bits
86          *  IMPDEF[9]
87          *  Domain[8:5]
88          *  XN[4] - Execute never bit
89          *  C[3] - Memory Region Attributes
90          *  B[2] - Memory Region Attributes
91          *  1[1]
92          *  PXN[0] - Privileged Execute Never
93          *
94          * r0 - point at the table
95          * r1 - address
96          * r2 - entry
97          * r3 - common section bits
98          * r4 - scratch
99          */
101         /*
102          * Memory Region Bits
103          *
104          *   TEX[14:12] = 000
105          *     C[3]     = 1
106          *     B[2]     = 1
107          *
108          * Outer and Inner WB, no write allocate
109          */
110         mov r3, #0
111         ldr r4, =(3 << 2)
112         orr r3, r4, r4
114         /* Section bit */
115         orr r3, r3, #2
117         /* Page table setup (identity mapping). */
118         ldr r0, =ttb
120         /* First block: .text/RO/execute enabled */
121         ldr r1, =.text
122         ldr r2, =0xFFF00000                     /* 1MB block alignment */
123         and r2, r1, r2
124         orr r2, r2, r3                          /* common bits */
125         orr r2, r2, #(1 << 15)                  /* AP[2] = 1 */
126         orr r2, r2, #(1 << 10)                  /* AP[0] = 1 => RO @ PL1 */
128         lsr r4, r2, #(20 - 2)
129         str r2, [r0, r4, lsl #0]                /* write entry */
131         /* Second block: .data/RW/no execute */
132         ldr r1, =.data
133         ldr r2, =0xFFF00000                     /* 1MB block alignment */
134         and r2, r1, r2
135         orr r2, r2, r3                          /* common bits */
136         orr r2, r2, #(1 << 10)                  /* AP[0] = 1 => RW @ PL1 */
137         orr r2, r2, #(1 << 4)                   /* XN[4] => no execute */
139         lsr r4, r2, #(20 - 2)
140         str r2, [r0, r4, lsl #0]                /* write entry */
142         /*
143          * DACR - Domain Control
144          *
145          * Enable client mode for domain 0 (we don't use any others)
146          */
147         ldr r0, =0x1
148         mcr p15, 0, r0, c3, c0, 0
150         /*
151          * TTCBR - Translation Table Base Control Register
152          *
153          * EAE[31] = 0, 32-bit translation, short descriptor format
154          * N[2:0] = 5 ( TTBRO uses 31:14-5 => 9 bit lookup stage )
155          */
156         ldr r0, =0x5
157         mcr p15, 0, r0, c1, c0, 2
159         /*
160          * TTBR0 -Translation Table Base Register 0
161          *
162          * [31:9] = Base address of table
163          *
164          * QEMU doesn't really care about the cache sharing
165          * attributes so we don't need to either.
166          */
167         ldr r0, =ttb
168         mcr p15, 0, r0, c2, c0, 0
170         /*
171          * SCTLR- System Control Register
172          *
173          * TE[30] = 0, exceptions to A32 state
174          * AFE[29] = 0, AP[0] is the access permissions bit
175          * EE[25] = 0, Little-endian
176          * WXN[19] = 0 = no effect, Write does not imply XN (execute never)
177          * I[12] = Instruction cachability control
178          * C[2] = Data cachability control
179          * M[0] = 1, enable stage 1 address translation for EL0/1
180          *
181          * At this point virtual memory is enabled.
182          */
183         ldr r0, =0x1005
184         mcr p15, 0, r0, c1, c0, 0
186         isb
188         mov  pc, lr  /* done, return to caller */
190 endf    mmu_setup
192 /* Output a single character to serial port */
193 __sys_outc:
194         STMFD sp!, {r0-r1}  // push r0, r1 onto stack
195         mov r1, sp
196         mov r0, #SYS_WRITEC
197         semihosting_call
198         LDMFD sp!, {r0-r1}  // pop r0, r1 from stack
199         bx lr
201 endf    __sys_outc
203 reset:
204         ldr     r1, =reset_error
205         b exception_handler
207 endf    reset
209 undef_instr:
210         ldr     r1, =undef_intr_error
211         b exception_handler
213 endf    undef_instr
215 software_intr:
216         ldr     r1, =software_intr_error
217         b exception_handler
219 endf    software_intr
221 prefetch_abort:
222         ldr     r1, =prefetch_abort_error
223         b exception_handler
225 endf    prefetch_abort
227 data_abort:
228         ldr     r1, =data_abort_error
229         b exception_handler
231 endf    data_abort
233 IRQ_handler:
234         ldr     r1, =irq_error
235         b exception_handler
237 endf    IRQ_handler
239 FIQ_handler:
240         ldr     r1, =fiq_error
241         b exception_handler
243 endf    FIQ_handler
246  * Initiate a exit semihosting call whenever there is any exception
247  * r1 already holds the string.
248  */
249 exception_handler:
250         mov     r0, #SYS_WRITE0
251         semihosting_call
252         mov     r0, #SYS_EXIT
253         mov     r1, #1
254         semihosting_call
256 endf    exception_handler
259  * We implement a stub raise() function which errors out as tests
260  * shouldn't trigger maths errors.
261  */
262         .global raise
263 raise:
264         mov     r0, #SYS_WRITE0
265         ldr     r1, =maths_error
266         semihosting_call
267         mov     r0, #SYS_EXIT
268         ldr     r1, =ADP_Stopped_InternalError
269         semihosting_call
271 endf    raise
273         .data
275 .data
277 reset_error:
278         .ascii "Reset exception occurred.\n\0"
280 undef_intr_error:
281         .ascii "Undefined Instruction Exception Occurred.\n\0"
283 software_intr_error:
284         .ascii "Software Interrupt Occurred.\n\0"
286 prefetch_abort_error:
287         .ascii "Prefetch Abort Occurred.\n\0"
289 data_abort_error:
290         .ascii "Data Abort Occurred.\n\0"
292 irq_error:
293         .ascii "IRQ exception occurred.\n\0"
295 fiq_error:
296         .ascii "FIQ exception occurred.\n\0"
298 maths_error:
299         .ascii "Software maths exception.\n\0"
302         /*
303          * 1st Stage Translation table
304          * 4096 entries, indexed by [31:20]
305          * each entry covers 1Mb of address space
306          * aligned on 16kb
307          */
308         .align  15
309 ttb:
310         .space  (4096 * 4), 0
312         .align  12
314         /* Space for stack */
315         .align  5
316         .section .bss
317 stack:
318         .space 65536, 0
319 stack_end: