entry_point.S 8.6 KB
Newer Older
1
/*
S
Shell 已提交
2
 * Copyright (c) 2006-2020, RT-Thread Development Team
3 4 5 6 7 8 9 10
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Date           Author       Notes
 * 2020-01-15     bigmagic     the first version
 * 2020-08-10     SummerGift   support clang compiler
 */

G
GuEe-GUI 已提交
11
#include "rtconfig.h"
S
Shell 已提交
12 13
.section ".text.entrypoint","ax"
.global __start
14

S
Shell 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28
__start:
#ifdef ARCH_ARM_BOOTWITH_FLUSH_CACHE
    bl      __asm_flush_dcache_all
#endif
    bl      rt_hw_cpu_id_set
    /* read cpu id, stop slave cores */
    mrs     x0, tpidr_el1
    cbz     x0, .L__cpu_0           /* .L prefix is the local label in ELF */

    /* cpu id > 0, stop */
    /* cpu id == 0 will also goto here after returned from entry() if possible */
.L__current_cpu_idle:
    wfe
    b       .L__current_cpu_idle
G
GuEe-GUI 已提交
29

S
Shell 已提交
30 31 32
.L__cpu_0:
    /* set stack before our code, Define stack pointer for current exception level */
    adr     x1, __start
33

S
Shell 已提交
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
    /* set up EL1 */
    mrs     x0, CurrentEL           /* CurrentEL Register. bit 2, 3. Others reserved */
    and     x0, x0, #12             /* clear reserved bits */

    /* running at EL3? */
    cmp     x0, #12                 /* 1100b. So, EL3 */
    bne     .L__not_in_el3          /* 11?  !EL3 -> 5: */

    /* should never be executed, just for completeness. (EL3) */
    mov     x2, #0x5b1
    msr     scr_el3, x2             /* SCR_ELn  Secure Configuration Register */
    mov     x2, #0x3c9
    msr     spsr_el3, x2            /* SPSR_ELn. Saved Program Status Register. 1111001001 */
    adr     x2, .L__not_in_el3
    msr     elr_el3, x2
    eret                            /* Exception Return: from EL3, continue from .L__not_in_el3 */

.L__not_in_el3:                     /* running at EL2 or EL1 */
    cmp     x0, #4                  /* 0x04  0100 EL1 */
    beq     .L__in_el1              /* EL1 -> 5: */

    mrs     x0, hcr_el2
    bic     x0, x0, #0xff
    msr     hcr_el2, x0

    msr     sp_el1, x1              /* in EL2, set sp of EL1 to _start */

    /* enable CNTP for EL1 */
    mrs     x0, cnthctl_el2         /* Counter-timer Hypervisor Control register */
    orr     x0, x0, #3
    msr     cnthctl_el2, x0
    msr     cntvoff_el2, xzr

    /* enable AArch64 in EL1 */
    mov     x0, #(1 << 31)          /* AArch64 */
    orr     x0, x0, #(1 << 1)       /* SWIO hardwired on Pi3 */
    msr     hcr_el2, x0
    mrs     x0, hcr_el2

    /* change execution level to EL1 */
    mov     x2, #0x3c4
    msr     spsr_el2, x2            /* 1111000100 */
    adr     x2, .L__in_el1
    msr     elr_el2, x2

    eret                            /* exception return. from EL2. continue from .L__in_el1 */

81 82 83 84 85
.macro GET_PHY reg, symbol
    adrp    \reg, \symbol
    add     \reg, \reg, #:lo12:\symbol
.endm

S
Shell 已提交
86 87 88 89 90 91 92 93
.L__in_el1:
    mov     sp, x1                  /* in EL1. Set sp to _start */

    /* Set CPACR_EL1 (Architecture Feature Access Control Register) to avoid trap from SIMD or float point instruction */
    mov     x1, #0x00300000         /* Don't trap any SIMD/FP instructions in both EL0 and EL1 */
    msr     cpacr_el1, x1

    /* clear bss */
94 95 96
    GET_PHY x1, __bss_start
    GET_PHY x2, __bss_end
    sub     x2, x2, x1              /* get bss size */
S
Shell 已提交
97

98
    and     x3, x2, #7              /* x3 is < 7 */
