From d7cd0244ff7841c657c831203beeb9d4fb1a2c05 Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Sun, 18 May 2025 23:47:15 +0800 Subject: [PATCH] Use Rust types to store `PerApRawInfo` --- ostd/src/arch/riscv/boot/smp.rs | 4 ++-- ostd/src/arch/x86/boot/smp.rs | 6 ++--- ostd/src/boot/smp.rs | 39 +++++++++++---------------------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/ostd/src/arch/riscv/boot/smp.rs b/ostd/src/arch/riscv/boot/smp.rs index 24bfa352..84ca6dbb 100644 --- a/ostd/src/arch/riscv/boot/smp.rs +++ b/ostd/src/arch/riscv/boot/smp.rs @@ -8,6 +8,6 @@ pub(crate) fn count_processors() -> Option { Some(1) } -pub(crate) fn bringup_all_aps(_info_ptr: *mut PerApRawInfo, _pr_ptr: Paddr, _num_cpus: u32) { - todo!() +pub(crate) fn bringup_all_aps(_info_ptr: *const PerApRawInfo, _pr_ptr: Paddr, _num_cpus: u32) { + unimplemented!() } diff --git a/ostd/src/arch/x86/boot/smp.rs b/ostd/src/arch/x86/boot/smp.rs index d856a6d4..3a9a931f 100644 --- a/ostd/src/arch/x86/boot/smp.rs +++ b/ostd/src/arch/x86/boot/smp.rs @@ -113,7 +113,7 @@ pub(crate) fn count_processors() -> Option { /// 1. we're in the boot context of the BSP, /// 2. all APs have not yet been booted, and /// 3. the arguments are valid to boot APs. -pub(crate) unsafe fn bringup_all_aps(info_ptr: *mut PerApRawInfo, pt_ptr: Paddr, num_cpus: u32) { +pub(crate) unsafe fn bringup_all_aps(info_ptr: *const PerApRawInfo, pt_ptr: Paddr, num_cpus: u32) { // SAFETY: The code and data to boot AP is valid to write because // there are no readers and we are the only writer at this point. unsafe { @@ -172,9 +172,9 @@ unsafe fn copy_ap_boot_code() { /// # Safety /// /// The caller must ensure the pointer to be filled is valid to write. -unsafe fn fill_boot_info_ptr(info_ptr: *mut PerApRawInfo) { +unsafe fn fill_boot_info_ptr(info_ptr: *const PerApRawInfo) { extern "C" { - static mut __ap_boot_info_array_pointer: *mut PerApRawInfo; + static mut __ap_boot_info_array_pointer: *const PerApRawInfo; } // SAFETY: The safety is upheld by the caller. diff --git a/ostd/src/boot/smp.rs b/ostd/src/boot/smp.rs index 17e81d41..44cf9c8b 100644 --- a/ostd/src/boot/smp.rs +++ b/ostd/src/boot/smp.rs @@ -23,7 +23,7 @@ const AP_BOOT_STACK_SIZE: usize = PAGE_SIZE * 64; struct ApBootInfo { /// Raw boot information for each AP. - per_ap_raw_info: Segment, + per_ap_raw_info: Box<[PerApRawInfo]>, /// Boot information for each AP. per_ap_info: Box<[PerApInfo]>, } @@ -50,6 +50,12 @@ pub(crate) struct PerApRawInfo { cpu_local: *mut u8, } +// SAFETY: This information (i.e., the pointer addresses) can be shared safely +// among multiple threads. However, it is the responsibility of the user to +// ensure that the contained pointers are used safely. +unsafe impl Send for PerApRawInfo {} +unsafe impl Sync for PerApRawInfo {} + static AP_LATE_ENTRY: Once = Once::new(); /// Boots all application processors. @@ -74,20 +80,8 @@ pub(crate) unsafe fn boot_all_aps() { // 1. the bootstrap processor (BSP) has the processor ID 0; // 2. the processor ID starts from `0` to `num_cpus - 1`. - let mut per_ap_info = Vec::new(); - - let per_ap_raw_info = FrameAllocOptions::new() - .zeroed(false) - .alloc_segment_with( - num_cpus - .saturating_sub(1) - .checked_mul(core::mem::size_of::()) - .unwrap() - .div_ceil(PAGE_SIZE), - |_| KernelMeta, - ) - .unwrap(); - let raw_info_ptr = paddr_to_vaddr(per_ap_raw_info.start_paddr()) as *mut PerApRawInfo; + let mut per_ap_raw_info = Vec::with_capacity(num_cpus); + let mut per_ap_info = Vec::with_capacity(num_cpus); for ap in 1..num_cpus { let boot_stack_pages = FrameAllocOptions::new() @@ -95,16 +89,10 @@ pub(crate) unsafe fn boot_all_aps() { .alloc_segment_with(AP_BOOT_STACK_SIZE / PAGE_SIZE, |_| KernelMeta) .unwrap(); - let raw_info = PerApRawInfo { + per_ap_raw_info.push(PerApRawInfo { stack_top: paddr_to_vaddr(boot_stack_pages.end_paddr()) as *mut u8, cpu_local: paddr_to_vaddr(crate::cpu::local::get_ap(ap.try_into().unwrap())) as *mut u8, - }; - - // SAFETY: The index is in range because we allocated enough memory. - let ptr = unsafe { raw_info_ptr.add(ap - 1) }; - // SAFETY: The memory is valid for writing because it was just allocated. - unsafe { ptr.write(raw_info) }; - + }); per_ap_info.push(PerApInfo { is_started: AtomicBool::new(false), boot_stack_pages, @@ -113,14 +101,13 @@ pub(crate) unsafe fn boot_all_aps() { assert!(!AP_BOOT_INFO.is_completed()); AP_BOOT_INFO.call_once(move || ApBootInfo { - per_ap_raw_info, + per_ap_raw_info: per_ap_raw_info.into_boxed_slice(), per_ap_info: per_ap_info.into_boxed_slice(), }); log::info!("Booting all application processors..."); - let info_ptr = paddr_to_vaddr(AP_BOOT_INFO.get().unwrap().per_ap_raw_info.start_paddr()) - as *mut PerApRawInfo; + let info_ptr = AP_BOOT_INFO.get().unwrap().per_ap_raw_info.as_ptr(); let pt_ptr = crate::mm::page_table::boot_pt::with_borrow(|pt| pt.root_address()).unwrap(); // SAFETY: It's the right time to boot APs (guaranteed by the caller) and // the arguments are valid to boot APs (generated above).