| @@ -1,259 +1,259 @@ | | | @@ -1,259 +1,259 @@ |
1 | /* $NetBSD: locore.S,v 1.41 2020/07/08 10:18:00 skrll Exp $ */ | | 1 | /* $NetBSD: locore.S,v 1.42 2020/08/28 12:31:44 skrll Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (C) 1994-1997 Mark Brinicombe | | 4 | * Copyright (C) 1994-1997 Mark Brinicombe |
5 | * Copyright (C) 1994 Brini | | 5 | * Copyright (C) 1994 Brini |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. All advertising materials mentioning features or use of this software | | 16 | * 3. All advertising materials mentioning features or use of this software |
17 | * must display the following acknowledgement: | | 17 | * must display the following acknowledgement: |
18 | * This product includes software developed by Brini. | | 18 | * This product includes software developed by Brini. |
19 | * 4. The name of Brini may not be used to endorse or promote products | | 19 | * 4. The name of Brini may not be used to endorse or promote products |
20 | * derived from this software without specific prior written permission. | | 20 | * derived from this software without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR | | 22 | * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
25 | * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | | 25 | * IN NO EVENT SHALL BRINI BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | | 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
27 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | | 27 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
28 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | | 28 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | | 29 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
30 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | | 30 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
31 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #include "opt_arm_debug.h" | | 34 | #include "opt_arm_debug.h" |
35 | | | 35 | |
36 | #include "assym.h" | | 36 | #include "assym.h" |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | #include <sys/syscall.h> | | 38 | #include <sys/syscall.h> |
39 | #include <sys/errno.h> | | 39 | #include <sys/errno.h> |
40 | #include <arm/asm.h> | | 40 | #include <arm/asm.h> |
41 | #include <arm/locore.h> | | 41 | #include <arm/locore.h> |
42 | | | 42 | |
43 | /* What size should this really be ? It is only used by init_arm() */ | | 43 | /* What size should this really be ? It is only used by initarm() */ |
44 | #define INIT_ARM_STACK_SIZE 2048 | | 44 | #define INIT_ARM_STACK_SIZE 2048 |
45 | | | 45 | |
46 | RCSID("$NetBSD: locore.S,v 1.41 2020/07/08 10:18:00 skrll Exp $") | | 46 | RCSID("$NetBSD: locore.S,v 1.42 2020/08/28 12:31:44 skrll Exp $") |
47 | | | 47 | |
48 | /* | | 48 | /* |
49 | * This is for kvm_mkdb, and should be the address of the beginning | | 49 | * This is for kvm_mkdb, and should be the address of the beginning |
50 | * of the kernel text segment (not necessarily the same as kernbase). | | 50 | * of the kernel text segment (not necessarily the same as kernbase). |
51 | */ | | 51 | */ |
52 | | | 52 | |
53 | .text | | 53 | .text |
54 | .align 0 | | 54 | .align 0 |
55 | | | 55 | |
56 | ENTRY_NP(kernel_text) | | 56 | ENTRY_NP(kernel_text) |
57 | | | 57 | |
58 | ASENTRY_NP(start) | | 58 | ASENTRY_NP(start) |
59 | mrs r1, cpsr /* fetch CPSR value */ | | 59 | mrs r1, cpsr /* fetch CPSR value */ |
60 | msr spsr_sx, r1 /* set SPSR[23:8] to known value */ | | 60 | msr spsr_sx, r1 /* set SPSR[23:8] to known value */ |
61 | | | 61 | |
62 | /* | | 62 | /* |
63 | * Get bss bounds (r1, r2), curlwp or curcpu (r8), and set initial | | 63 | * Get bss bounds (r1, r2), curlwp or curcpu (r8), and set initial |
64 | * stack. | | 64 | * stack. |
65 | */ | | 65 | */ |
66 | adr r1, .Lstart | | 66 | adr r1, .Lstart |
67 | ldmia r1, {r1, r2, r8, sp} | | 67 | ldmia r1, {r1, r2, r8, sp} |
68 | | | 68 | |
69 | #if defined(TPIDRPRW_IS_CURCPU) || defined(TPIDRPRW_IS_CURLWP) | | 69 | #if defined(TPIDRPRW_IS_CURCPU) || defined(TPIDRPRW_IS_CURLWP) |
70 | mcr p15, 0, r8, c13, c0, 4 | | 70 | mcr p15, 0, r8, c13, c0, 4 |
71 | #endif | | 71 | #endif |
72 | #if defined(TPIDRPRW_IS_CURLWP) | | 72 | #if defined(TPIDRPRW_IS_CURLWP) |
73 | ldr r8, [r8, #L_CPU] /* r8 needs curcpu in it */ | | 73 | ldr r8, [r8, #L_CPU] /* r8 needs curcpu in it */ |
74 | #endif | | 74 | #endif |
75 | | | 75 | |
76 | mov r4, #0 | | 76 | mov r4, #0 |
77 | #ifdef _ARM_ARCH_DWORD_OK | | 77 | #ifdef _ARM_ARCH_DWORD_OK |
78 | mov r5, #0 | | 78 | mov r5, #0 |
79 | #endif | | 79 | #endif |
80 | .L1: | | 80 | .L1: |
81 | #ifdef _ARM_ARCH_DWORD_OK | | 81 | #ifdef _ARM_ARCH_DWORD_OK |
82 | strd r4, r5, [r1], #0x0008 /* Zero the bss */ | | 82 | strd r4, r5, [r1], #0x0008 /* Zero the bss */ |
83 | #else | | 83 | #else |
84 | str r4, [r1], #0x0004 /* Zero the bss */ | | 84 | str r4, [r1], #0x0004 /* Zero the bss */ |
85 | #endif | | 85 | #endif |
86 | cmp r1, r2 | | 86 | cmp r1, r2 |
87 | blt .L1 | | 87 | blt .L1 |
88 | | | 88 | |
89 | mrc p15, 0, r3, c0, c0, 0 /* get our cpuid and save it early */ | | 89 | mrc p15, 0, r3, c0, c0, 0 /* get our cpuid and save it early */ |
90 | str r3, [r8, #CI_ARM_CPUID] | | 90 | str r3, [r8, #CI_ARM_CPUID] |
91 | | | 91 | |
92 | mov fp, #0x00000000 /* trace back starts here */ | | 92 | mov fp, #0x00000000 /* trace back starts here */ |
93 | bl _C_LABEL(initarm) /* Off we go */ | | 93 | bl _C_LABEL(initarm) /* Off we go */ |
94 | | | 94 | |
95 | /* initarm will return the new stack pointer. */ | | 95 | /* initarm will return the new stack pointer. */ |
96 | mov sp, r0 | | 96 | mov sp, r0 |
97 | | | 97 | |
98 | mov fp, #0x00000000 /* trace back starts here */ | | 98 | mov fp, #0x00000000 /* trace back starts here */ |
99 | mov ip, sp | | 99 | mov ip, sp |
100 | push {fp, ip, lr, pc} | | 100 | push {fp, ip, lr, pc} |
101 | sub fp, ip, #4 | | 101 | sub fp, ip, #4 |
102 | | | 102 | |
103 | bl _C_LABEL(main) /* call main()! */ | | 103 | bl _C_LABEL(main) /* call main()! */ |
104 | | | 104 | |
105 | adr r0, .Lmainreturned | | 105 | adr r0, .Lmainreturned |
106 | b _C_LABEL(panic) | | 106 | b _C_LABEL(panic) |
107 | /* NOTREACHED */ | | 107 | /* NOTREACHED */ |
108 | | | 108 | |
109 | ENTRY_NP(uartputc) | | 109 | ENTRY_NP(uartputc) |
110 | #ifdef EARLYCONS | | 110 | #ifdef EARLYCONS |
111 | b ___CONCAT(EARLYCONS, _platform_early_putchar) | | 111 | b ___CONCAT(EARLYCONS, _platform_early_putchar) |
112 | #endif | | 112 | #endif |
113 | RET | | 113 | RET |
114 | ASEND(uartputc) | | 114 | ASEND(uartputc) |
115 | | | 115 | |
116 | .Lstart: | | 116 | .Lstart: |
117 | .word _edata | | 117 | .word _edata |
118 | .word _end | | 118 | .word _end |
119 | #if defined(TPIDRPRW_IS_CURLWP) | | 119 | #if defined(TPIDRPRW_IS_CURLWP) |
120 | .word _C_LABEL(lwp0) | | 120 | .word _C_LABEL(lwp0) |
121 | #else | | 121 | #else |
122 | .word _C_LABEL(cpu_info_store) | | 122 | .word _C_LABEL(cpu_info_store) |
123 | #endif | | 123 | #endif |
124 | #if !defined(__HAVE_GENERIC_START) | | 124 | #if !defined(__HAVE_GENERIC_START) |
125 | .word svcstk_end | | 125 | .word svcstk_end |
126 | #else | | 126 | #else |
127 | .word start_stacks_top | | 127 | .word start_stacks_top |
128 | #endif | | 128 | #endif |
129 | | | 129 | |
130 | .Lmainreturned: | | 130 | .Lmainreturned: |
131 | .asciz "main() returned" | | 131 | .asciz "main() returned" |
132 | .align 0 | | 132 | .align 0 |
133 | ASEND(start) | | 133 | ASEND(start) |
134 | | | 134 | |
135 | #if !defined(__HAVE_GENERIC_START) | | 135 | #if !defined(__HAVE_GENERIC_START) |
136 | .bss | | 136 | .bss |
137 | #ifdef __ARM_EABI__ | | 137 | #ifdef __ARM_EABI__ |
138 | .align 3 | | 138 | .align 3 |
139 | #endif | | 139 | #endif |
140 | svcstk: | | 140 | svcstk: |
141 | .space INIT_ARM_STACK_SIZE | | 141 | .space INIT_ARM_STACK_SIZE |
142 | svcstk_end: | | 142 | svcstk_end: |
143 | #endif | | 143 | #endif |
144 | | | 144 | |
145 | .text | | 145 | .text |
146 | .align 0 | | 146 | .align 0 |
147 | | | 147 | |
148 | #ifndef OFW | | 148 | #ifndef OFW |
149 | /* OFW based systems will used OF_boot() */ | | 149 | /* OFW based systems will used OF_boot() */ |
150 | | | 150 | |
151 | .Lcpufuncs: | | 151 | .Lcpufuncs: |
152 | .word _C_LABEL(cpufuncs) | | 152 | .word _C_LABEL(cpufuncs) |
153 | | | 153 | |
154 | ENTRY_NP(cpu_reset) | | 154 | ENTRY_NP(cpu_reset) |
155 | #ifdef _ARM_ARCH_6 | | 155 | #ifdef _ARM_ARCH_6 |
156 | cpsid if, #PSR_SVC32_MODE | | 156 | cpsid if, #PSR_SVC32_MODE |
157 | #else | | 157 | #else |
158 | mrs r2, cpsr | | 158 | mrs r2, cpsr |
159 | bic r2, r2, #(PSR_MODE) | | 159 | bic r2, r2, #(PSR_MODE) |
160 | orr r2, r2, #(PSR_SVC32_MODE) | | 160 | orr r2, r2, #(PSR_SVC32_MODE) |
161 | orr r2, r2, #(IF32_bits) | | 161 | orr r2, r2, #(IF32_bits) |
162 | msr cpsr_c, r2 | | 162 | msr cpsr_c, r2 |
163 | #endif | | 163 | #endif |
164 | | | 164 | |
165 | ldr r0, .Lcpufuncs | | 165 | ldr r0, .Lcpufuncs |
166 | mov lr, pc | | 166 | mov lr, pc |
167 | ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] | | 167 | ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] |
168 | | | 168 | |
169 | /* | | 169 | /* |
170 | * Load the virutal address of the MD reset function first. | | 170 | * Load the virutal address of the MD reset function first. |
171 | */ | | 171 | */ |
172 | ldr r4, .Lcpu_reset_address | | 172 | ldr r4, .Lcpu_reset_address |
173 | ldr r4, [r4] | | 173 | ldr r4, [r4] |
174 | cmp r4, #0 | | 174 | cmp r4, #0 |
175 | | | 175 | |
176 | /* | | 176 | /* |
177 | * If virtual address is NULL, we must be using the physical address | | 177 | * If virtual address is NULL, we must be using the physical address |
178 | */ | | 178 | */ |
179 | ldreq r4, .Lcpu_reset_address_paddr | | 179 | ldreq r4, .Lcpu_reset_address_paddr |
180 | ldreq r4, [r4] | | 180 | ldreq r4, [r4] |
181 | | | 181 | |
182 | /* | | 182 | /* |
183 | * MMU & IDC off, 32 bit program & data space | | 183 | * MMU & IDC off, 32 bit program & data space |
184 | * Hurl ourselves into the ROM | | 184 | * Hurl ourselves into the ROM |
185 | */ | | 185 | */ |
186 | mrc p15, 0, r0, c1, c0, 0 | | 186 | mrc p15, 0, r0, c1, c0, 0 |
187 | bic r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE) | | 187 | bic r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE) |
188 | bic r0, r0, #(CPU_CONTROL_IC_ENABLE) | | 188 | bic r0, r0, #(CPU_CONTROL_IC_ENABLE) |
189 | orr r0, r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) | | 189 | orr r0, r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) |
190 | mcr p15, 0, r0, c1, c0, 0 | | 190 | mcr p15, 0, r0, c1, c0, 0 |
191 | mcreq p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ | | 191 | mcreq p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ |
192 | mov pc, r4 | | 192 | mov pc, r4 |
193 | | | 193 | |
194 | /* | | 194 | /* |
195 | * cpu_reset_address contains the address to branch to, to complete | | 195 | * cpu_reset_address contains the address to branch to, to complete |
196 | * the CPU reset after turning the MMU off | | 196 | * the CPU reset after turning the MMU off |
197 | * This variable is provided by the hardware specific code | | 197 | * This variable is provided by the hardware specific code |
198 | */ | | 198 | */ |
199 | .Lcpu_reset_address: | | 199 | .Lcpu_reset_address: |
200 | .word _C_LABEL(cpu_reset_address) | | 200 | .word _C_LABEL(cpu_reset_address) |
201 | .Lcpu_reset_address_paddr: | | 201 | .Lcpu_reset_address_paddr: |
202 | .word _C_LABEL(cpu_reset_address_paddr) | | 202 | .word _C_LABEL(cpu_reset_address_paddr) |
203 | END(cpu_reset) | | 203 | END(cpu_reset) |
204 | #endif /* OFW */ | | 204 | #endif /* OFW */ |
205 | | | 205 | |
206 | /* | | 206 | /* |
207 | * setjump + longjmp | | 207 | * setjump + longjmp |
208 | */ | | 208 | */ |
209 | ENTRY(setjmp) | | 209 | ENTRY(setjmp) |
210 | stmia r0, {r4-r14} | | 210 | stmia r0, {r4-r14} |
211 | mov r0, #0x00000000 | | 211 | mov r0, #0x00000000 |
212 | RET | | 212 | RET |
213 | END(setjmp) | | 213 | END(setjmp) |
214 | | | 214 | |
215 | ENTRY(longjmp) | | 215 | ENTRY(longjmp) |
216 | ldmia r0, {r4-r14} | | 216 | ldmia r0, {r4-r14} |
217 | mov r0, #0x00000001 | | 217 | mov r0, #0x00000001 |
218 | RET | | 218 | RET |
219 | END(longjmp) | | 219 | END(longjmp) |
220 | | | 220 | |
221 | .data | | 221 | .data |
222 | .global _C_LABEL(esym) | | 222 | .global _C_LABEL(esym) |
223 | _C_LABEL(esym): .word _C_LABEL(end) | | 223 | _C_LABEL(esym): .word _C_LABEL(end) |
224 | | | 224 | |
225 | ENTRY_NP(abort) | | 225 | ENTRY_NP(abort) |
226 | b _C_LABEL(abort) | | 226 | b _C_LABEL(abort) |
227 | END(abort) | | 227 | END(abort) |
228 | | | 228 | |
229 | /* | | 229 | /* |
230 | * Part of doing a system dump, we need to save a switchframe onto the | | 230 | * Part of doing a system dump, we need to save a switchframe onto the |
231 | * stack, then save the rest of the registers into the dumppcb. | | 231 | * stack, then save the rest of the registers into the dumppcb. |
232 | */ | | 232 | */ |
233 | ENTRY(dumpsys) | | 233 | ENTRY(dumpsys) |
234 | /* push registers onto stack */ | | 234 | /* push registers onto stack */ |
235 | mov ip, sp | | 235 | mov ip, sp |
236 | push {r4-r7, ip, lr} | | 236 | push {r4-r7, ip, lr} |
237 | | | 237 | |
238 | /* fill in dumppcb */ | | 238 | /* fill in dumppcb */ |
239 | ldr r0, .Ldumppcb | | 239 | ldr r0, .Ldumppcb |
240 | | | 240 | |
241 | #ifndef __XSCALE__ | | 241 | #ifndef __XSCALE__ |
242 | add r2, r0, #(PCB_R8) | | 242 | add r2, r0, #(PCB_R8) |
243 | stmia r2, {r8-r13} | | 243 | stmia r2, {r8-r13} |
244 | #else | | 244 | #else |
245 | strd r8, r9, [r0, #(PCB_R8)] | | 245 | strd r8, r9, [r0, #(PCB_R8)] |
246 | strd r10, r11, [r0, #(PCB_R10)] | | 246 | strd r10, r11, [r0, #(PCB_R10)] |
247 | strd r12, r13, [r0, #(PCB_R12)] | | 247 | strd r12, r13, [r0, #(PCB_R12)] |
248 | #endif | | 248 | #endif |
249 | | | 249 | |
250 | bl _C_LABEL(dodumpsys) | | 250 | bl _C_LABEL(dodumpsys) |
251 | | | 251 | |
252 | /* unwind the stack */ | | 252 | /* unwind the stack */ |
253 | pop {r4-r7, ip, pc} | | 253 | pop {r4-r7, ip, pc} |
254 | | | 254 | |
255 | .Ldumppcb: | | 255 | .Ldumppcb: |
256 | .word _C_LABEL(dumppcb) | | 256 | .word _C_LABEL(dumppcb) |
257 | END(dumpsys) | | 257 | END(dumpsys) |
258 | | | 258 | |
259 | /* End of locore.S */ | | 259 | /* End of locore.S */ |