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
26 changes: 23 additions & 3 deletions src/arch/aarch64/start/smp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use core::ptr;
use core::sync::atomic::AtomicPtr;

use aarch64_cpu::asm::barrier::{SY, dsb};

use crate::kernel::CURRENT_STACK_ADDRESS;

/*
Expand Down Expand Up @@ -154,20 +156,38 @@ pub(crate) unsafe extern "C" fn smp_start() -> ! {
"ldr x0, ={sctlr_el1}",
"msr sctlr_el1, x0",

// initialize argument for pre_init
// initialize argument for `smp_start_rust()`
"mov x0, xzr",
"mrs x1, mpidr_el1",
"and x1, x1, #0xff",

// Jump to Rust code
"b {pre_init}",
"b {smp_start_rust}",

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),
tcr_bits = const tcr_size(VA_BITS) | TCR_TG1_4K | TCR_FLAGS,
stack_top_offset = const KERNEL_STACK_SIZE - TaskStacks::MARKER_SIZE,
current_stack_address = sym CURRENT_STACK_ADDRESS,
sctlr_el1 = const SCTLR_EL1,
ttbr0 = sym TTBR0,
pre_init = sym crate::arch::start::hermit_entry::pre_init,
smp_start_rust = sym smp_start_rust,
)
}

unsafe extern "C" fn smp_start_rust() -> ! {
// set exception table
unsafe {
core::arch::asm!(
"adrp x4, vector_table",
"add x4, x4, #:lo12:vector_table",
"msr vbar_el1, x4",
out("x4") _,
options(nostack),
);
}

// Memory barrier
dsb(SY);

crate::application_processor_main()
}
10 changes: 7 additions & 3 deletions src/arch/riscv64/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,18 @@ pub fn boot_next_processor() {
// TODO: Old: Changing cpu_online will cause uhyve to start the next processor
CPU_ONLINE.fetch_add(1, Ordering::Release);

#[allow(clippy::needless_return)]
#[cfg(feature = "uhyve")]
if env::is_uhyve() {
return;
}

//When running bare-metal/QEMU we use the firmware to start the next hart
let start_addr = (crate::arch::start::hermit_entry::_start as *const ()).expose_provenance();
sbi_rt::hart_start(next_hart_id as usize, start_addr, 0).unwrap();
#[cfg(feature = "smp")]
{
//When running bare-metal/QEMU we use the firmware to start the next hart
let start_addr = (crate::arch::start::smp::smp_start as *const ()).expose_provenance();
sbi_rt::hart_start(next_hart_id as usize, start_addr, 0).unwrap();
}
}

pub fn print_statistics() {
Expand Down
2 changes: 2 additions & 0 deletions src/arch/riscv64/start/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub mod hermit_entry;
#[cfg(feature = "smp")]
pub mod smp;
30 changes: 30 additions & 0 deletions src/arch/riscv64/start/smp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use core::arch::naked_asm;
use core::sync::atomic::Ordering;

use crate::arch::riscv64::kernel::CURRENT_STACK_ADDRESS;
use crate::config::KERNEL_STACK_SIZE;
use crate::kernel::CURRENT_BOOT_ID;

#[unsafe(naked)]
pub unsafe extern "C" fn smp_start(hart_id: usize) -> ! {
naked_asm!(
// Use stack pointer from `CURRENT_STACK_ADDRESS` if set
"ld t0, {current_stack_pointer}",
"beqz t0, 2f",
"li t1, {top_offset}",
"add t0, t0, t1",
"mv sp, t0",
"2:",

"j {smp_start_rust}",
current_stack_pointer = sym CURRENT_STACK_ADDRESS,
top_offset = const KERNEL_STACK_SIZE,
smp_start_rust = sym smp_start_rust,
)
}

unsafe extern "C" fn smp_start_rust(hart_id: usize) -> ! {
CURRENT_BOOT_ID.store(hart_id as u32, Ordering::Relaxed);

crate::application_processor_main();
}
11 changes: 6 additions & 5 deletions src/arch/x86_64/kernel/apic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ pub fn init_x2apic() {
}
}

/// Initialize the required _start variables for the next CPU to be booted.
/// Initialize the required `smp::start` variables for the next CPU to be booted.
#[cfg(feature = "smp")]
pub fn init_next_processor_variables() {
use alloc::alloc::alloc;
Expand All @@ -751,9 +751,10 @@ pub fn init_next_processor_variables() {
/// This is partly confirmed by <https://wiki.osdev.org/Symmetric_Multiprocessing>
#[cfg(all(target_os = "none", feature = "smp"))]
pub fn boot_application_processors() {
use hermit_entry::boot_info::RawBootInfo;
use x86_64::structures::paging::Translate;

use crate::arch::start::smp;

let smp_boot_code = include_bytes!(concat!(core::env!("OUT_DIR"), "/boot.bin"));

// We shouldn't have any problems fitting the boot code into a single page, but let's better be sure.
Expand Down Expand Up @@ -797,11 +798,11 @@ pub fn boot_application_processors() {
// Set entry point
debug!(
"Set entry point for application processor to {:p}",
arch::start::hermit_entry::_start as *const ()
smp::smp_start as *const ()
);
(SMP_BOOT_CODE_ADDRESS + SMP_BOOT_CODE_OFFSET_ENTRY)
.as_mut_ptr::<unsafe extern "C" fn(Option<&'static RawBootInfo>, cpu_id: u32) -> !>()
.write_unaligned(arch::start::hermit_entry::_start);
.as_mut_ptr::<unsafe extern "C" fn() -> !>()
.write_unaligned(smp::smp_start);
}

// Now wake up each application processor.
Expand Down
2 changes: 2 additions & 0 deletions src/arch/x86_64/start/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
pub mod hermit_entry;
#[cfg(feature = "smp")]
pub mod smp;
33 changes: 33 additions & 0 deletions src/arch/x86_64/start/smp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use x86_64::registers::control::{Cr0, Cr0Flags};

use crate::arch::kernel::scheduler::TaskStacks;
use crate::config::KERNEL_STACK_SIZE;
use crate::kernel::CURRENT_STACK_ADDRESS;

#[unsafe(naked)]
pub unsafe extern "C" fn smp_start() -> ! {
core::arch::naked_asm!(
// Overwrite RSP with `CURRENT_STACK_ADDRESS`
"mov rax, qword ptr [rip + {current_stack_address}@GOTPCREL]",
"mov rsp, qword ptr [rax]",

// Add top stack offset
"add rsp, {stack_top_offset}",

// Jump into Rust code
"jmp {smp_start_rust}",

current_stack_address = sym CURRENT_STACK_ADDRESS,
stack_top_offset = const KERNEL_STACK_SIZE - TaskStacks::MARKER_SIZE,
smp_start_rust = sym smp_start_rust,
)
}

unsafe extern "C" fn smp_start_rust() -> ! {
// Enable caching
unsafe {
Cr0::update(|flags| flags.remove(Cr0Flags::CACHE_DISABLE | Cr0Flags::NOT_WRITE_THROUGH));
}

crate::application_processor_main();
}
Loading