sel4_runtime_common/
start.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7// TODO
8// - guard pages for stack?
9
10use core::arch::global_asm;
11
12#[macro_export]
13macro_rules! declare_stack {
14    ($size:expr) => {
15        #[allow(non_upper_case_globals)]
16        #[no_mangle]
17        static __sel4_runtime_common__stack_bottom: $crate::_private::start::StackBottom = {
18            static STACK: $crate::_private::start::Stack<{ $size }> =
19                $crate::_private::start::Stack::new();
20            STACK.bottom()
21        };
22    };
23}
24
25#[macro_export]
26macro_rules! declare_entrypoint {
27    (($( $i:ident: $t:ty ),* $(,)?) -> ! $body:block) => {
28        #[allow(unreachable_code)]
29        #[no_mangle]
30        unsafe extern "C" fn __sel4_runtime_common__rust_entrypoint($($i: $t,)*) -> ! {
31            $crate::_private::start::with_local_initialization(|| {
32                $crate::_private::start::global_initialzation();
33                $body
34            });
35            $crate::_private::start::abort!("entrypoint returned")
36        }
37    };
38}
39
40macro_rules! common_asm_prefix {
41    () => {
42        r#"
43            .extern __sel4_runtime_common__rust_entrypoint
44            .extern __sel4_runtime_common__stack_bottom
45
46            .global _start
47
48            .section .text
49
50            _start:
51        "#
52    };
53}
54
55cfg_if::cfg_if! {
56    if #[cfg(target_arch = "aarch64")] {
57        global_asm! {
58            common_asm_prefix!(),
59            r#"
60                    ldr x9, =__sel4_runtime_common__stack_bottom
61                    ldr x9, [x9]
62                    mov sp, x9
63                    b __sel4_runtime_common__rust_entrypoint
64
65                1:  b 1b
66            "#
67        }
68    } else if #[cfg(target_arch = "arm")] {
69        global_asm! {
70            common_asm_prefix!(),
71            r#"
72                    ldr r8, =__sel4_runtime_common__stack_bottom
73                    ldr r8, [r8]
74                    mov sp, r8
75                    b __sel4_runtime_common__rust_entrypoint
76
77                1:  b 1b
78            "#
79        }
80    } else if #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] {
81        macro_rules! riscv_common_asm_body {
82            () => {
83                r#"
84                        # See https://www.sifive.com/blog/all-aboard-part-3-linker-relaxation-in-riscv-toolchain
85                    .option push
86                    .option norelax
87                    1:  auipc gp, %pcrel_hi(__global_pointer$)
88                        addi gp, gp, %pcrel_lo(1b)
89                    .option pop
90
91                        la sp, __sel4_runtime_common__stack_bottom
92                        __sel4_runtime_common__lx sp, (sp)
93                        jal __sel4_runtime_common__rust_entrypoint
94
95                    1:  j 1b
96                "#
97            }
98        }
99
100        #[cfg(target_arch = "riscv64")]
101        global_asm! {
102            r#"
103                .macro __sel4_runtime_common__lx dst, src
104                    ld \dst, \src
105                .endm
106            "#,
107            common_asm_prefix!(),
108            riscv_common_asm_body!()
109        }
110
111        #[cfg(target_arch = "riscv32")]
112        global_asm! {
113            r#"
114                .macro __sel4_runtime_common__lx dst, src
115                    lw \dst, \src
116                .endm
117            "#,
118            common_asm_prefix!(),
119            riscv_common_asm_body!()
120        }
121    } else if #[cfg(target_arch = "x86_64")] {
122        global_asm! {
123            common_asm_prefix!(),
124            r#"
125                    mov rsp, __sel4_runtime_common__stack_bottom
126                    mov rbp, rsp
127                    sub rsp, 0x8 // Stack must be 16-byte aligned before call
128                    push rbp
129                    call __sel4_runtime_common__rust_entrypoint
130
131                1:  jmp 1b
132            "#
133        }
134    } else {
135        compile_error!("unsupported architecture");
136    }
137}
138
139pub mod _private {
140    pub use sel4_panicking_env::abort;
141    pub use sel4_stack::{Stack, StackBottom};
142
143    pub use crate::{global_initialzation, with_local_initialization};
144}