S
Shell 已提交
99
    ldr     x4, =~0x7
100
    and     x2, x2, x4              /* mask ~7 */
S
Shell 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

.L__clean_bss_loop:
    cbz     x2, .L__clean_bss_loop_1
    str     xzr, [x1], #8
    sub     x2, x2, #8
    b       .L__clean_bss_loop

.L__clean_bss_loop_1:
    cbz     x3, .L__jump_to_entry
    strb    wzr, [x1], #1
    sub     x3, x3, #1
    b       .L__clean_bss_loop_1

.L__jump_to_entry:          /* jump to C code, should not return */        
    bl mmu_tcr_init

117
    adr x1, __start         /* install early page table */
S
Shell 已提交
118 119 120 121 122 123 124 125
    ldr x0, =~0x1fffff
    and x0, x1, x0
    add x1, x0, #0x1000

    msr ttbr0_el1, x0
    msr ttbr1_el1, x1
    dsb sy

126 127 128 129
#ifdef RT_USING_SMART
    ldr     x2, =__start
    GET_PHY x3, __start
    sub     x3, x3, x2
130
#endif
131 132
    ldr x2, =0x40000000     /* map 1G memory for kernel space */
    bl rt_hw_mem_setup_early
S
Shell 已提交
133 134 135 136 137 138 139 140 141 142 143

    ldr x30, =after_mmu_enable  /* set LR to after_mmu_enable function, it's a v_addr */

    mrs x1, sctlr_el1
    bic x1, x1, #(3 << 3)    /* dis SA, SA0 */
    bic x1, x1, #(1 << 1)    /* dis A */
    orr x1, x1, #(1 << 12)   /* I */
    orr x1, x1, #(1 << 2)    /* C */
    orr x1, x1, #(1 << 0)    /* M */
    msr sctlr_el1, x1        /* enable MMU */

144 145
    dsb ish
    isb
S
Shell 已提交
146
    ic ialluis               /* Invalidate all instruction caches in Inner Shareable domain to Point of Unification */
147 148
    dsb ish
    isb
S
Shell 已提交
149
    tlbi vmalle1             /* Invalidate all stage 1 translations used at EL1 with the current VMID */
150 151
    dsb ish
    isb
S
Shell 已提交
152 153 154
    ret

after_mmu_enable:
155
#ifdef RT_USING_SMART
S
Shell 已提交
156 157 158 159 160 161 162 163 164 165 166
    mrs x0, tcr_el1          /* disable ttbr0, only using kernel space */
    orr x0, x0, #(1 << 7)
    msr tcr_el1, x0
    msr ttbr0_el1, xzr
    dsb sy
#endif

    mov     x0, #1
    msr     spsel, x0
    adr     x1, __start
    mov     sp, x1           /* sp_el1 set to _start */
167

S
Shell 已提交
168
    b  rtthread_startup
G
GuEe-GUI 已提交
169 170

#ifdef RT_USING_SMP
S
Shell 已提交
171 172 173
/**
 *  secondary cpu
 */
174

175
.global _secondary_cpu_entry
S
Shell 已提交
176 177 178
_secondary_cpu_entry:
    bl      rt_hw_cpu_id_set
    adr     x1, __start
179

S
Shell 已提交
180
    /* set up EL1 */
181
    mrs     x0, CurrentEL           /* CurrentEL Register. bit 2, 3. Others reserved */
S
Shell 已提交
182 183 184 185 186 187 188 189 190 191 192 193
    and     x0, x0, #12             /* clear reserved bits */

    /* running at EL3? */
    cmp     x0, #12                 /* 1100b. So, EL3 */
    bne     .L__not_in_el3_cpux          /* 11?  !EL3 -> 5: */

    /* should never be executed, just for completeness. (EL3) */
    mov     x2, #0x5b1
    msr     scr_el3, x2             /* SCR_ELn  Secure Configuration Register */
    mov     x2, #0x3c9
    msr     spsr_el3, x2            /* SPSR_ELn. Saved Program Status Register. 1111001001 */
    adr     x2, .L__not_in_el3_cpux
194
    msr     elr_el3, x2
