Skip to content

Commit 2aa512a

Browse files
authored
Merge pull request #2596 from hermit-os/arch-start
refactor(arch): extract hermit-entry-specific start code
2 parents 08d51ed + d752a02 commit 2aa512a

14 files changed

Lines changed: 181 additions & 182 deletions

File tree

src/arch/aarch64/kernel/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ pub mod pci;
1010
pub mod processor;
1111
pub mod scheduler;
1212
pub mod serial;
13-
#[cfg(target_os = "none")]
14-
mod start;
1513
pub mod systemtime;
1614

1715
use alloc::alloc::alloc;
@@ -112,7 +110,7 @@ pub fn boot_next_processor() {
112110

113111
use memory_addresses::VirtAddr;
114112

115-
use crate::arch::aarch64::kernel::start::{TTBR0, smp_start};
113+
use crate::arch::aarch64::start::smp::{TTBR0, smp_start};
116114
use crate::mm::virtual_to_physical;
117115

118116
if cpu_online == 0 {

src/arch/aarch64/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
pub mod kernel;
22
pub mod mm;
3+
#[cfg(target_os = "none")]
4+
pub mod start;
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use core::arch::{asm, naked_asm};
2+
3+
use aarch64_cpu::asm::barrier::{SY, dsb};
4+
use hermit_entry::Entry;
5+
use hermit_entry::boot_info::RawBootInfo;
6+
7+
use crate::config::KERNEL_STACK_SIZE;
8+
use crate::env;
9+
use crate::kernel::scheduler::TaskStacks;
10+
use crate::kernel::{CPU_ONLINE, CURRENT_STACK_ADDRESS};
11+
12+
/// Entrypoint - Initialize Stack pointer and Exception Table
13+
#[unsafe(no_mangle)]
14+
#[unsafe(naked)]
15+
pub unsafe extern "C" fn _start(boot_info: Option<&'static RawBootInfo>, cpu_id: u32) -> ! {
16+
// validate signatures
17+
// `_Start` is compatible to `Entry`
18+
{
19+
unsafe extern "C" fn _entry(_boot_info: &'static RawBootInfo, _cpu_id: u32) -> ! {
20+
unreachable!()
21+
}
22+
pub type _Start =
23+
unsafe extern "C" fn(boot_info: Option<&'static RawBootInfo>, cpu_id: u32) -> !;
24+
const _ENTRY: Entry = _entry;
25+
const _START: _Start = _start;
26+
const _PRE_INIT: _Start = pre_init;
27+
}
28+
29+
naked_asm!(
30+
// use core::sync::atomic::{AtomicU32, Ordering};
31+
//
32+
// pub static CPU_ONLINE: AtomicU32 = AtomicU32::new(0);
33+
//
34+
// while CPU_ONLINE.load(Ordering::Acquire) != this {
35+
// core::hint::spin_loop();
36+
// }
37+
"mrs x4, mpidr_el1",
38+
"and x4, x4, #0xff",
39+
"1:",
40+
"adrp x8, {cpu_online}",
41+
"ldr x5, [x8, #:lo12:{cpu_online}]",
42+
"cmp x4, x5",
43+
"b.eq 2f",
44+
"b 1b",
45+
"2:",
46+
47+
// we want to use sp_el1
48+
"msr spsel, #1",
49+
50+
// Overwrite RSP if `CURRENT_STACK_ADDRESS != 0`
51+
"adrp x8, {current_stack_address}",
52+
"ldr x4, [x8, #:lo12:{current_stack_address}]",
53+
"cmp x4, 0",
54+
"b.eq 3f",
55+
"mov sp, x4",
56+
"b 4f",
57+
"3:",
58+
"mov x4, sp",
59+
"4:",
60+
"str x4, [x8, #:lo12:{current_stack_address}]",
61+
62+
// Add stack top offset
63+
"mov x8, {stack_top_offset}",
64+
"add sp, sp, x8",
65+
66+
// Jump to Rust code
67+
"b {pre_init}",
68+
69+
cpu_online = sym CPU_ONLINE,
70+
stack_top_offset = const KERNEL_STACK_SIZE - TaskStacks::MARKER_SIZE,
71+
current_stack_address = sym CURRENT_STACK_ADDRESS,
72+
pre_init = sym pre_init,
73+
)
74+
}
75+
76+
#[inline(never)]
77+
#[unsafe(no_mangle)]
78+
pub unsafe extern "C" fn pre_init(boot_info: Option<&'static RawBootInfo>, cpu_id: u32) -> ! {
79+
// set exception table
80+
unsafe {
81+
asm!(
82+
"adrp x4, vector_table",
83+
"add x4, x4, #:lo12:vector_table",
84+
"msr vbar_el1, x4",
85+
out("x4") _,
86+
options(nostack),
87+
);
88+
}
89+
90+
// Memory barrier
91+
dsb(SY);
92+
93+
if cpu_id == 0 {
94+
env::set_boot_info(*boot_info.unwrap());
95+
crate::boot_processor_main()
96+
} else {
97+
#[cfg(not(feature = "smp"))]
98+
{
99+
let style = anstyle::Style::new().fg_color(Some(anstyle::AnsiColor::Red.into()));
100+
let preamble = format_args!("[ ][{cpu_id}][{style}ERROR{style:#}]");
101+
println!(
102+
"{preamble} Secondary core booted, but Hermit was not built with SMP support!"
103+
);
104+
loop {
105+
crate::arch::kernel::processor::halt();
106+
}
107+
}
108+
#[cfg(feature = "smp")]
109+
crate::application_processor_main()
110+
}
111+
}

src/arch/aarch64/start/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod hermit_entry;
2+
#[cfg(feature = "smp")]
3+
pub mod smp;
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
1-
#![allow(dead_code)]
2-
3-
use core::arch::{asm, naked_asm};
4-
#[cfg(feature = "smp")]
51
use core::ptr;
6-
#[cfg(feature = "smp")]
72
use core::sync::atomic::AtomicPtr;
83

9-
use aarch64_cpu::asm::barrier::{SY, dsb};
10-
use hermit_entry::Entry;
11-
use hermit_entry::boot_info::RawBootInfo;
12-
13-
use crate::arch::aarch64::kernel::scheduler::TaskStacks;
14-
use crate::config::KERNEL_STACK_SIZE;
15-
use crate::env;
4+
use crate::kernel::CURRENT_STACK_ADDRESS;
165

176
/*
187
* Memory types available.
@@ -31,100 +20,35 @@ const MT_NORMAL: u64 = 4;
3120
const TCR_IRGN_WBWA: u64 = ((1) << 8) | ((1) << 24);
3221
const TCR_ORGN_WBWA: u64 = ((1) << 10) | ((1) << 26);
3322
const TCR_SHARED: u64 = ((3) << 12) | ((3) << 28);
23+
#[expect(dead_code)]
3424
const TCR_TBI0: u64 = 1 << 37;
25+
#[expect(dead_code)]
3526
const TCR_TBI1: u64 = 1 << 38;
27+
#[expect(dead_code)]
3628
const TCR_ASID16: u64 = 1 << 36;
29+
#[expect(dead_code)]
3730
const TCR_TG1_16K: u64 = 1 << 30;
3831
const TCR_TG1_4K: u64 = 0 << 30;
3932
const TCR_FLAGS: u64 = TCR_IRGN_WBWA | TCR_ORGN_WBWA | TCR_SHARED;
4033

4134
/// Number of virtual address bits for 4KB page
4235
const VA_BITS: u64 = 48;
4336

44-
unsafe extern "C" {
45-
static vector_table: u8;
46-
}
47-
48-
/// Entrypoint - Initialize Stack pointer and Exception Table
49-
#[unsafe(no_mangle)]
50-
#[unsafe(naked)]
51-
pub unsafe extern "C" fn _start(boot_info: Option<&'static RawBootInfo>, cpu_id: u32) -> ! {
52-
// validate signatures
53-
// `_Start` is compatible to `Entry`
54-
{
55-
unsafe extern "C" fn _entry(_boot_info: &'static RawBootInfo, _cpu_id: u32) -> ! {
56-
unreachable!()
57-
}
58-
pub type _Start =
59-
unsafe extern "C" fn(boot_info: Option<&'static RawBootInfo>, cpu_id: u32) -> !;
60-
const _ENTRY: Entry = _entry;
61-
const _START: _Start = _start;
62-
const _PRE_INIT: _Start = pre_init;
63-
}
64-
65-
naked_asm!(
66-
// use core::sync::atomic::{AtomicU32, Ordering};
67-
//
68-
// pub static CPU_ONLINE: AtomicU32 = AtomicU32::new(0);
69-
//
70-
// while CPU_ONLINE.load(Ordering::Acquire) != this {
71-
// core::hint::spin_loop();
72-
// }
73-
"mrs x4, mpidr_el1",
74-
"and x4, x4, #0xff",
75-
"1:",
76-
"adrp x8, {cpu_online}",
77-
"ldr x5, [x8, #:lo12:{cpu_online}]",
78-
"cmp x4, x5",
79-
"b.eq 2f",
80-
"b 1b",
81-
"2:",
82-
83-
// we want to use sp_el1
84-
"msr spsel, #1",
85-
86-
// Overwrite RSP if `CURRENT_STACK_ADDRESS != 0`
87-
"adrp x8, {current_stack_address}",
88-
"ldr x4, [x8, #:lo12:{current_stack_address}]",
89-
"cmp x4, 0",
90-
"b.eq 3f",
91-
"mov sp, x4",
92-
"b 4f",
93-
"3:",
94-
"mov x4, sp",
95-
"4:",
96-
"str x4, [x8, #:lo12:{current_stack_address}]",
97-
98-
// Add stack top offset
99-
"mov x8, {stack_top_offset}",
100-
"add sp, sp, x8",
101-
102-
// Jump to Rust code
103-
"b {pre_init}",
104-
105-
cpu_online = sym super::CPU_ONLINE,
106-
stack_top_offset = const KERNEL_STACK_SIZE - TaskStacks::MARKER_SIZE,
107-
current_stack_address = sym super::CURRENT_STACK_ADDRESS,
108-
pre_init = sym pre_init,
109-
)
110-
}
111-
112-
#[cfg(feature = "smp")]
11337
const fn tcr_size(x: u64) -> u64 {
11438
((64 - x) << 16) | (64 - x)
11539
}
11640

117-
#[cfg(feature = "smp")]
11841
const fn mair(attr: u64, mt: u64) -> u64 {
11942
attr << (mt * 8)
12043
}
12144

122-
#[cfg(feature = "smp")]
12345
pub(crate) static TTBR0: AtomicPtr<u8> = AtomicPtr::new(ptr::null_mut());
12446

125-
#[cfg(feature = "smp")]
12647
#[unsafe(naked)]
12748
pub(crate) unsafe extern "C" fn smp_start() -> ! {
49+
use crate::config::KERNEL_STACK_SIZE;
50+
use crate::kernel::scheduler::TaskStacks;
51+
12852
// Prepare system control register (SCTRL)
12953
//
13054
// UCI [26] Enables EL0 access in AArch64 for DC CVAU, DC CIVAC,
@@ -154,7 +78,7 @@ pub(crate) unsafe extern "C" fn smp_start() -> ! {
15478
#[cfg(target_endian = "big")]
15579
const SCTLR_EL1: u64 = 0b111_0000_0101_1101_0000_0001_1101;
15680

157-
naked_asm!(
81+
core::arch::naked_asm!(
15882
// disable interrupts
15983
"msr daifset, #0b111",
16084

@@ -241,47 +165,9 @@ pub(crate) unsafe extern "C" fn smp_start() -> ! {
241165
mair_el1 = const mair(0x00, MT_DEVICE_nGnRnE) | mair(0x04, MT_DEVICE_nGnRE) | mair(0x0c, MT_DEVICE_GRE) | mair(0x44, MT_NORMAL_NC) | mair(0xff, MT_NORMAL),
242166
tcr_bits = const tcr_size(VA_BITS) | TCR_TG1_4K | TCR_FLAGS,
243167
stack_top_offset = const KERNEL_STACK_SIZE - TaskStacks::MARKER_SIZE,
244-
current_stack_address = sym super::CURRENT_STACK_ADDRESS,
168+
current_stack_address = sym CURRENT_STACK_ADDRESS,
245169
sctlr_el1 = const SCTLR_EL1,
246170
ttbr0 = sym TTBR0,
247-
pre_init = sym pre_init,
171+
pre_init = sym crate::arch::start::hermit_entry::pre_init,
248172
)
249173
}
250-
251-
#[inline(never)]
252-
#[unsafe(no_mangle)]
253-
unsafe extern "C" fn pre_init(boot_info: Option<&'static RawBootInfo>, cpu_id: u32) -> ! {
254-
// set exception table
255-
unsafe {
256-
asm!(
257-
"adrp x4, {vector_table}",
258-
"add x4, x4, #:lo12:{vector_table}",
259-
"msr vbar_el1, x4",
260-
vector_table = sym vector_table,
261-
out("x4") _,
262-
options(nostack),
263-
);
264-
}
265-
266-
// Memory barrier
267-
dsb(SY);
268-
269-
if cpu_id == 0 {
270-
env::set_boot_info(*boot_info.unwrap());
271-
crate::boot_processor_main()
272-
} else {
273-
#[cfg(not(feature = "smp"))]
274-
{
275-
let style = anstyle::Style::new().fg_color(Some(anstyle::AnsiColor::Red.into()));
276-
let preamble = format_args!("[ ][{cpu_id}][{style}ERROR{style:#}]");
277-
println!(
278-
"{preamble} Secondary core booted, but Hermit was not built with SMP support!"
279-
);
280-
loop {
281-
crate::arch::kernel::processor::halt();
282-
}
283-
}
284-
#[cfg(feature = "smp")]
285-
crate::application_processor_main()
286-
}
287-
}

src/arch/riscv64/kernel/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pub mod pci;
88
pub mod processor;
99
pub mod scheduler;
1010
pub mod serial;
11-
mod start;
1211
pub mod switch;
1312
pub mod systemtime;
1413
use alloc::vec::Vec;
@@ -32,11 +31,11 @@ use crate::mm::{FrameAlloc, PageRangeAllocator};
3231
pub(crate) static HARTS_AVAILABLE: InitCell<Vec<usize>> = InitCell::new(Vec::new());
3332

3433
/// Kernel header to announce machine features
35-
static CPU_ONLINE: AtomicU32 = AtomicU32::new(0);
36-
static CURRENT_BOOT_ID: AtomicU32 = AtomicU32::new(0);
37-
static CURRENT_STACK_ADDRESS: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
38-
static HART_MASK: AtomicU64 = AtomicU64::new(0);
39-
static NUM_CPUS: AtomicU32 = AtomicU32::new(0);
34+
pub(crate) static CPU_ONLINE: AtomicU32 = AtomicU32::new(0);
35+
pub(crate) static CURRENT_BOOT_ID: AtomicU32 = AtomicU32::new(0);
36+
pub(crate) static CURRENT_STACK_ADDRESS: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
37+
pub(crate) static HART_MASK: AtomicU64 = AtomicU64::new(0);
38+
pub(crate) static NUM_CPUS: AtomicU32 = AtomicU32::new(0);
4039

4140
// FUNCTIONS
4241

@@ -155,7 +154,7 @@ pub fn boot_next_processor() {
155154
}
156155

157156
//When running bare-metal/QEMU we use the firmware to start the next hart
158-
let start_addr = (start::_start as *const ()).expose_provenance();
157+
let start_addr = (crate::arch::start::hermit_entry::_start as *const ()).expose_provenance();
159158
sbi_rt::hart_start(next_hart_id as usize, start_addr, 0).unwrap();
160159
}
161160

src/arch/riscv64/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod kernel;
22
pub mod mm;
3+
pub mod start;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use core::sync::atomic::Ordering;
44
use hermit_entry::Entry;
55
use hermit_entry::boot_info::RawBootInfo;
66

7-
use super::{CPU_ONLINE, CURRENT_BOOT_ID, HART_MASK, NUM_CPUS};
87
use crate::arch::riscv64::kernel::CURRENT_STACK_ADDRESS;
98
#[cfg(not(feature = "smp"))]
109
use crate::arch::riscv64::kernel::processor;
1110
use crate::config::KERNEL_STACK_SIZE;
1211
use crate::env;
12+
use crate::kernel::{CPU_ONLINE, CURRENT_BOOT_ID, HART_MASK, NUM_CPUS};
1313

1414
//static mut BOOT_STACK: [u8; KERNEL_STACK_SIZE] = [0; KERNEL_STACK_SIZE];
1515

src/arch/riscv64/start/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod hermit_entry;

0 commit comments

Comments
 (0)