Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:05

0001 /**
0002  * @file
0003  *
0004  * @brief Boot and system start code.
0005  */
0006 
0007 /*
0008  * Copyright (C) 2008, 2020 embedded brains GmbH & Co. KG
0009  *
0010  * Copyright (c) 2016 Pavel Pisa <pisa@cmp.felk.cvut.cz>
0011  *
0012  *  Czech Technical University in Prague
0013  *  Zikova 1903/4
0014  *  166 36 Praha 6
0015  *  Czech Republic
0016  *
0017  * The license and distribution terms for this file may be
0018  * found in the file LICENSE in this distribution or at
0019  * http://www.rtems.org/license/LICENSE.
0020  */
0021 
0022 #include <rtems/asm.h>
0023 #include <rtems/score/percpu.h>
0024 
0025 #include <bspopts.h>
0026 #include <bsp/irq.h>
0027 
0028 #include <dev/cache/arm-data-cache-loop-set-way.h>
0029 
0030     /* Global symbols */
0031     .globl  _start
0032     .type   _start, %function
0033     .globl  bsp_start_hook_0_done
0034     .type   bsp_start_hook_0_done, %function
0035     .globl  bsp_start_vector_table_begin
0036     .globl  bsp_start_vector_table_end
0037     .globl  bsp_start_vector_table_size
0038     .globl  bsp_vector_table_size
0039 
0040     .section    ".bsp_start_text", "ax"
0041 
0042 #ifdef BSP_START_ZIMAGE_HEADER
0043 .rept   8
0044     mov r0, r0
0045 .endr
0046     b   .Lafter_header
0047     .word   0x016f2818      /* Magic numbers to help the loader */
0048     .word   bsp_section_start_begin /* zImage start address */
0049     .word   bsp_section_data_end    /* zImage end address */
0050 .Lafter_header:
0051 #endif /* BSP_START_ZIMAGE_HEADER */
0052 
0053 #if defined(ARM_MULTILIB_ARCH_V4)
0054 
0055 #ifdef BSP_START_IN_HYP_SUPPORT
0056     .globl  bsp_start_hyp_vector_table_begin
0057 #endif
0058 
0059     .arm
0060 
0061 /*
0062  * This is the exception vector table and the pointers to the default
0063  * exceptions handlers.
0064  */
0065 
0066 bsp_start_vector_table_begin:
0067 
0068     ldr pc, .Lhandler_addr_reset
0069     ldr pc, .Lhandler_addr_undef
0070     ldr pc, .Lhandler_addr_swi
0071     ldr pc, .Lhandler_addr_prefetch
0072     ldr pc, .Lhandler_addr_abort
0073 
0074 #ifdef BSP_START_VECTOR_RESERVED_SLOT
0075     BSP_START_VECTOR_RESERVED_SLOT
0076 #else
0077     udf
0078 #endif
0079 
0080     ldr pc, .Lhandler_addr_irq
0081     ldr pc, .Lhandler_addr_fiq
0082 
0083 #ifdef BSP_START_VECTOR_ADDRESS_TABLE_ALIGNMENT
0084 .balign BSP_START_VECTOR_ADDRESS_TABLE_ALIGNMENT
0085 #endif
0086 
0087 .Lhandler_addr_reset:
0088 
0089 #ifdef BSP_START_RESET_VECTOR
0090     .word   BSP_START_RESET_VECTOR
0091 #else
0092     .word   _start
0093 #endif
0094 
0095 .Lhandler_addr_undef:
0096 
0097     .word   _ARMV4_Exception_undef_default
0098 
0099 .Lhandler_addr_swi:
0100 
0101     .word   _ARMV4_Exception_swi_default
0102 
0103 .Lhandler_addr_prefetch:
0104 
0105     .word   _ARMV4_Exception_pref_abort_default
0106 
0107 .Lhandler_addr_abort:
0108 
0109     .word   _ARMV4_Exception_data_abort_default
0110 
0111 .Lhandler_addr_reserved:
0112 
0113     .word   0
0114 
0115 .Lhandler_addr_irq:
0116 
0117     .word   _ARMV4_Exception_interrupt
0118 
0119 .Lhandler_addr_fiq:
0120 
0121     .word   _ARMV4_Exception_fiq_default
0122 
0123 bsp_start_vector_table_end:
0124 
0125 #ifdef BSP_START_IN_HYP_SUPPORT
0126 bsp_start_hyp_vector_table_begin:
0127     udf
0128     ldr pc, .Lhandler_addr_hyp_undef
0129     udf
0130     udf
0131     udf
0132     udf
0133     udf
0134     udf
0135 
0136 .Lhandler_addr_hyp_reset:
0137     .word   0
0138 
0139 .Lhandler_addr_hyp_undef:
0140     .word   _ARMV4_Exception_undef_default
0141 
0142 .Lhandler_addr_hyp_swi:
0143     .word   0
0144 
0145 .Lhandler_addr_hyp_prefetch:
0146     .word   0
0147 
0148 .Lhandler_addr_hyp_abort:
0149     .word   0
0150 
0151 .Lhandler_addr_hyp_hyp:
0152     .word   0
0153 
0154 .Lhandler_addr_hyp_irq:
0155     .word   0
0156 
0157 .Lhandler_addr_hyp_fiq:
0158     .word   0
0159 #endif
0160 
0161 /* Start entry */
0162 
0163 _start:
0164 
0165     /*
0166      * We do not save the context since we do not return to the boot
0167      * loader.  Boot loaders may pass the device tree in r2.  Do not touch
0168      * r2 until bsp_fdt_copy() is called.
0169      */
0170 
0171 #ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
0172     mov r0, #0
0173     mov r1, #0
0174     mov r2, #0
0175     mov r3, #0
0176     mov r4, #0
0177     mov r5, #0
0178     mov r6, #0
0179     mov r7, #0
0180     mov r8, #0
0181     mov r9, #0
0182     mov r10, #0
0183     mov r11, #0
0184     mov r12, #0
0185     mov r13, #0
0186 #endif
0187 
0188 #if __ARM_ARCH >= 7
0189     /*
0190      * Write to BPIALL (Branch Predictor Invalidate All) to invalidate all
0191      * branch predictors.  There is no need to use BPIALLIS (Branch
0192      * Predictor Invalidate All, Inner Shareable) since this code is
0193      * executed on all processors used by RTEMS.
0194      */
0195     mov r0, #0
0196     mcr p15, 0, r0, c7, c5, 6
0197 #endif
0198 
0199 #ifdef RTEMS_SMP
0200     /* Read MPIDR and get current processor index */
0201     mrc p15, 0, r7, c0, c0, 5
0202     and r7, #0xff
0203 
0204     /*
0205      * Check that this is a configured processor.  If not, then there is
0206      * not much that can be done since we do not have a stack available for
0207      * this processor.  Just loop forever in this case.
0208      */
0209     ldr r1, =_SMP_Processor_configured_maximum
0210     ldr r1, [r1]
0211     cmp r1, r7
0212     bgt .Lconfigured_processor
0213 .Linvalid_processor_wait_for_ever:
0214     wfe
0215     b   .Linvalid_processor_wait_for_ever
0216 .Lconfigured_processor:
0217 
0218         /*
0219          * Get current per-CPU control and store it in PL1 only Thread ID
0220          * Register (TPIDRPRW).
0221          */
0222     ldr r1, =_Per_CPU_Information
0223     add r1, r1, r7, asl #PER_CPU_CONTROL_SIZE_LOG2
0224     mcr p15, 0, r1, c13, c0, 4
0225 
0226 #endif
0227 
0228     /* Calculate interrupt stack area end for current processor */
0229     ldr r1, =_ISR_Stack_size
0230 #ifdef RTEMS_SMP
0231     add r3, r7, #1
0232     mul r1, r1, r3
0233 #endif
0234     ldr r0, =_ISR_Stack_area_begin
0235     add r3, r1, r0
0236 
0237     /* Save original CPSR value */
0238     mrs r4, cpsr
0239 
0240 #ifdef BSP_START_IN_HYP_SUPPORT
0241     orr r0, r4, #(ARM_PSR_I | ARM_PSR_F)
0242     msr cpsr, r4
0243 
0244     and r0, r4, #ARM_PSR_M_MASK
0245     cmp r0, #ARM_PSR_M_HYP
0246     bne .L_skip_hyp_svc_switch
0247 
0248     /* Boot loader starts kernel in HYP mode, switch to SVC necessary */
0249 
0250     ldr r1, =bsp_stack_hyp_size
0251     mov sp, r3
0252     sub r3, r3, r1
0253 
0254     ldr r0, =bsp_start_hyp_vector_table_begin
0255     mcr p15, 4, r0, c12, c0, 0
0256 
0257     mov r0, #0
0258     mcr p15, 4, r0, c1, c1, 0
0259     mcr p15, 4, r0, c1, c1, 2
0260     mcr p15, 4, r0, c1, c1, 3
0261 /*
0262  * HSCTLR.TE
0263  * optional start of hypervisor handlers in Thumb mode
0264  *  orr r0, #(1 << 30)
0265  */
0266     mcr p15, 4, r0, c1, c0, 0   /* HSCTLR */
0267     mrc p15, 4, r0, c1, c1, 1   /* HDCR */
0268     and r0, #0x1f       /* Preserve HPMN */
0269     mcr p15, 4, r0, c1, c1, 1   /* HDCR */
0270 
0271     /* Prepare SVC mode for eret */
0272     mrs r0, cpsr
0273     bic r0, r0, #ARM_PSR_M_MASK
0274     orr r0, r0, #ARM_PSR_M_SVC
0275     msr spsr_cxsf, r0
0276 
0277     ldr r0, =.L_hyp_to_svc_return
0278     .inst 0xe12ef300    /* msr ELR_hyp, r0 */
0279     mov r0, sp
0280     .inst 0xe160006e    /* eret */
0281 .L_hyp_to_svc_return:
0282     mov sp, r0
0283 
0284 .L_skip_hyp_svc_switch:
0285 #endif /* BSP_START_IN_HYP_SUPPORT */
0286 
0287     /* Initialize stack pointer registers for the various modes */
0288 
0289     /* Enter FIQ mode and set up the FIQ stack pointer */
0290     mov r0, #(ARM_PSR_M_FIQ | ARM_PSR_I | ARM_PSR_F)
0291     msr cpsr, r0
0292     ldr r1, =bsp_stack_fiq_size
0293     mov sp, r3
0294     sub r3, r3, r1
0295 
0296 #ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
0297     /* These are banked FIQ mode registers */
0298     mov r8, #0
0299     mov r9, #0
0300     mov r10, #0
0301     mov r11, #0
0302     mov r12, #0
0303 #endif
0304 
0305     /* Enter ABT mode and set up the ABT stack pointer */
0306     mov r0, #(ARM_PSR_M_ABT | ARM_PSR_I | ARM_PSR_F)
0307     msr cpsr, r0
0308     ldr r1, =bsp_stack_abt_size
0309     mov sp, r3
0310     sub r3, r3, r1
0311 
0312     /* Enter UND mode and set up the UND stack pointer */
0313     mov r0, #(ARM_PSR_M_UND | ARM_PSR_I | ARM_PSR_F)
0314     msr cpsr, r0
0315     ldr r1, =bsp_stack_und_size
0316     mov sp, r3
0317     sub r3, r3, r1
0318 
0319     /* Enter IRQ mode and set up the IRQ stack pointer */
0320     mov r0, #(ARM_PSR_M_IRQ | ARM_PSR_I | ARM_PSR_F)
0321     msr cpsr, r0
0322     mov sp, r3
0323 
0324     /*
0325      * Enter SVC mode and set up the SVC stack pointer, reuse IRQ stack
0326      * (interrupts are disabled).
0327      */
0328     mov r0, #(ARM_PSR_M_SVC | ARM_PSR_I | ARM_PSR_F)
0329     msr cpsr, r0
0330     mov sp, r3
0331 
0332     /* Stay in SVC mode */
0333 
0334     /* Copy device tree from boot loader */
0335 #ifdef BSP_START_COPY_FDT_FROM_U_BOOT
0336 #ifdef RTEMS_SMP
0337     cmp r7, #0
0338     bne 1f
0339 #endif
0340     mov r0, r2
0341     bl  bsp_fdt_copy
0342 1:
0343 #endif
0344 
0345 #ifdef ARM_MULTILIB_VFP
0346 #ifdef ARM_MULTILIB_HAS_CPACR
0347     /* Read CPACR */
0348     mrc p15, 0, r0, c1, c0, 2
0349 
0350     /* Enable CP10 and CP11 */
0351     orr r0, r0, #(1 << 20)
0352     orr r0, r0, #(1 << 22)
0353 
0354     /*
0355      * Clear ASEDIS and D32DIS.  Writes to D32DIS are ignored for VFP-D16.
0356      */
0357     bic r0, r0, #(3 << 30)
0358 
0359     /* Write CPACR */
0360     mcr p15, 0, r0, c1, c0, 2
0361     isb
0362 #endif
0363 
0364     /* Enable FPU */
0365     mov r0, #(1 << 30)
0366     vmsr FPEXC, r0
0367 
0368 #ifdef BSP_START_NEEDS_REGISTER_INITIALIZATION
0369     mov r0, #0
0370     vmov    d0, r0, r0
0371     vmov    d1, r0, r0
0372     vmov    d2, r0, r0
0373     vmov    d3, r0, r0
0374     vmov    d4, r0, r0
0375     vmov    d5, r0, r0
0376     vmov    d6, r0, r0
0377     vmov    d7, r0, r0
0378     vmov    d8, r0, r0
0379     vmov    d9, r0, r0
0380     vmov    d10, r0, r0
0381     vmov    d11, r0, r0
0382     vmov    d12, r0, r0
0383     vmov    d13, r0, r0
0384     vmov    d14, r0, r0
0385     vmov    d15, r0, r0
0386 #ifdef ARM_MULTILIB_VFP_D32
0387     vmov    d16, r0, r0
0388     vmov    d17, r0, r0
0389     vmov    d18, r0, r0
0390     vmov    d19, r0, r0
0391     vmov    d20, r0, r0
0392     vmov    d21, r0, r0
0393     vmov    d22, r0, r0
0394     vmov    d23, r0, r0
0395     vmov    d24, r0, r0
0396     vmov    d25, r0, r0
0397     vmov    d26, r0, r0
0398     vmov    d27, r0, r0
0399     vmov    d28, r0, r0
0400     vmov    d29, r0, r0
0401     vmov    d30, r0, r0
0402     vmov    d31, r0, r0
0403 #endif /* ARM_MULTILIB_VFP_D32 */
0404 #endif /* BSP_START_NEEDS_REGISTER_INITIALIZATION */
0405 
0406 #endif /* ARM_MULTILIB_VFP */
0407 
0408 #if (__ARM_ARCH >= 7 && __ARM_ARCH_PROFILE == 'A') || __ARM_ARCH >= 8
0409     /*
0410      * Set VBAR to the vector table in the start section and make sure
0411      * SCTLR[M, I, A, C, V] are cleared.  Afterwards, exceptions are
0412      * handled by RTEMS.
0413      */
0414     ldr r0, =bsp_start_vector_table_begin
0415     dsb
0416     mcr p15, 0, r0, c12, c0, 0
0417     mrc p15, 0, r0, c1, c0, 0
0418     bic r1, r0, #0x2800
0419     bic r1, r1, #0x7
0420     mcr p15, 0, r1, c1, c0, 0
0421     isb
0422 
0423 #ifdef RTEMS_SMP
0424     /* Skip the data cache initialization if we are a secondary processor */
0425     cmp r7, #0
0426     bne .Ldata_caches_initialized
0427 #endif
0428 
0429     /* Check previous SCTLR[C] and initialize data caches */
0430     tst r0, #0x4
0431     bne .Lclean_invalidate_data_caches
0432 
0433     /*
0434      * Invalidate the sets and ways of all data or unified cache levels
0435      * using DCISW (Data Cache line Invalidate by Set/Way).
0436      */
0437     ARM_DATA_CACHE_LOOP_SET_WAY c6
0438     b   .Ldata_caches_initialized
0439 
0440 .Lclean_invalidate_data_caches:
0441 
0442     /*
0443      * Clean and invalidate the sets and ways of all data or unified cache
0444      * levels using DCCISW (Data Cache line Clean and Invalidate by
0445      * Set/Way).
0446      */
0447     ARM_DATA_CACHE_LOOP_SET_WAY c14
0448 
0449 .Ldata_caches_initialized:
0450 
0451     /*
0452      * Invalidate the instruction cache levels using ICIALLU (Instruction
0453      * Cache Invalidate All to PoU).
0454      */
0455     mov r0, #0
0456     mcr p15, 0, r0, c7, c5, 0
0457 
0458 #if __ARM_ARCH_PROFILE == 'A'
0459     /*
0460      * Invalidate the TLB using ITLBIALL (Instruction TLB Invalidate All).
0461      */
0462     mov r0, #0
0463     mcr p15, 0, r0, c8, c7, 0
0464     isb
0465 #endif
0466 #endif /* (__ARM_ARCH >= 7 && __ARM_ARCH_PROFILE == 'A') || __ARM_ARCH >= 8 */
0467 
0468     /*
0469      * Invoke the start hook 0.
0470      *
0471      * The previous code and parts of the start hook 0 may run with an
0472      * address offset.  After the return from start hook 0 it is assumed
0473      * that the code can run at its intended position.  Thus the link
0474      * register will be loaded with the absolute address and the branch
0475      * link instruction cannot be used.  In THUMB mode the branch
0476      * instruction as a very limited address range of 2KiB.  Use a bx to
0477      * the start hook 0 address instead corrected by the address offset.
0478      */
0479     ldr lr, =bsp_start_hook_0_done
0480     mov r0, pc
0481     ldr r1, =.Lget_absolute_pc
0482 .Lget_absolute_pc:
0483     sub r1, r0
0484     ldr r7, =bsp_start_hook_0
0485     add r7, r1
0486     bx  r7
0487 
0488     /* Allow bsp_start_hook_0() hooks to jump to this label */
0489 bsp_start_hook_0_done:
0490 
0491     /*
0492      * Initialize the exception vectors.  This includes the exceptions
0493      * vectors and the pointers to the default exception handlers.
0494      */
0495 
0496     ldr r0, =bsp_vector_table_begin
0497     ldr r1, =bsp_start_vector_table_begin
0498     cmp r0, r1
0499     beq .Lvector_table_copy_done
0500     ldmia   r1!, {r2-r9}
0501     stmia   r0!, {r2-r9}
0502     ldmia   r1!, {r2-r9}
0503     stmia   r0!, {r2-r9}
0504 
0505 .Lvector_table_copy_done:
0506 
0507     /*
0508      * This code path is only executed by the primary processor.  Set the
0509      * VBAR to the normal vector table.  For secondary processors, this is
0510      * done by bsp_start_hook_0().
0511      */
0512 #if (__ARM_ARCH >= 7 && __ARM_ARCH_PROFILE == 'A') || __ARM_ARCH >= 8
0513     ldr r0, =bsp_vector_table_begin
0514     dsb
0515     mcr p15, 0, r0, c12, c0, 0
0516     isb
0517 #elif defined(__ARM_ARCH_6KZ__)
0518     mov r1, #0
0519     ldr r0, =bsp_vector_table_begin
0520     mcr p15, 0, r1, c7, c10, 4      /* DataSync */
0521     mcr p15, 0, r0, c12, c0, 0      /* Load VBAR */
0522     mcr p15, 0, r1, c7, c5, 4       /* Flush Prefetch */
0523 #endif
0524 
0525     SWITCH_FROM_ARM_TO_THUMB    r3
0526 
0527     /* Branch to start hook 1 */
0528     bl  bsp_start_hook_1
0529 
0530     /* Branch to boot card */
0531     mov r0, #0
0532     bl  boot_card
0533 
0534 #elif defined(ARM_MULTILIB_ARCH_V7M)
0535 
0536 #include <rtems/score/armv7m.h>
0537 
0538     .syntax unified
0539 
0540     .thumb
0541 
0542 bsp_start_vector_table_begin:
0543 
0544     .word   _ISR_Stack_area_end
0545     .word   _start /* Reset */
0546     .word   _ARMV7M_Exception_default /* NMI */
0547     .word   _ARMV7M_Exception_default /* Hard Fault */
0548     .word   _ARMV7M_Exception_default /* MPU Fault */
0549     .word   _ARMV7M_Exception_default /* Bus Fault */
0550     .word   _ARMV7M_Exception_default /* Usage Fault */
0551     .word   _ARMV7M_Exception_default /* Reserved */
0552     .word   _ARMV7M_Exception_default /* Reserved */
0553     .word   _ARMV7M_Exception_default /* Reserved */
0554     .word   _ARMV7M_Exception_default /* Reserved */
0555     .word   _ARMV7M_Supervisor_call /* SVC */
0556     .word   _ARMV7M_Exception_default /* Debug Monitor */
0557     .word   _ARMV7M_Exception_default /* Reserved */
0558     .word   _ARMV7M_Pendable_service_call /* PendSV */
0559     .word   _ARMV7M_Clock_handler /* SysTick */
0560     .rept   BSP_INTERRUPT_VECTOR_COUNT
0561     .word   _ARMV7M_NVIC_Interrupt_dispatch /* IRQ */
0562     .endr
0563 
0564 bsp_start_vector_table_end:
0565 
0566     .thumb_func
0567 
0568 _start:
0569 
0570 #if defined(ARM_MULTILIB_VFP) && defined(ARM_MULTILIB_HAS_CPACR)
0571     /*
0572      * Enable CP10 and CP11 coprocessors for privileged and user mode in
0573      * CPACR (bits 20-23).  Ensure that write to register completes.
0574      */
0575     ldr r0, =ARMV7M_CPACR
0576     ldr r1, [r0]
0577     orr r1, r1, #(0xf << 20)
0578     str r1, [r0]
0579     dsb
0580     isb
0581 #endif
0582 
0583     ldr sp, =_ISR_Stack_area_end
0584 
0585     /*
0586      * Set the Main Stack Pointer (MSP) to the ISR stack area end just in
0587      * case we run using the Process Stack Pointer (PSP).
0588      */
0589     mov r0, sp
0590     msr msp, r0
0591 
0592     ldr lr, =bsp_start_hook_0_done + 1
0593     b   bsp_start_hook_0
0594 
0595     /* Allow bsp_start_hook_0() hooks to jump to this label */
0596 bsp_start_hook_0_done:
0597 
0598     bl  bsp_start_hook_1
0599     movs    r0, #0
0600     bl  boot_card
0601 
0602 #endif /* defined(ARM_MULTILIB_ARCH_V7M) */
0603 
0604     .set    bsp_start_vector_table_size, bsp_start_vector_table_end - bsp_start_vector_table_begin
0605     .set    bsp_vector_table_size, bsp_start_vector_table_size