Set the page table for APs before kicking

This commit is contained in:
Zhang Junyang
2024-12-13 21:23:52 +08:00
committed by Tate, Hongliang Tian
parent 285dde5546
commit 68bdda4c4c
3 changed files with 41 additions and 11 deletions

View File

@ -83,7 +83,13 @@ x2apic_mode:
rdmsr rdmsr
jmp ap_protect jmp ap_protect
.code32 // This is a pointer to the page table used by the APs.
// The BSP will fill this pointer before kicking the APs.
.global __boot_page_table_pointer
.align 4
__boot_page_table_pointer:
.skip 4
ap_protect: ap_protect:
// Save the local APIC ID in an unused register. // Save the local APIC ID in an unused register.
// We will calculate the stack pointer of this core // We will calculate the stack pointer of this core
@ -103,7 +109,7 @@ ap_protect:
// Set the page table. The application processors use // Set the page table. The application processors use
// the same page table as the bootstrap processor's // the same page table as the bootstrap processor's
// boot phase page table. // boot phase page table.
lea eax, [boot_page_table_start] mov eax, __boot_page_table_pointer
mov cr3, eax mov cr3, eax
// Enable long mode. // Enable long mode.
@ -132,9 +138,9 @@ ap_long_mode_in_low_address:
mov rax, offset ap_long_mode mov rax, offset ap_long_mode
jmp rax jmp rax
.data
// This is a pointer to be filled by the BSP when boot stacks // This is a pointer to be filled by the BSP when boot stacks
// of all APs are allocated and initialized. // of all APs are allocated and initialized.
.data
.global __ap_boot_stack_array_pointer .global __ap_boot_stack_array_pointer
.align 8 .align 8
__ap_boot_stack_array_pointer: __ap_boot_stack_array_pointer:

View File

@ -57,7 +57,8 @@ pub(crate) fn get_num_processors() -> Option<u32> {
/// Brings up all application processors. /// Brings up all application processors.
pub(crate) fn bringup_all_aps() { pub(crate) fn bringup_all_aps() {
copy_ap_boot_code(); copy_ap_boot_code();
init_boot_stack_array(); fill_boot_stack_array_ptr();
fill_boot_pt_ptr();
send_boot_ipis(); send_boot_ipis();
} }
@ -85,7 +86,7 @@ fn copy_ap_boot_code() {
} }
/// Initializes the boot stack array in the AP boot code with the given pages. /// Initializes the boot stack array in the AP boot code with the given pages.
fn init_boot_stack_array() { fn fill_boot_stack_array_ptr() {
let pages = &crate::boot::smp::AP_BOOT_INFO let pages = &crate::boot::smp::AP_BOOT_INFO
.get() .get()
.unwrap() .unwrap()
@ -97,7 +98,7 @@ fn init_boot_stack_array() {
} }
let ap_boot_stack_arr_ptr: *mut u64 = __ap_boot_stack_array_pointer as usize as *mut u64; let ap_boot_stack_arr_ptr: *mut u64 = __ap_boot_stack_array_pointer as usize as *mut u64;
log::debug!( log::debug!(
"__ap_boot_stack_array_pointer: {:#x?}", "Setting __ap_boot_stack_array_pointer={:#x?} for AP boot stacks",
ap_boot_stack_arr_ptr ap_boot_stack_arr_ptr
); );
@ -107,6 +108,24 @@ fn init_boot_stack_array() {
} }
} }
fn fill_boot_pt_ptr() {
// This is defined in the boot assembly code.
extern "C" {
fn __boot_page_table_pointer();
}
let boot_pt_ptr: *mut u32 = __boot_page_table_pointer as usize as *mut u32;
let boot_pt = crate::mm::page_table::boot_pt::with_borrow(|pt| pt.root_address()).unwrap();
log::debug!(
"Setting __boot_page_table_pointer={:#x?} for AP boot page tables",
boot_pt
);
// SAFETY: this pointer points to a static variable defined in the `ap_boot.S`.
unsafe {
boot_pt_ptr.write_volatile(boot_pt as u32);
}
}
// The symbols are defined in the linker script. // The symbols are defined in the linker script.
extern "C" { extern "C" {
fn __ap_boot_start(); fn __ap_boot_start();

View File

@ -16,7 +16,7 @@ use crate::{
cpu::num_cpus, cpu::num_cpus,
cpu_local_cell, cpu_local_cell,
mm::{ mm::{
nr_subpage_per_huge, paddr_to_vaddr, page::allocator::PAGE_ALLOCATOR, PageProperty, nr_subpage_per_huge, paddr_to_vaddr, page::allocator::PAGE_ALLOCATOR, Paddr, PageProperty,
PagingConstsTrait, Vaddr, PAGE_SIZE, PagingConstsTrait, Vaddr, PAGE_SIZE,
}, },
sync::SpinLock, sync::SpinLock,
@ -32,9 +32,9 @@ type FrameNumber = usize;
/// ///
/// The boot page table will be dropped when there's no CPU activating it. /// The boot page table will be dropped when there's no CPU activating it.
/// This function will return an [`Err`] if the boot page table is dropped. /// This function will return an [`Err`] if the boot page table is dropped.
pub(crate) fn with_borrow<F>(f: F) -> Result<(), ()> pub(crate) fn with_borrow<F, R>(f: F) -> Result<R, ()>
where where
F: FnOnce(&mut BootPageTable), F: FnOnce(&mut BootPageTable) -> R,
{ {
let mut boot_pt = BOOT_PAGE_TABLE.lock(); let mut boot_pt = BOOT_PAGE_TABLE.lock();
@ -48,9 +48,9 @@ where
*boot_pt = Some(unsafe { BootPageTable::from_current_pt() }); *boot_pt = Some(unsafe { BootPageTable::from_current_pt() });
} }
f(boot_pt.as_mut().unwrap()); let r = f(boot_pt.as_mut().unwrap());
Ok(()) Ok(r)
} }
/// Dismiss the boot page table. /// Dismiss the boot page table.
@ -115,6 +115,11 @@ impl<E: PageTableEntryTrait, C: PagingConstsTrait> BootPageTable<E, C> {
} }
} }
/// Returns the root physical address of the boot page table.
pub(crate) fn root_address(&self) -> Paddr {
self.root_pt * C::BASE_PAGE_SIZE
}
/// Maps a base page to a frame. /// Maps a base page to a frame.
/// ///
/// # Panics /// # Panics