diff --git a/kernel/src/cpu/paging.rs b/kernel/src/cpu/paging.rs index 38c38c8..15d44f5 100644 --- a/kernel/src/cpu/paging.rs +++ b/kernel/src/cpu/paging.rs @@ -13,7 +13,7 @@ use kernel_common::{ use log::info; use spin::Mutex; -use crate::sys::lapic::smp_invalidate_tlb; +use crate::sys::smp::smp_invalidate_tlb; extern "C" { static _text_start: u8; diff --git a/kernel/src/main.rs b/kernel/src/main.rs index bc0a0a1..4b3454e 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -29,9 +29,10 @@ use sys::{ acpica_osl::AE_OK, early_acpi::EarlyACPIHandler, hpet::setup_hpet, - lapic::{get_current_lapic_id, setup_lapic_timer, smp_broadcast_panic, start_aps}, + lapic::{get_current_lapic_id, setup_lapic_timer}, madt::{parse_madt, INTERRUPTS_SETUP}, pic::disable_pic, + smp::{smp_broadcast_panic, start_aps}, sync::LOCKS_HELD, task::setup_multitasking, }; diff --git a/kernel/src/sys/lapic.rs b/kernel/src/sys/lapic.rs index 8d2ef14..0e8d600 100644 --- a/kernel/src/sys/lapic.rs +++ b/kernel/src/sys/lapic.rs @@ -1,36 +1,16 @@ use core::{ - ptr::{copy, null_mut}, + ptr::null_mut, sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering}, }; -use alloc::{vec, vec::Vec}; -use kernel_common::{ - instructions::{get_rflags, pause}, - paging::PageTable, -}; +use kernel_common::instructions::get_rflags; -use crate::{ - cpu::{ - isr::{ISR_INVALIDATE_TLB, ISR_SCHEDULER}, - paging::{map_physical, map_range, unmap, virt_to_phys, CURRENT_PML4}, - }, - BROADCASTED_PANIC, -}; +use crate::cpu::{isr::ISR_SCHEDULER, paging::map_physical}; -use super::{ - hpet::sleep, - sync::Spinlock, - task::{ALL_APS_STARTED, STACK_SIZE, STARTING_AP_ID}, -}; +use super::hpet::sleep; -extern "C" { - fn ap_trampoline(); - static trampoline_pml4: u8; - static trampoline_stack: u8; -} - -struct LAPIC { - lapic_id: AtomicUsize, +pub struct LAPIC { + pub lapic_id: AtomicUsize, present: AtomicBool, } @@ -43,13 +23,10 @@ const REGISTER_TIMER_LVT: usize = 0xc8; const REGISTER_TIMER_INITIAL_COUNT: usize = 0xe0; const REGISTER_TIMER_CURRENT_COUNT: usize = 0xe4; const REGISTER_TIMER_DIVIDE: usize = 0xf8; -const IPI_NMI: u32 = 0x400; -const IPI_INIT: u32 = 0x500; -const IPI_STARTUP: u32 = 0x600; static ADDRESS: AtomicPtr = AtomicPtr::new(null_mut()); pub static BSP_LAPIC_ID: AtomicUsize = AtomicUsize::new(0); -static LAPICS: [LAPIC; 256] = [const { +pub static LAPICS: [LAPIC; 256] = [const { LAPIC { lapic_id: AtomicUsize::new(0), present: AtomicBool::new(false), @@ -57,7 +34,6 @@ static LAPICS: [LAPIC; 256] = [const { }; 256]; static TICKS_PER_MS: AtomicUsize = AtomicUsize::new(0); pub static NEXT_LAPIC_ID: AtomicUsize = AtomicUsize::new(0); -static INVALIDATE_TLB_LOCK: Spinlock = Spinlock::new(); pub fn send_eoi() { let address = ADDRESS.load(Ordering::SeqCst); @@ -92,7 +68,7 @@ fn calibrate_timer() { let ticks_in_10ms = 0xffffffff - unsafe { address.add(REGISTER_TIMER_CURRENT_COUNT).read_volatile() }; TICKS_PER_MS.store(ticks_in_10ms as usize / 10, Ordering::SeqCst); } -fn send_ipi(lapic_id: usize, data: u32) { +pub fn send_ipi(lapic_id: usize, data: u32) { let address = ADDRESS.load(Ordering::SeqCst); unsafe { address.add(REGISTER_ICR_2).write_volatile((lapic_id << 24) as u32); @@ -124,72 +100,3 @@ pub fn add_lapic(lapic_id: usize) { LAPICS[next_id].lapic_id.store(lapic_id, Ordering::SeqCst); LAPICS[next_id].present.store(true, Ordering::SeqCst); } -pub fn start_aps() { - let stack: Vec = vec![0; STACK_SIZE]; - let pml4_phys_addr; - { - let pml4 = CURRENT_PML4.lock(); - let pml4 = pml4.as_ref().unwrap(); - let pml4_phys_addr_u64 = virt_to_phys(*pml4 as *const PageTable as u64); - pml4_phys_addr = u32::try_from(pml4_phys_addr_u64).unwrap(); - } - unsafe { - map_range(0x1000, 0x1000, 0x1000, false, true, false, false); - let dest_ptr = 0x1000 as *mut u8; - let src_ptr = ap_trampoline as *const u8; - copy(src_ptr, dest_ptr, 0x1000); - let pml4_offset = (&raw const trampoline_pml4).offset_from(src_ptr); - let pml4_addr = (0x1000 + pml4_offset) as *mut u32; - *pml4_addr = pml4_phys_addr; - let stack_offset = (&raw const trampoline_stack).offset_from(src_ptr); - let stack_addr = (0x1000 + stack_offset) as *mut u64; - *stack_addr = stack.as_ptr() as u64 + STACK_SIZE as u64; - map_range(0x1000, 0x1000, 0x1000, false, true, true, false); - } - for i in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) { - let lapic_id = LAPICS[i].lapic_id.load(Ordering::SeqCst); - if lapic_id == BSP_LAPIC_ID.load(Ordering::SeqCst) { - continue; - } - STARTING_AP_ID.store(lapic_id as i64, Ordering::SeqCst); - send_ipi(lapic_id, IPI_INIT); - sleep(10000); - send_ipi(lapic_id, IPI_STARTUP | 1); - while STARTING_AP_ID.load(Ordering::SeqCst) != -1 { - pause(); - } - } - ALL_APS_STARTED.store(true, Ordering::SeqCst); - unsafe { - unmap(0x1000); - } -} -pub fn smp_invalidate_tlb() { - if !ALL_APS_STARTED.load(Ordering::SeqCst) { - return; - } - INVALIDATE_TLB_LOCK.lock(); - let current_lapic_id = get_current_lapic_id(); - for i in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) { - let lapic_id = LAPICS[i].lapic_id.load(Ordering::SeqCst); - if lapic_id == current_lapic_id { - continue; - } - send_ipi(lapic_id, ISR_INVALIDATE_TLB as u32); - } - INVALIDATE_TLB_LOCK.unlock(); -} -pub fn smp_broadcast_panic() { - BROADCASTED_PANIC.store(true, Ordering::SeqCst); - if !ALL_APS_STARTED.load(Ordering::SeqCst) { - return; - } - let current_lapic_id = get_current_lapic_id(); - for i in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) { - let lapic_id = LAPICS[i].lapic_id.load(Ordering::SeqCst); - if lapic_id == current_lapic_id { - continue; - } - send_ipi(lapic_id, IPI_NMI); - } -} diff --git a/kernel/src/sys/mod.rs b/kernel/src/sys/mod.rs index 9440a68..d3a923a 100644 --- a/kernel/src/sys/mod.rs +++ b/kernel/src/sys/mod.rs @@ -6,5 +6,6 @@ pub mod lapic; pub mod madt; pub mod pic; pub mod scheduler; +pub mod smp; pub mod sync; pub mod task; diff --git a/kernel/src/sys/smp.rs b/kernel/src/sys/smp.rs new file mode 100644 index 0000000..32db39b --- /dev/null +++ b/kernel/src/sys/smp.rs @@ -0,0 +1,101 @@ +use core::{ptr::copy, sync::atomic::Ordering}; + +use alloc::{vec, vec::Vec}; +use kernel_common::{instructions::pause, paging::PageTable}; + +use crate::{ + cpu::{ + isr::ISR_INVALIDATE_TLB, + paging::{map_range, unmap, virt_to_phys, CURRENT_PML4}, + }, + BROADCASTED_PANIC, +}; + +use super::{ + hpet::sleep, + lapic::{get_current_lapic_id, send_ipi, BSP_LAPIC_ID, LAPICS, NEXT_LAPIC_ID}, + sync::Spinlock, + task::{ALL_APS_STARTED, STACK_SIZE, STARTING_AP_ID}, +}; + +extern "C" { + fn ap_trampoline(); + static trampoline_pml4: u8; + static trampoline_stack: u8; +} + +const IPI_NMI: u32 = 0x400; +const IPI_INIT: u32 = 0x500; +const IPI_STARTUP: u32 = 0x600; + +static INVALIDATE_TLB_LOCK: Spinlock = Spinlock::new(); + +pub fn start_aps() { + let stack: Vec = vec![0; STACK_SIZE]; + let pml4_phys_addr; + { + let pml4 = CURRENT_PML4.lock(); + let pml4 = pml4.as_ref().unwrap(); + let pml4_phys_addr_u64 = virt_to_phys(*pml4 as *const PageTable as u64); + pml4_phys_addr = u32::try_from(pml4_phys_addr_u64).unwrap(); + } + unsafe { + map_range(0x1000, 0x1000, 0x1000, false, true, false, false); + let dest_ptr = 0x1000 as *mut u8; + let src_ptr = ap_trampoline as *const u8; + copy(src_ptr, dest_ptr, 0x1000); + let pml4_offset = (&raw const trampoline_pml4).offset_from(src_ptr); + let pml4_addr = (0x1000 + pml4_offset) as *mut u32; + *pml4_addr = pml4_phys_addr; + let stack_offset = (&raw const trampoline_stack).offset_from(src_ptr); + let stack_addr = (0x1000 + stack_offset) as *mut u64; + *stack_addr = stack.as_ptr() as u64 + STACK_SIZE as u64; + map_range(0x1000, 0x1000, 0x1000, false, true, true, false); + } + for i in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) { + let lapic_id = LAPICS[i].lapic_id.load(Ordering::SeqCst); + if lapic_id == BSP_LAPIC_ID.load(Ordering::SeqCst) { + continue; + } + STARTING_AP_ID.store(lapic_id as i64, Ordering::SeqCst); + send_ipi(lapic_id, IPI_INIT); + sleep(10000); + send_ipi(lapic_id, IPI_STARTUP | 1); + while STARTING_AP_ID.load(Ordering::SeqCst) != -1 { + pause(); + } + } + ALL_APS_STARTED.store(true, Ordering::SeqCst); + unsafe { + unmap(0x1000); + } +} +pub fn smp_invalidate_tlb() { + if !ALL_APS_STARTED.load(Ordering::SeqCst) { + return; + } + INVALIDATE_TLB_LOCK.lock(); + let current_lapic_id = get_current_lapic_id(); + for i in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) { + let lapic_id = LAPICS[i].lapic_id.load(Ordering::SeqCst); + if lapic_id == current_lapic_id { + continue; + } + send_ipi(lapic_id, ISR_INVALIDATE_TLB as u32); + } + INVALIDATE_TLB_LOCK.unlock(); +} +pub fn smp_broadcast_panic() { + BROADCASTED_PANIC.store(true, Ordering::SeqCst); + if !ALL_APS_STARTED.load(Ordering::SeqCst) { + return; + } + let current_lapic_id = get_current_lapic_id(); + for i in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) { + let lapic_id = LAPICS[i].lapic_id.load(Ordering::SeqCst); + if lapic_id == current_lapic_id { + continue; + } + send_ipi(lapic_id, IPI_NMI); + } +}