5353//! `__sbss` and `__ebss` is zeroed, and the memory between `__sdata` and
5454//! `__edata` is initialised with the data found at `__sidata`.
5555//!
56+ //! The stacks look like:
57+ //!
58+ //! ```text
59+ //! +------------------+ <----_stack_top
60+ //! | HYP Stack | } _hyp_stack_size bytes (Armv8-R only)
61+ //! +------------------+
62+ //! | UND Stack | } _und_stack_size bytes
63+ //! +------------------+
64+ //! | SVC Stack | } _svc_stack_size bytes
65+ //! +------------------+
66+ //! | ABT Stack | } _abt_stack_size bytes
67+ //! +------------------+
68+ //! | IRQ Stack | } _irq_stack_size bytes
69+ //! +------------------+
70+ //! | FIQ Stack | } _fiq_stack_size bytes
71+ //! +------------------+
72+ //! | SYS Stack | } No specific size
73+ //! +------------------+
74+ //! ```
75+ //!
5676//! ### C-Compatible Functions
5777//!
5878//! * `kmain` - the `extern "C"` entry point to your application.
213233//! `_irq_handler`
214234//! * `_asm_default_fiq_handler` - an FIQ handler that just spins
215235//! * `_default_handler` - a C compatible function that spins forever.
236+ //! * `_init_segments` - initialises `.bss` and `.data`
237+ //! * `_stack_setup` - initialises UND, SVC, ABT, IRQ, FIQ and SYS stacks from
238+ //! the address given in `r0`
216239//!
217240//! The assembly language trampolines are required because Armv7-R (and Armv8-R)
218241//! processors do not save a great deal of state on entry to an exception
@@ -573,12 +596,17 @@ core::arch::global_asm!(
573596 r#"
574597 // Work around https://github.com/rust-lang/rust/issues/127269
575598 .fpu vfp3-d16
576-
577- .section .text.el1_start
578- .type _el1_start, %function
579- _el1_start:
580- // Set up stacks.
581- ldr r0, =_stack_top
599+
600+ // Configure a stack for every mode. Leaves you in sys mode.
601+ //
602+ // Pass in stack top in r0.
603+ .section .text._stack_setup
604+ .global _stack_setup
605+ .type _stack_setup, %function
606+ _stack_setup:
607+ // Save LR from whatever mode we're currently in
608+ mov r2, lr
609+ // (we might not be in the same mode when we return).
582610 // Set stack pointer (right after) and mask interrupts for for UND mode (Mode 0x1B)
583611 msr cpsr, {und_mode}
584612 mov sp, r0
@@ -607,13 +635,19 @@ core::arch::global_asm!(
607635 // Set stack pointer (right after) and mask interrupts for for System mode (Mode 0x1F)
608636 msr cpsr, {sys_mode}
609637 mov sp, r0
610- // Clear the Thumb Exception bit because we're in Arm mode
611- mrc p15, 0, r0, c1, c0, 0
612- bic r0, #{te_bit}
613- mcr p15, 0, r0, c1, c0, 0
614- "# ,
615- fpu_enable!( ) ,
616- r#"
638+ // Clear the Thumb Exception bit because all our targets are currently
639+ // for Arm (A32) mode
640+ mrc p15, 0, r1, c1, c0, 0
641+ bic r1, #{te_bit}
642+ mcr p15, 0, r1, c1, c0, 0
643+ bx r2
644+ .size _stack_setup, . - _stack_setup
645+
646+ // Initialises stacks, .data and .bss
647+ .section .text._init_segments
648+ .global _init_segments
649+ .type _init_segments, %function
650+ _init_segments:
617651 // Initialise .bss
618652 ldr r0, =__sbss
619653 ldr r1, =__ebss
@@ -635,11 +669,8 @@ core::arch::global_asm!(
635669 stm r0!, {{r3}}
636670 b 0b
637671 1:
638- // Jump to application
639- bl kmain
640- // In case the application returns, loop forever
641- b .
642- .size _el1_start, . - _el1_start
672+ bx lr
673+ .size _init_segments, . - _init_segments
643674 "# ,
644675 und_mode = const {
645676 Cpsr :: new_with_raw_value( 0 )
@@ -703,7 +734,18 @@ core::arch::global_asm!(
703734 .global _default_start
704735 .type _default_start, %function
705736 _default_start:
706- ldr pc, =_el1_start
737+ // Set up stacks.
738+ ldr r0, =_stack_top
739+ bl _stack_setup
740+ // Init .data and .bss
741+ bl _init_segments
742+ "# ,
743+ fpu_enable!( ) ,
744+ r#"
745+ // Jump to application
746+ bl kmain
747+ // In case the application returns, loop forever
748+ b .
707749 .size _default_start, . - _default_start
708750 "#
709751) ;
@@ -731,30 +773,42 @@ core::arch::global_asm!(
731773 cmp r0, {cpsr_mode_hyp}
732774 bne 1f
733775 // Set stack pointer
734- ldr sp, =_stack_top
776+ ldr r0, =_stack_top
777+ mov sp, r0
778+ ldr r1, =_hyp_stack_size
779+ sub r0, r0, r1
735780 // Set the HVBAR (for EL2) to _vector_table
736- ldr r0 , =_vector_table
737- mcr p15, 4, r0 , c12, c0, 0
781+ ldr r1 , =_vector_table
782+ mcr p15, 4, r1 , c12, c0, 0
738783 // Configure HACTLR to let us enter EL1
739- mrc p15, 4, r0 , c1, c0, 1
740- mov r1 , {hactlr_bits}
741- orr r0, r0, r1
742- mcr p15, 4, r0 , c1, c0, 1
784+ mrc p15, 4, r1 , c1, c0, 1
785+ mov r2 , {hactlr_bits}
786+ orr r1, r1, r2
787+ mcr p15, 4, r1 , c1, c0, 1
743788 // Program the SPSR - enter system mode (0x1F) in Arm mode with IRQ, FIQ masked
744- mov r0 , {sys_mode}
745- msr spsr_hyp, r0
746- adr r0 , 1f
747- msr elr_hyp, r0
789+ mov r1 , {sys_mode}
790+ msr spsr_hyp, r1
791+ adr r1 , 1f
792+ msr elr_hyp, r1
748793 dsb
749794 isb
750795 eret
751796 1:
797+ // Set up stacks. r0 points to the bottom of the hyp stack.
798+ bl _stack_setup
752799 // Set the VBAR (for EL1) to _vector_table. NB: This isn't required on
753800 // Armv7-R because that only supports 'low' (default) or 'high'.
754801 ldr r0, =_vector_table
755802 mcr p15, 0, r0, c12, c0, 0
756- // go do the rest of the EL1 init
757- ldr pc, =_el1_start
803+ // Init .data and .bss
804+ bl _init_segments
805+ "# ,
806+ fpu_enable!( ) ,
807+ r#"
808+ // Jump to application
809+ bl kmain
810+ // In case the application returns, loop forever
811+ b .
758812 .size _default_start, . - _default_start
759813 "# ,
760814 cpsr_mode_hyp = const ProcessorMode :: Hyp as u8 ,
0 commit comments