Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ jobs:
- test-qemu-v7r
- test-qemu-v7a
- test-qemu-v8r
- test-qemu-v8r-smp
- test-qemu-v8r-el2
steps:
- name: Checkout
Expand Down
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
target
examples/mps3-an536/target
examples/mps3-an536/target-d32
examples/mps3-an536-smp/target
examples/mps3-an536-smp/target-d32
examples/mps3-an536-el2/target
examples/mps3-an536-el2/target-d32
examples/versatileab/target
Expand Down
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"./arm-targets/Cargo.toml",
"examples/versatileab/Cargo.toml",
"examples/mps3-an536/Cargo.toml",
"examples/mps3-an536-smp/Cargo.toml",
"examples/mps3-an536-el2/Cargo.toml"
"examples/mps3-an536-el2/Cargo.toml",
]
}
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ exclude = [
"arm-targets",
"examples/versatileab",
"examples/mps3-an536",
"examples/mps3-an536-smp",
"examples/mps3-an536-el2",
"examples/c-code",
"examples/xilinx-zynq-a9",
Expand Down
6 changes: 4 additions & 2 deletions aarch32-rt/link.x
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,9 @@ PROVIDE(_sys_stack_size = 16K);
/* Default to one CPU core (i.e. one copy of each stack) */
PROVIDE(_num_cores = 1);

/* Our default main function for any non-primary cores */
PROVIDE(kmain_secondary = _default_kmain_secondary);

/* Default stack alignment. You can over-align if you want to set up MPU regions for the stacks */
PROVIDE(_stack_alignment = 8);

Expand All @@ -274,17 +277,16 @@ PROVIDE(_asm_svc_handler = _asm_default_svc_handler);
PROVIDE(_asm_hvc_handler = _asm_default_hvc_handler);
PROVIDE(_asm_prefetch_abort_handler = _asm_default_prefetch_abort_handler);
PROVIDE(_asm_data_abort_handler = _asm_default_data_abort_handler);
/* TODO: Hyp handler goes here */
PROVIDE(_asm_irq_handler = _asm_default_irq_handler);
PROVIDE(_asm_fiq_handler = _asm_default_fiq_handler);
PROVIDE(_asm_secondary_core_park = _asm_default_secondary_core_park);

/* Weak aliases for C default handlers */
PROVIDE(_undefined_handler = _default_handler);
PROVIDE(_svc_handler = _default_handler);
PROVIDE(_hvc_handler = _default_handler);
PROVIDE(_prefetch_abort_handler = _default_handler);
PROVIDE(_data_abort_handler = _default_handler);
/* TODO: Hyp handler goes here */
PROVIDE(_irq_handler = _default_handler);
/* NB: There is no default C-language FIQ handler */

Expand Down
24 changes: 16 additions & 8 deletions aarch32-rt/src/arch_v4/abort.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
//! Data and Prefetch Abort handlers for Armv4 to Armv6

// # _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);`
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
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 _data_abort_handler(addr: usize);`
.pushsection .text._asm_default_data_abort_handler
.arm
.global _asm_default_data_abort_handler
Expand Down Expand Up @@ -40,14 +44,18 @@ core::arch::global_asm!(
"#
);

// # _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);`
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
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 a prefetch abort.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _prefetch_abort_handler(addr: usize);`
.pushsection .text._asm_default_prefetch_abort_handler
.arm
.global _asm_default_prefetch_abort_handler
Expand Down
49 changes: 13 additions & 36 deletions aarch32-rt/src/arch_v4/boot.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,27 @@
//! Start-up code for CPUs that always boot into EL1
//! Start-up code for ARMv4 - ARMv6 CPUs that always boot into EL1

// # _default_start
//
// Reset function for ARMv4 to ARMv6
//
// Initialises global memory and sets up stacks. Only supports one CPU core.
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
core::arch::global_asm!(
r#"
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp2

.pushsection .text.default_start
.arm
.global _default_start
.type _default_start, %function
_default_start:
// Init .data and .bss
bl _init_segments
// Set up stacks.
// Init .data and .bss on primary core
bl _asm_init_segments
// Do standard core init - only one core supported
mov r0, #0
bl _stack_setup_preallocated
"#,
#[cfg(any(target_abi = "eabihf", feature = "eabi-fpu"))]
r#"
// Allow VFP coprocessor access
mrc p15, 0, r0, c1, c0, 2
orr r0, r0, #0xF00000
mcr p15, 0, r0, c1, c0, 2
// Enable VFP
mov r0, #0x40000000
vmsr fpexc, r0
"#,
r#"
// Zero all registers before calling kmain
mov r0, 0
mov r1, 0
mov r2, 0
mov r3, 0
mov r4, 0
mov r5, 0
mov r6, 0
mov r7, 0
mov r8, 0
mov r9, 0
mov r10, 0
mov r11, 0
mov r12, 0
// Jump to application
bl kmain
// In case the application returns, loop forever
b .
b _asm_core_start
.size _default_start, . - _default_start
.popsection
"#
Expand Down
5 changes: 3 additions & 2 deletions aarch32-rt/src/arch_v4/hvc.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! Dummy hypervisor handler for architectures without HYP mode

// # _asm_default_hvc_handler
//
// Never called but makes the linker happy
#[cfg(target_arch = "arm")]
core::arch::global_asm!(
r#"
// Work around https://github.com/rust-lang/rust/issues/127269
.fpu vfp2

// Never called but makes the linker happy
.pushsection .text._asm_default_hvc_handler
.arm
.global _asm_default_hvc_handler
Expand Down
40 changes: 22 additions & 18 deletions aarch32-rt/src/arch_v4/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,33 @@

use crate::{Cpsr, ProcessorMode};

// # _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();` in
// system mode (or SVC mode if the `svc-stack-interrupt` feature is
// enabled).
//
// We call the C-compatible handler in a different mode because when when an
// IRQ occurs, the PC is copied to LR_irq immediately. If the C code was
// running in IRQ mode, then it will be using LR_irq for normal LR things
// (because that's the LR register when you are in IRQ mode). Instantly
// trashing the LR register of running code is bad. So, by switching to SYS
// mode (or SVC mode) we ensure that LR_irq is always unused at the point an
// IRQ occurs.
//
// See [ARM Cortex-R Series (Armv7-R) Programmer's Guide] for more details.
//
// [ARM Cortex-R Series (Armv7-R) Programmer's Guide]:
// https://developer.arm.com/documentation/den0042/0100/Exceptions-and-Interrupts/External-interrupt-requests/Nested-interrupt-handling
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
#[cfg(target_arch = "arm")]
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 interrupt. Saves state and
// calls a C-compatible handler like `extern "C" fn _irq_handler();` in
// system mode (or SVC mode if the `svc-stack-interrupt` feature is
// enabled).
//
// We call the C-compatible handler in a different mode because when when an
// IRQ occurs, the PC is copied to LR_irq immediately. If the C code was
// running in IRQ mode, then it will be using LR_irq for normal LR things
// (because that's the LR register when you are in IRQ mode). Instantly
// trashing the LR register of running code is bad. So, by switching to SYS
// mode (or SVC mode) we ensure that LR_irq is always unused at the point an
// IRQ occurs.
//
// See [ARM Cortex-R Series (Armv7-R) Programmer's Guide] for more details.
//
// [ARM Cortex-R Series (Armv7-R) Programmer's Guide]:
// https://developer.arm.com/documentation/den0042/0100/Exceptions-and-Interrupts/External-interrupt-requests/Nested-interrupt-handling
.pushsection .text._asm_default_irq_handler
.arm
.global _asm_default_irq_handler
Expand Down
12 changes: 8 additions & 4 deletions aarch32-rt/src/arch_v4/svc.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//! SVC handler for Armv4 to Armv6

// # _asm_default_svc_handler
//
// 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;`
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
#[cfg(target_arch = "arm")]
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 software interrupt.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _svc_handler(arg: u32, frame: &Frame) -> u32;`
.pushsection .text._asm_default_svc_handler
.arm
.global _asm_default_svc_handler
Expand Down
16 changes: 10 additions & 6 deletions aarch32-rt/src/arch_v4/undefined.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
//! Undefined handler for Armv4 to Armv6

// # _asm_default_undefined_handler
//
// 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) -> !;`
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
#[cfg(target_arch = "arm")]
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) -> !;`
.pushsection .text._asm_default_undefined_handler
.arm
.global _asm_default_undefined_handler
Expand Down
24 changes: 16 additions & 8 deletions aarch32-rt/src/arch_v7/abort.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
//! Data and Prefetch Abort handlers for Armv7 and higher

// # _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);`
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
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 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
Expand Down Expand Up @@ -39,14 +43,18 @@ core::arch::global_asm!(
abt_mode = const crate::ProcessorMode::Abt as u8,
);

// # _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);`
//
// This function must produce A32 machine code, because it's called by the Vector Table
// with a raw PC load and the Vector Table is always in A32 machine code.
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 a prefetch abort.
// Saves state and calls a C-compatible handler like
// `extern "C" fn _prefetch_abort_handler(addr: usize);`
.pushsection .text._asm_default_prefetch_abort_handler
.arm
.global _asm_default_prefetch_abort_handler
Expand Down
Loading