53
53
//! `__sbss` and `__ebss` is zeroed, and the memory between `__sdata` and
54
54
//! `__edata` is initialised with the data found at `__sidata`.
55
55
//!
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
+ //!
56
76
//! ### C-Compatible Functions
57
77
//!
58
78
//! * `kmain` - the `extern "C"` entry point to your application.
213
233
//! `_irq_handler`
214
234
//! * `_asm_default_fiq_handler` - an FIQ handler that just spins
215
235
//! * `_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`
216
239
//!
217
240
//! The assembly language trampolines are required because Armv7-R (and Armv8-R)
218
241
//! processors do not save a great deal of state on entry to an exception
@@ -573,12 +596,17 @@ core::arch::global_asm!(
573
596
r#"
574
597
// Work around https://github.com/rust-lang/rust/issues/127269
575
598
.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).
582
610
// Set stack pointer (right after) and mask interrupts for for UND mode (Mode 0x1B)
583
611
msr cpsr, {und_mode}
584
612
mov sp, r0
@@ -607,13 +635,19 @@ core::arch::global_asm!(
607
635
// Set stack pointer (right after) and mask interrupts for for System mode (Mode 0x1F)
608
636
msr cpsr, {sys_mode}
609
637
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:
617
651
// Initialise .bss
618
652
ldr r0, =__sbss
619
653
ldr r1, =__ebss
@@ -635,11 +669,8 @@ core::arch::global_asm!(
635
669
stm r0!, {{r3}}
636
670
b 0b
637
671
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
643
674
"# ,
644
675
und_mode = const {
645
676
Cpsr :: new_with_raw_value( 0 )
@@ -703,7 +734,18 @@ core::arch::global_asm!(
703
734
.global _default_start
704
735
.type _default_start, %function
705
736
_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 .
707
749
.size _default_start, . - _default_start
708
750
"#
709
751
) ;
@@ -731,30 +773,42 @@ core::arch::global_asm!(
731
773
cmp r0, {cpsr_mode_hyp}
732
774
bne 1f
733
775
// 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
735
780
// 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
738
783
// 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
743
788
// 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
748
793
dsb
749
794
isb
750
795
eret
751
796
1:
797
+ // Set up stacks. r0 points to the bottom of the hyp stack.
798
+ bl _stack_setup
752
799
// Set the VBAR (for EL1) to _vector_table. NB: This isn't required on
753
800
// Armv7-R because that only supports 'low' (default) or 'high'.
754
801
ldr r0, =_vector_table
755
802
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 .
758
812
.size _default_start, . - _default_start
759
813
"# ,
760
814
cpsr_mode_hyp = const ProcessorMode :: Hyp as u8 ,
0 commit comments