diff --git a/aarch32-rt/src/arch_v4/abort.rs b/aarch32-rt/src/arch_v4/abort.rs index 12e5549..bc0f807 100644 --- a/aarch32-rt/src/arch_v4/abort.rs +++ b/aarch32-rt/src/arch_v4/abort.rs @@ -5,11 +5,10 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp2 - // Called from the vector table when we have an undefined exception. // Saves state and calls a C-compatible handler like // `extern "C" fn _data_abort_handler(addr: usize);` - .section .text._asm_default_data_abort_handler + .pushsection .text._asm_default_data_abort_handler .arm .global _asm_default_data_abort_handler .type _asm_default_data_abort_handler, %function @@ -18,8 +17,7 @@ core::arch::global_asm!( push {{ r12 }} // Save preserved register R12 - can now use it mrs r12, spsr // grab SPSR push {{ r12 }} // save SPSR value - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding) "#, @@ -38,6 +36,7 @@ core::arch::global_asm!( pop {{ r12 }} // restore R12 movs pc, lr // return from exception .size _asm_default_data_abort_handler, . - _asm_default_data_abort_handler + .popsection "# ); @@ -46,11 +45,10 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp2 - // Called from the vector table when we have a prefetch abort. // Saves state and calls a C-compatible handler like // `extern "C" fn _prefetch_abort_handler(addr: usize);` - .section .text._asm_default_prefetch_abort_handler + .pushsection .text._asm_default_prefetch_abort_handler .arm .global _asm_default_prefetch_abort_handler .type _asm_default_prefetch_abort_handler, %function @@ -59,8 +57,7 @@ core::arch::global_asm!( push {{ r12 }} // Save preserved register R12 - can now use it mrs r12, spsr // grab SPSR push {{ r12 }} // save SPSR value - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding) "#, @@ -79,5 +76,6 @@ core::arch::global_asm!( pop {{ r12 }} // restore R12 movs pc, lr // return from exception .size _asm_default_prefetch_abort_handler, . - _asm_default_prefetch_abort_handler + .popsection "#, ); diff --git a/aarch32-rt/src/arch_v4/hvc.rs b/aarch32-rt/src/arch_v4/hvc.rs index 58f2b10..3c67491 100644 --- a/aarch32-rt/src/arch_v4/hvc.rs +++ b/aarch32-rt/src/arch_v4/hvc.rs @@ -7,12 +7,13 @@ core::arch::global_asm!( .fpu vfp2 // Never called but makes the linker happy - .section .text._asm_default_hvc_handler + .pushsection .text._asm_default_hvc_handler .arm .global _asm_default_hvc_handler .type _asm_default_hvc_handler, %function _asm_default_hvc_handler: b . .size _asm_default_hvc_handler, . - _asm_default_hvc_handler + .popsection "#, ); diff --git a/aarch32-rt/src/arch_v4/interrupt.rs b/aarch32-rt/src/arch_v4/interrupt.rs index a82296b..b6509a4 100644 --- a/aarch32-rt/src/arch_v4/interrupt.rs +++ b/aarch32-rt/src/arch_v4/interrupt.rs @@ -11,7 +11,10 @@ core::arch::global_asm!( // Called from the vector table when we have an interrupt. // Saves state and calls a C-compatible handler like // `extern "C" fn _irq_handler();` - .section .text._asm_default_irq_handler + // + // See https://developer.arm.com/documentation/dui0203/j/handling-processor-exceptions/armv6-and-earlier--armv7-a-and-armv7-r-profiles/interrupt-handlers + // for details on how we need to save LR_irq, SPSR_irq and LR_sys. + .pushsection .text._asm_default_irq_handler .arm .global _asm_default_irq_handler .type _asm_default_irq_handler, %function @@ -22,8 +25,7 @@ core::arch::global_asm!( push {{ lr }} // save it to IRQ stack using LR msr cpsr_c, {sys_mode} // switch to system mode so we can handle another interrupt (because if we interrupt irq mode we trash our own shadow registers) push {{ lr }} // Save LR of system mode before using it for stack alignment - mov lr, sp // align SP down to eight byte boundary using LR - and lr, lr, 7 // + and lr, sp, 7 // align SP down to eight byte boundary using LR sub sp, lr // SP now aligned - only push 64-bit values from here push {{ r0-r3, r12, lr }} // push alignment amount (in LR) and preserved registers "#, @@ -41,6 +43,7 @@ core::arch::global_asm!( msr spsr, lr // ldmfd sp!, {{ pc }}^ // return from exception (^ => restore SPSR to CPSR) .size _asm_default_irq_handler, . - _asm_default_irq_handler + .popsection "#, // sys mode with IRQ masked sys_mode = const { diff --git a/aarch32-rt/src/arch_v4/svc.rs b/aarch32-rt/src/arch_v4/svc.rs index ab96d5c..b652aba 100644 --- a/aarch32-rt/src/arch_v4/svc.rs +++ b/aarch32-rt/src/arch_v4/svc.rs @@ -6,11 +6,10 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp2 - // Called from the vector table when we have an software interrupt. // Saves state and calls a C-compatible handler like // `extern "C" fn _svc_handler(arg: u32, frame: &Frame) -> u32;` - .section .text._asm_default_svc_handler + .pushsection .text._asm_default_svc_handler .arm .global _asm_default_svc_handler .type _asm_default_svc_handler, %function @@ -18,8 +17,7 @@ core::arch::global_asm!( push {{ r12, lr }} // save LR and R12 - can now use R12 (but leave LR alone for SVC code lookup) mrs r12, spsr // grab SPSR using R12 push {{ r12 }} // save SPSR value - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r6, r12 }} // push alignment amount, and stacked SVC argument registers (must be even number of regs for alignment) mov r12, sp // save SP for integer frame @@ -48,6 +46,7 @@ core::arch::global_asm!( msr spsr, lr // ldmfd sp!, {{ r12, pc }}^ // restore R12 and return from exception (^ => restore SPSR to CPSR) .size _asm_default_svc_handler, . - _asm_default_svc_handler + .popsection "#, t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() }, ); diff --git a/aarch32-rt/src/arch_v4/undefined.rs b/aarch32-rt/src/arch_v4/undefined.rs index ccd4713..26f1c0a 100644 --- a/aarch32-rt/src/arch_v4/undefined.rs +++ b/aarch32-rt/src/arch_v4/undefined.rs @@ -5,13 +5,13 @@ core::arch::global_asm!( r#" // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp2 - + // Called from the vector table when we have an undefined exception. // Saves state and calls a C-compatible handler like // `extern "C" fn _undefined_handler(addr: usize) -> usize;` // or // `extern "C" fn _undefined_handler(addr: usize) -> !;` - .section .text._asm_default_undefined_handler + .pushsection .text._asm_default_undefined_handler .arm .global _asm_default_undefined_handler .type _asm_default_undefined_handler, %function @@ -23,8 +23,7 @@ core::arch::global_asm!( ite eq // Adjust LR to point to faulting instruction - see p.1206 of the ARMv7-A architecture manual. subeq lr, lr, #4 // Subtract 4 in Arm Mode subne lr, lr, #2 // Subtract 2 in Thumb Mode - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding) "#, @@ -43,6 +42,7 @@ core::arch::global_asm!( pop {{ r12 }} // restore R12 movs pc, lr // return from exception (movs => restore SPSR to CPSR) .size _asm_default_undefined_handler, . - _asm_default_undefined_handler + .popsection "#, t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() }, ); diff --git a/aarch32-rt/src/arch_v7/abort.rs b/aarch32-rt/src/arch_v7/abort.rs index 8a2093d..9551677 100644 --- a/aarch32-rt/src/arch_v7/abort.rs +++ b/aarch32-rt/src/arch_v7/abort.rs @@ -5,19 +5,19 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp3 - .section .text._asm_default_data_abort_handler // Called from the vector table when we have an undefined exception. // Saves state and calls a C-compatible handler like // `extern "C" fn _data_abort_handler(addr: usize);` + .pushsection .text._asm_default_data_abort_handler + .arm .global _asm_default_data_abort_handler .type _asm_default_data_abort_handler, %function _asm_default_data_abort_handler: sub lr, lr, #8 // Subtract 8 from LR, see p.1214 of the ARMv7-A architecture manual. srsfd sp!, #{abt_mode} // store return state to ABT stack push {{ r12 }} // Save preserved register R12 - can now use it - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding) "#, @@ -35,6 +35,7 @@ core::arch::global_asm!( str lr, [sp] // overwrite the saved LR with the one from the C handler rfefd sp! // return from exception .size _asm_default_data_abort_handler, . - _asm_default_data_abort_handler + .popsection "#, abt_mode = const crate::ProcessorMode::Abt as u8, ); @@ -43,20 +44,19 @@ core::arch::global_asm!( r#" // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp3 - .section .text._asm_default_prefetch_abort_handler - + // Called from the vector table when we have a prefetch abort. // Saves state and calls a C-compatible handler like // `extern "C" fn _prefetch_abort_handler(addr: usize);` - .global _asm_default_prefetch_abort_handler + .pushsection .text._asm_default_prefetch_abort_handler .arm + .global _asm_default_prefetch_abort_handler .type _asm_default_prefetch_abort_handler, %function _asm_default_prefetch_abort_handler: sub lr, lr, #4 // Subtract 8 from LR, see p.1212 of the ARMv7-A architecture manual. srsfd sp!, #{abt_mode} // store return state to ABT stack push {{ r12 }} // save R12 - can now use it - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding) "#, @@ -74,6 +74,7 @@ core::arch::global_asm!( str lr, [sp] // overwrite the saved LR with the one from the C handler rfefd sp! // return from exception .size _asm_default_prefetch_abort_handler, . - _asm_default_prefetch_abort_handler + .popsection "#, abt_mode = const crate::ProcessorMode::Abt as u8, ); diff --git a/aarch32-rt/src/arch_v7/hvc.rs b/aarch32-rt/src/arch_v7/hvc.rs index 3547498..3320b42 100644 --- a/aarch32-rt/src/arch_v7/hvc.rs +++ b/aarch32-rt/src/arch_v7/hvc.rs @@ -7,7 +7,7 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp3 - .section .text._asm_default_hvc_handler + .pushsection .text._asm_default_hvc_handler // Called from the vector table when we have an hypervisor call. // Saves state and calls a C-compatible handler like @@ -33,6 +33,7 @@ core::arch::global_asm!( pop {{ r12, lr }} // pop state from stack eret // Return from the asm handler .size _asm_default_hvc_handler, . - _asm_default_hvc_handler + .popsection "#, ); @@ -45,12 +46,13 @@ core::arch::global_asm!( // Never called but makes the linker happy - .section .text._asm_default_hvc_handler + .pushsection .text._asm_default_hvc_handler .arm .global _asm_default_hvc_handler .type _asm_default_hvc_handler, %function _asm_default_hvc_handler: b . .size _asm_default_hvc_handler, . - _asm_default_hvc_handler + .popsection "#, ); diff --git a/aarch32-rt/src/arch_v7/interrupt.rs b/aarch32-rt/src/arch_v7/interrupt.rs index dab9b3c..d9499c6 100644 --- a/aarch32-rt/src/arch_v7/interrupt.rs +++ b/aarch32-rt/src/arch_v7/interrupt.rs @@ -6,11 +6,14 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp3 - .section .text._asm_default_irq_handler - // Called from the vector table when we have an interrupt. // Saves state and calls a C-compatible handler like // `extern "C" fn _irq_handler();` + // + // See https://developer.arm.com/documentation/dui0203/j/handling-processor-exceptions/armv6-and-earlier--armv7-a-and-armv7-r-profiles/interrupt-handlers + // for details on how we need to save LR_irq, SPSR_irq and LR_sys. + .pushsection .text._asm_default_irq_handler + .arm .global _asm_default_irq_handler .type _asm_default_irq_handler, %function _asm_default_irq_handler: @@ -18,8 +21,7 @@ core::arch::global_asm!( srsfd sp!, #{sys_mode} // store return state to SYS stack cps #{sys_mode} // switch to system mode so we can handle another interrupt (because if we interrupt irq mode we trash our own shadow registers) push {{ lr }} // save adjusted LR to SYS stack - mov lr, sp // align SP down to eight byte boundary using LR - and lr, lr, 7 // + and lr, sp, 7 // align SP down to eight byte boundary using LR sub sp, lr // SP now aligned - only push 64-bit values from here push {{ r0-r3, r12, lr }} // push alignment amount (in LR) and preserved registers "#, @@ -34,6 +36,7 @@ core::arch::global_asm!( pop {{ lr }} // restore adjusted LR rfefd sp! // return from exception .size _asm_default_irq_handler, . - _asm_default_irq_handler + .popsection "#, sys_mode = const crate::ProcessorMode::Sys as u8, ); diff --git a/aarch32-rt/src/arch_v7/svc.rs b/aarch32-rt/src/arch_v7/svc.rs index cadc631..ae68eaa 100644 --- a/aarch32-rt/src/arch_v7/svc.rs +++ b/aarch32-rt/src/arch_v7/svc.rs @@ -5,19 +5,18 @@ core::arch::global_asm!( r#" // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp3 - + // Called from the vector table when we have an software interrupt. // Saves state and calls a C-compatible handler like // `extern "C" fn _svc_handler(arg: u32, frame: &Frame) -> u32;` - .section .text._asm_default_svc_handler + .pushsection .text._asm_default_svc_handler .arm .global _asm_default_svc_handler .type _asm_default_svc_handler, %function _asm_default_svc_handler: srsfd sp!, #{svc_mode} // store return state to SVC stack push {{ r12, lr }} // save LR and R12 - can now use R12 (but leave LR alone for SVC code lookup) - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r6, r12 }} // push alignment amount, and stacked SVC argument registers (must be even number of regs for alignment) mov r12, sp // save SP for integer frame @@ -41,6 +40,7 @@ core::arch::global_asm!( pop {{ r12, lr }} // restore R12 and LR rfefd sp! // return from exception .size _asm_default_svc_handler, . - _asm_default_svc_handler + .popsection "#, svc_mode = const crate::ProcessorMode::Svc as u8, t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() }, diff --git a/aarch32-rt/src/arch_v7/undefined.rs b/aarch32-rt/src/arch_v7/undefined.rs index 03e1312..99d9952 100644 --- a/aarch32-rt/src/arch_v7/undefined.rs +++ b/aarch32-rt/src/arch_v7/undefined.rs @@ -11,7 +11,8 @@ core::arch::global_asm!( // `extern "C" fn _undefined_handler(addr: usize) -> usize;` // or // `extern "C" fn _undefined_handler(addr: usize) -> !;` - .section .text._asm_default_undefined_handler + .pushsection .text._asm_default_undefined_handler + .arm .global _asm_default_undefined_handler .type _asm_default_undefined_handler, %function _asm_default_undefined_handler: @@ -22,8 +23,7 @@ core::arch::global_asm!( ite eq // Adjust LR to point to faulting instruction - see p.1206 of the ARMv7-A architecture manual. subeq lr, lr, #4 // Subtract 4 in Arm Mode subne lr, lr, #2 // Subtract 2 in Thumb Mode - mov r12, sp // align SP down to eight byte boundary using R12 - and r12, r12, 7 // + and r12, sp, 7 // align SP down to eight byte boundary using R12 sub sp, r12 // SP now aligned - only push 64-bit values from here push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding) "#, @@ -41,6 +41,7 @@ core::arch::global_asm!( str lr, [sp] // overwrite the saved LR with the one from the C handler rfefd sp! // return from exception .size _asm_default_undefined_handler, . - _asm_default_undefined_handler + .popsection "#, und_mode = const crate::ProcessorMode::Und as u8, t_bit = const { crate::Cpsr::new_with_raw_value(0).with_t(true).raw_value() }, diff --git a/aarch32-rt/src/lib.rs b/aarch32-rt/src/lib.rs index 03d4929..4d48513 100644 --- a/aarch32-rt/src/lib.rs +++ b/aarch32-rt/src/lib.rs @@ -579,7 +579,7 @@ pub extern "C" fn _default_handler() { #[cfg(target_arch = "arm")] core::arch::global_asm!( r#" - .section .vector_table,"ax",%progbits + .pushsection .vector_table,"ax",%progbits .arm .global _vector_table .type _vector_table, %function @@ -594,6 +594,7 @@ core::arch::global_asm!( ldr pc, =_asm_irq_handler ldr pc, =_asm_fiq_handler .size _vector_table, . - _vector_table + .popsection "# ); @@ -746,7 +747,7 @@ macro_rules! restore_fpu_context { #[cfg(target_arch = "arm")] core::arch::global_asm!( r#" - .section .text._asm_default_fiq_handler + .pushsection .text._asm_default_fiq_handler // Our default FIQ handler .global _asm_default_fiq_handler @@ -754,6 +755,7 @@ core::arch::global_asm!( _asm_default_fiq_handler: b _asm_default_fiq_handler .size _asm_default_fiq_handler, . - _asm_default_fiq_handler + .popsection "#, ); @@ -798,7 +800,7 @@ core::arch::global_asm!( // Configure a stack for every mode. Leaves you in sys mode. // // Pass the core number in r0 - .section .text._stack_setup_preallocated + .pushsection .text._stack_setup_preallocated .global _stack_setup_preallocated .arm .type _stack_setup_preallocated, %function @@ -850,9 +852,10 @@ core::arch::global_asm!( // return to caller bx r3 .size _stack_setup_preallocated, . - _stack_setup_preallocated + .popsection // Initialises stacks, .data and .bss - .section .text._init_segments + .pushsection .text._init_segments .arm .global _init_segments .type _init_segments, %function @@ -891,6 +894,7 @@ core::arch::global_asm!( // return to caller bx lr .size _init_segments, . - _init_segments + .popsection "#, und_mode = const { Cpsr::new_with_raw_value(0) @@ -950,7 +954,7 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp2 - .section .text.default_start + .pushsection .text.default_start .arm .global _default_start .type _default_start, %function @@ -982,6 +986,7 @@ core::arch::global_asm!( // In case the application returns, loop forever b . .size _default_start, . - _default_start + .popsection "# ); @@ -997,7 +1002,7 @@ core::arch::global_asm!( // Work around https://github.com/rust-lang/rust/issues/127269 .fpu vfp2 - .section .text.default_start + .pushsection .text.default_start .arm .global _default_start .type _default_start, %function @@ -1057,6 +1062,7 @@ core::arch::global_asm!( // In case the application returns, loop forever b . .size _default_start, . - _default_start + .popsection "#, cpsr_mode_hyp = const ProcessorMode::Hyp as u8, hactlr_bits = const { diff --git a/examples/mps3-an536-smp/src/lib.rs b/examples/mps3-an536-smp/src/lib.rs index e3a798e..3fe7087 100644 --- a/examples/mps3-an536-smp/src/lib.rs +++ b/examples/mps3-an536-smp/src/lib.rs @@ -199,7 +199,7 @@ pub fn start_core1() { #[cfg(arm_architecture = "v8-r")] core::arch::global_asm!( r#" - .section .text.startup + .pushsection .text.startup .align 4 .arm @@ -274,6 +274,7 @@ core::arch::global_asm!( // call our kmain2 for core 1 bl kmain2 .size _start, . - _start + .popsection "#, hactlr_bits = const { Hactlr::new_with_raw_value(0) diff --git a/examples/mps3-an536/src/bin/el2_hello.rs b/examples/mps3-an536/src/bin/el2_hello.rs index 4c3d174..0de1b45 100644 --- a/examples/mps3-an536/src/bin/el2_hello.rs +++ b/examples/mps3-an536/src/bin/el2_hello.rs @@ -28,12 +28,12 @@ fn main() -> ! { panic!("I am an example panic"); } -// Provide a custom `_start` function that sets us up in EL2 mode, with a -// stack. -// -// Unlike the default routine, it does not initialise any other stacks, or -// switch to EL1 mode. -// +/// Provide a custom `_start` function that sets us up in EL2 mode, with a +/// stack. +/// +/// Unlike the default routine, it does not initialise any other stacks, or +/// switch to EL1 mode. +/// /// # Safety /// /// This function should not be called manually. It should only be called on reset