S
Shell 已提交
195 196 197 198 199 200 201 202 203
    eret                            /* Exception Return: from EL3, continue from .L__not_in_el3 */

.L__not_in_el3_cpux:                     /* running at EL2 or EL1 */
    cmp     x0, #4                  /* 0x04  0100 EL1 */
    beq     .L__in_el1_cpux              /* EL1 -> 5: */
 
    mrs     x0, hcr_el2
    bic     x0, x0, #0xff
    msr     hcr_el2, x0
204

S
Shell 已提交
205
    msr     sp_el1, x1              /* in EL2, set sp of EL1 to _start */
206

S
Shell 已提交
207
    /* enable CNTP for EL1 */
208 209 210 211 212
    mrs     x0, cnthctl_el2         /* Counter-timer Hypervisor Control register */
    orr     x0, x0, #3
    msr     cnthctl_el2, x0
    msr     cntvoff_el2, xzr

S
Shell 已提交
213 214
    /* enable AArch64 in EL1 */
    mov     x0, #(1 << 31)          /* AArch64 */
215 216
    orr     x0, x0, #(1 << 1)       /* SWIO hardwired on Pi3 */
    msr     hcr_el2, x0
S
Shell 已提交
217
    mrs     x0, hcr_el2
218

S
Shell 已提交
219 220 221 222
    /* change execution level to EL1 */
    mov     x2, #0x3c4
    msr     spsr_el2, x2            /* 1111000100 */
    adr     x2, .L__in_el1_cpux
223 224
    msr     elr_el2, x2

S
Shell 已提交
225
    eret                            /* exception return. from EL2. continue from .L__in_el1 */
226

S
Shell 已提交
227 228 229 230 231
.L__in_el1_cpux:
    mrs     x0, tpidr_el1
    /* each cpu init stack is 8k */
    sub     x1, x1, x0, lsl #13
    mov     sp, x1                  /* in EL1. Set sp to _start */
232

S
Shell 已提交
233 234 235
    /* Set CPACR_EL1 (Architecture Feature Access Control Register) to avoid trap from SIMD or float point instruction */
    mov     x1, #0x00300000         /* Don't trap any SIMD/FP instructions in both EL0 and EL1 */
    msr     cpacr_el1, x1
G
GuEe-GUI 已提交
236

S
Shell 已提交
237 238 239 240 241 242
.L__jump_to_entry_cpux:                   /* jump to C code, should not return */

    /* init mmu early */

    bl mmu_tcr_init

243
    adr x1, __start             /* GET & setup early page table */
S
Shell 已提交
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
    ldr x0, =~0x1fffff
    and x0, x1, x0
    add x1, x0, #0x1000

    msr ttbr0_el1, x0
    msr ttbr1_el1, x1
    dsb sy

    ldr x30, =after_mmu_enable_cpux  /* set LR to after_mmu_enable function, it's a v_addr */

    mrs x1, sctlr_el1
    bic x1, x1, #(3 << 3)    /* dis SA, SA0 */
    bic x1, x1, #(1 << 1)    /* dis A */
    orr x1, x1, #(1 << 12)   /* I */
    orr x1, x1, #(1 << 2)    /* C */
    orr x1, x1, #(1 << 0)    /* M */
    msr sctlr_el1, x1        /* enable MMU */

    dsb sy
    isb sy
    ic ialluis               /* Invalidate all instruction caches in Inner Shareable domain to Point of Unification */
    dsb sy
    isb sy
    tlbi vmalle1             /* Invalidate all stage 1 translations used at EL1 with the current VMID */
    dsb sy
    isb sy
    ret

after_mmu_enable_cpux:
    mrs x0, tcr_el1          /* disable ttbr0, only using kernel space */
    orr x0, x0, #(1 << 7)
    msr tcr_el1, x0
    msr ttbr0_el1, xzr
    dsb sy

    mov     x0, #1
    msr     spsel, x0
    mrs     x0, tpidr_el1
    /* each cpu init stack is 8k */
    adr     x1, __start
    sub     x1, x1, x0, lsl #13
    mov     sp, x1                  /* in EL1. Set sp to _start */

    b rt_hw_secondary_cpu_bsp_start
G
GuEe-GUI 已提交
288
#endif