Skip to main content

sel4_reset/
lib.rs

1//
2// Copyright 2024, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7#![no_std]
8
9use core::arch::global_asm;
10use core::slice;
11
12use sel4_panicking_env::abort;
13use sel4_phdrs::{PT_SEL4_RESET_REGIONS, locate_phdrs};
14use sel4_stack::{Stack, StackBottom};
15
16use sel4_phdrs_patched as _;
17
18#[cfg(not(any(
19    target_arch = "aarch64",
20    target_arch = "arm",
21    target_arch = "riscv64",
22    target_arch = "riscv32",
23    target_arch = "x86_64",
24)))]
25compile_error!("unsupported architecture");
26
27// // //
28
29#[repr(C)]
30#[derive(Debug)]
31struct RegionMeta {
32    dst_vaddr: usize,
33    dst_size: usize,
34    src_vaddr: usize,
35    src_size: usize,
36}
37
38unsafe fn reset_memory(regions: &'static [RegionMeta]) {
39    for meta in regions {
40        let dst = unsafe { slice::from_raw_parts_mut(meta.dst_vaddr as *mut u8, meta.dst_size) };
41        let (dst_data, dst_zero) = dst.split_at_mut(meta.src_size);
42        if meta.src_vaddr != 0 {
43            let src =
44                unsafe { slice::from_raw_parts_mut(meta.src_vaddr as *mut u8, meta.src_size) };
45            dst_data.copy_from_slice(src);
46        }
47        dst_zero.fill(0);
48    }
49}
50
51unsafe fn get_regions() -> &'static [RegionMeta] {
52    unsafe {
53        let phdr = locate_phdrs()
54            .unwrap_or_else(|err| abort!("{err}"))
55            .find_by_type(PT_SEL4_RESET_REGIONS)
56            .unwrap_or_else(|| abort!("missing PT_SEL4_RESET_REGIONS program header"));
57        slice::from_raw_parts(
58            phdr.p_vaddr as *const _,
59            phdr.p_memsz / size_of::<RegionMeta>(),
60        )
61    }
62}
63
64// // //
65
66unsafe extern "C" {
67    fn _reset(x0: usize, x1: usize, x2: usize, x3: usize) -> !;
68    fn _start(x0: usize, x1: usize, x2: usize, x3: usize) -> !;
69}
70
71pub fn reset() -> ! {
72    unsafe {
73        _reset(0, 0, 0, 0);
74    }
75}
76
77pub fn reset1(x0: usize) -> ! {
78    unsafe {
79        _reset(x0, 0, 0, 0);
80    }
81}
82
83pub fn reset2(x0: usize, x1: usize) -> ! {
84    unsafe {
85        _reset(x0, x1, 0, 0);
86    }
87}
88
89pub fn reset3(x0: usize, x1: usize, x2: usize) -> ! {
90    unsafe {
91        _reset(x0, x1, x2, 0);
92    }
93}
94
95pub fn reset4(x0: usize, x1: usize, x2: usize, x3: usize) -> ! {
96    unsafe {
97        _reset(x0, x1, x2, x3);
98    }
99}
100
101#[unsafe(no_mangle)]
102unsafe extern "C" fn __sel4_reset__rust_entrypoint(
103    x0: usize,
104    x1: usize,
105    x2: usize,
106    x3: usize,
107) -> ! {
108    unsafe {
109        reset_memory(get_regions());
110        _start(x0, x1, x2, x3)
111    }
112}
113
114const STACK_SIZE: usize = 4096;
115
116#[unsafe(link_section = ".persistent")]
117static STACK: Stack<STACK_SIZE> = Stack::new();
118
119#[unsafe(no_mangle)]
120static __sel4_reset__stack_bottom: StackBottom = STACK.bottom();
121
122global_asm! {
123    r#"
124        .extern __sel4_reset__stack_bottom
125        .extern __sel4_reset__rust_entrypoint
126
127        .global _reset
128
129        .section .text.reset, "axR", %progbits
130        _reset:
131    "#,
132    #[cfg(target_arch = "aarch64")]
133    r#"
134            ldr x9, =__sel4_reset__stack_bottom
135            ldr x9, [x9]
136            mov sp, x9
137            b __sel4_reset__rust_entrypoint
138    "#,
139    #[cfg(target_arch = "arm")]
140    r#"
141            ldr r8, =__sel4_reset__stack_bottom
142            ldr r8, [r8]
143            mov sp, r8
144            b __sel4_reset__rust_entrypoint
145    "#,
146    #[cfg(target_arch = "riscv64")]
147    r#"
148            la sp, __sel4_reset__stack_bottom
149            ld sp, (sp)
150            j __sel4_reset__rust_entrypoint
151    "#,
152    #[cfg(target_arch = "riscv32")]
153    r#"
154            la sp, __sel4_reset__stack_bottom
155            lw sp, (sp)
156            j __sel4_reset__rust_entrypoint
157    "#,
158    #[cfg(target_arch = "x86_64")]
159    r#"
160            mov rsp, __sel4_reset__stack_bottom
161            mov rbp, rsp
162            sub rsp, 0x8 // Stack must be 16-byte aligned before call
163            push rbp
164            jmp __sel4_reset__rust_entrypoint
165    "#,
166}