diff --git a/Cargo.lock b/Cargo.lock index c590be81..7ca8ff5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "thiserror", ] @@ -168,7 +168,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -179,7 +179,7 @@ checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -266,7 +266,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -337,7 +337,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -405,7 +405,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -473,7 +473,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -686,7 +686,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1266,7 +1266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1522,7 +1522,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1586,9 +1586,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -1642,7 +1642,7 @@ checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1834,7 +1834,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -1856,7 +1856,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2309,5 +2309,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] diff --git a/kernel/arch/aarch64/src/mem/mod.rs b/kernel/arch/aarch64/src/mem/mod.rs index 46da6408..165e76b2 100644 --- a/kernel/arch/aarch64/src/mem/mod.rs +++ b/kernel/arch/aarch64/src/mem/mod.rs @@ -9,12 +9,12 @@ use core::{ use aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1}; use kernel_arch_interface::{ mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping}, + sync::split_spinlock, KERNEL_VIRT_OFFSET, }; use libk_mm_interface::{ address::PhysicalAddress, table::{page_index, EntryLevel, EntryLevelExt}, - KernelImageObject, }; use memtables::aarch64::{FixedTables, KERNEL_L3_COUNT}; use static_assertions::const_assert_eq; @@ -66,9 +66,15 @@ static mut DEVICE_MAPPING_L3S: [PageTable; DEVICE_MAPPING_L3_COUNT] = pub const RAM_MAPPING_OFFSET: usize = MAPPING_OFFSET | (RAM_MAPPING_START_L1I * L1::SIZE); pub static MEMORY_LIMIT: AtomicUsize = AtomicUsize::new(0); -#[link_section = ".data.tables"] -pub static mut KERNEL_TABLES: KernelImageObject = - unsafe { KernelImageObject::new(FixedTables::zeroed()) }; +split_spinlock! { + use crate::ArchitectureImpl; + use crate::mem::FixedTables; + use libk_mm_interface::KernelImageObject; + + #[link_section = ".data.tables"] + static KERNEL_TABLES: KernelImageObject = + unsafe { KernelImageObject::new(FixedTables::zeroed()) }; +} impl KernelTableManager for KernelTableManagerImpl { fn virtualize(address: u64) -> usize { @@ -221,9 +227,10 @@ pub unsafe fn map_ram_l1(index: usize) { if index >= RAM_MAPPING_L1_COUNT { todo!() } - assert_eq!(KERNEL_TABLES.l1.data[index + RAM_MAPPING_START_L1I], 0); + let mut tables = KERNEL_TABLES.lock(); + assert_eq!(tables.l1.data[index + RAM_MAPPING_START_L1I], 0); - KERNEL_TABLES.l1.data[index + RAM_MAPPING_START_L1I] = + tables.l1.data[index + RAM_MAPPING_START_L1I] = ((index * L1::SIZE) as u64) | ram_block_flags().bits(); } @@ -363,8 +370,7 @@ pub fn tlb_flush_vaae1(mut page: usize) { /// /// Unsafe, must only be called by BSP during its early init while still in "lower-half" pub unsafe fn load_fixed_tables() { - #[allow(static_mut_refs)] - let ttbr0 = KERNEL_TABLES.l1.data.as_ptr() as u64; + let ttbr0 = KERNEL_TABLES.lock().l1.data.as_ptr().addr() as u64; TTBR0_EL1.set(ttbr0); TTBR1_EL1.set(ttbr0); } @@ -376,6 +382,7 @@ pub unsafe fn load_fixed_tables() { /// Unsafe, must only be called by BSP during its early init, must already be in "higher-half" pub unsafe fn init_fixed_tables() { // TODO this could be built in compile-time too? + let mut tables = KERNEL_TABLES.lock(); let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET; let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET; @@ -386,11 +393,11 @@ pub unsafe fn init_fixed_tables() { DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::empty()); } - assert_eq!(KERNEL_TABLES.l2.data[EARLY_MAPPING_L2I], 0); - KERNEL_TABLES.l2.data[EARLY_MAPPING_L2I] = + assert_eq!(tables.l2.data[EARLY_MAPPING_L2I], 0); + tables.l2.data[EARLY_MAPPING_L2I] = (early_mapping_l3_phys as u64) | kernel_table_flags().bits(); - assert_eq!(KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I], 0); - KERNEL_TABLES.l1.data[DEVICE_MAPPING_L1I] = + assert_eq!(tables.l1.data[DEVICE_MAPPING_L1I], 0); + tables.l1.data[DEVICE_MAPPING_L1I] = (device_mapping_l2_phys as u64) | kernel_table_flags().bits(); } diff --git a/kernel/arch/i686/src/context.rs b/kernel/arch/i686/src/context.rs index 0905d44b..cca2ade2 100644 --- a/kernel/arch/i686/src/context.rs +++ b/kernel/arch/i686/src/context.rs @@ -11,7 +11,7 @@ use yggdrasil_abi::{arch::SavedFrame, error::Error}; use crate::{ gdt::{self, TSS}, - mem::kernel_tables, + mem::KERNEL_TABLES, }; #[allow(unused)] @@ -156,7 +156,8 @@ impl> 22; @@ -130,7 +130,7 @@ impl KernelDynamic { } pub fn clone_kernel_tables(dst: &mut PageTable) { - let tables = kernel_tables(); + let tables = KERNEL_TABLES.lock(); for (i, entry) in tables.l0.kernel.iter().enumerate() { dst[i + KERNEL_SPLIT_L0] = *entry; } diff --git a/kernel/arch/i686/src/mem/mod.rs b/kernel/arch/i686/src/mem/mod.rs index 5e5079a3..9f87e69f 100644 --- a/kernel/arch/i686/src/mem/mod.rs +++ b/kernel/arch/i686/src/mem/mod.rs @@ -1,18 +1,12 @@ -use core::{ - cell::UnsafeCell, - ops::{Deref, DerefMut}, -}; - use fixed::FixedTables; use kernel_arch_interface::{ mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping}, - sync::{IrqSafeSpinlock, IrqSafeSpinlockGuard}, + sync::split_spinlock, KERNEL_VIRT_OFFSET, }; use libk_mm_interface::{ address::{AsPhysicalAddress, PhysicalAddress}, table::{page_count, EntryLevel}, - KernelImageObject, }; use table::{PageAttributes, PageEntry, L0, L3}; use yggdrasil_abi::error::Error; @@ -23,59 +17,18 @@ pub mod table; pub use process::ProcessAddressSpaceImpl; -use crate::ArchitectureImpl; - #[derive(Debug)] pub struct KernelTableManagerImpl; -#[link_section = ".data.tables"] -pub static KERNEL_TABLES: KernelTablesInner = KernelTablesInner::new(); -static KERNEL_TABLES_LOCK: IrqSafeSpinlock = IrqSafeSpinlock::new(()); +split_spinlock! { + use libk_mm_interface::KernelImageObject; + use crate::mem::FixedTables; + use crate::ArchitectureImpl; -#[repr(C, align(0x1000))] -pub struct KernelTablesInner { - inner: UnsafeCell>, -} - -impl KernelTablesInner { - const fn new() -> Self { - Self { - inner: unsafe { UnsafeCell::new(KernelImageObject::new(FixedTables::zeroed())) }, - } - } -} - -unsafe impl Sync for KernelTablesInner {} - -pub struct KernelTablesGuard<'a> { - inner: &'a KernelTablesInner, - _guard: IrqSafeSpinlockGuard<'a, ArchitectureImpl, ()>, -} - -pub fn kernel_tables<'a>() -> KernelTablesGuard<'a> { - let _guard = KERNEL_TABLES_LOCK.lock(); - let inner = &KERNEL_TABLES; - KernelTablesGuard { inner, _guard } -} - -impl AsPhysicalAddress for KernelTablesGuard<'_> { - unsafe fn as_physical_address(&self) -> PhysicalAddress { - (*self.inner.inner.get()).as_physical_address() - } -} - -impl Deref for KernelTablesGuard<'_> { - type Target = KernelImageObject; - - fn deref(&self) -> &Self::Target { - unsafe { &*self.inner.inner.get() } - } -} - -impl DerefMut for KernelTablesGuard<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { &mut *self.inner.inner.get() } - } + #[link_section = ".data.tables"] + static KERNEL_TABLES: KernelImageObject = unsafe { + KernelImageObject::new(FixedTables::zeroed()) + }; } impl KernelTableManager for KernelTableManagerImpl { @@ -97,7 +50,7 @@ impl KernelTableManager for KernelTableManagerImpl { assert_eq!(base & 0xFFF, 0); log::info!("map_device_pages({:#x}, {})", base, count); let page_count = page_count::(count); - let virt = kernel_tables().map_dynamic_memory(base, page_count)?; + let virt = KERNEL_TABLES.lock().map_dynamic_memory(base, page_count)?; Ok(RawDeviceMemoryMapping::from_raw_parts( virt, virt, page_count, 0, @@ -110,11 +63,14 @@ impl KernelTableManager for KernelTableManagerImpl { } fn virtualize(phys: u64) -> usize { - kernel_tables().virtualize(PhysicalAddress::from_u64(phys)) + KERNEL_TABLES + .lock() + .virtualize(PhysicalAddress::from_u64(phys)) } fn physicalize(virt: usize) -> u64 { - kernel_tables() + KERNEL_TABLES + .lock() .physicalize(virt) .expect("Invalid virtual address") .into_u64() @@ -137,7 +93,7 @@ impl KernelTableManager for KernelTableManagerImpl { /// /// Only meant to be called once during early OS init. pub unsafe fn init_fixed_tables() { - let mut tables = kernel_tables(); + let mut tables = KERNEL_TABLES.lock(); // Unmap lower stuff for (i, entry) in tables.l0.lower.iter_mut().enumerate() { diff --git a/kernel/arch/interface/src/lib.rs b/kernel/arch/interface/src/lib.rs index de1b3aea..f3f46c8b 100644 --- a/kernel/arch/interface/src/lib.rs +++ b/kernel/arch/interface/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -#![feature(step_trait, const_trait_impl, never_type)] +#![feature(step_trait, const_trait_impl, never_type, decl_macro)] #![allow(clippy::new_without_default)] use alloc::vec::Vec; diff --git a/kernel/arch/interface/src/sync.rs b/kernel/arch/interface/src/sync.rs index a1f6bbae..6934410f 100644 --- a/kernel/arch/interface/src/sync.rs +++ b/kernel/arch/interface/src/sync.rs @@ -153,3 +153,67 @@ impl<'a, A: Architecture, T> DerefMut for IrqSafeSpinlockGuard<'a, A, T> { self.inner.deref_mut() } } + +/// Helper macro to implement "split" locks. This may be needed when a very specific storage +/// layout for the locked type is required. +pub macro split_spinlock( + $(use $use:path;)* + + $(#[$meta:meta])* + static $name:ident<$lock:ident: $arch:ty>: $ty:ty = $init:expr; +) { + pub use $name::$name; + + #[allow(non_snake_case)] + pub mod $name { + $(use $use;)* + + use core::cell::UnsafeCell; + use core::marker::PhantomData; + use core::sync::atomic::{AtomicBool, Ordering}; + + $(#[$meta])* + pub static $name: __Wrapper = __Wrapper { + inner: UnsafeCell::new($init) + }; + static __LOCK: AtomicBool = AtomicBool::new(false); + + #[repr(transparent)] + pub struct __Wrapper { + inner: UnsafeCell<$ty> + } + pub struct __Guard($crate::guard::IrqGuard<$arch>); + + impl __Wrapper { + pub fn $lock(&self) -> __Guard { + let irq = $crate::guard::IrqGuard::acquire(); + while __LOCK.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() { + core::hint::spin_loop(); + } + __Guard(irq) + } + } + + unsafe impl Sync for __Wrapper {} + + impl core::ops::Deref for __Guard { + type Target = $ty; + + fn deref(&self) -> &Self::Target { + unsafe { &*$name.inner.get() } + } + } + + impl core::ops::DerefMut for __Guard { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *$name.inner.get() } + } + } + + impl Drop for __Guard { + fn drop(&mut self) { + __LOCK.store(false, Ordering::Release) + } + } + } +} diff --git a/kernel/arch/x86_64/src/context.rs b/kernel/arch/x86_64/src/context.rs index de64ff9a..ca87acca 100644 --- a/kernel/arch/x86_64/src/context.rs +++ b/kernel/arch/x86_64/src/context.rs @@ -423,10 +423,7 @@ impl = - unsafe { KernelImageObject::new(FixedTables::zeroed()) }; +split_spinlock! { + use crate::ArchitectureImpl; + use crate::mem::FixedTables; + use libk_mm_interface::KernelImageObject; + + #[link_section = ".data.tables"] + static KERNEL_TABLES: KernelImageObject = + unsafe { KernelImageObject::new(FixedTables::zeroed()) }; +} // 2MiB for early mappings const EARLY_MAPPING_OFFSET: usize = CANONICAL_ADDRESS_MASK @@ -336,9 +342,10 @@ impl<'a, T: ?Sized> Drop for EarlyMapping<'a, T> { } pub fn clone_kernel_tables(dst: &mut PageTable) { + let tables = KERNEL_TABLES.lock(); unsafe { - dst[KERNEL_L0_INDEX] = PageEntry::from_raw(KERNEL_TABLES.l0.data[KERNEL_L0_INDEX]); - dst[RAM_MAPPING_L0I] = PageEntry::from_raw(KERNEL_TABLES.l0.data[RAM_MAPPING_L0I]); + dst[KERNEL_L0_INDEX] = PageEntry::from_raw(tables.l0.data[KERNEL_L0_INDEX]); + dst[RAM_MAPPING_L0I] = PageEntry::from_raw(tables.l0.data[RAM_MAPPING_L0I]); } } @@ -359,6 +366,7 @@ pub fn clone_kernel_tables(dst: &mut PageTable) { /// /// Unsafe, must only be called by BSP during its early init, must already be in "higher-half" pub unsafe fn init_fixed_tables() { + let mut tables = KERNEL_TABLES.lock(); // TODO this could be built in compile-time too? let early_mapping_l3_phys = addr_of!(EARLY_MAPPING_L3) as usize - KERNEL_VIRT_OFFSET; let device_mapping_l2_phys = addr_of!(DEVICE_MAPPING_L2) as usize - KERNEL_VIRT_OFFSET; @@ -371,20 +379,20 @@ pub unsafe fn init_fixed_tables() { DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::WRITABLE); } - assert_eq!(KERNEL_TABLES.kernel_l2.data[EARLY_MAPPING_L2I], 0); - KERNEL_TABLES.kernel_l2.data[EARLY_MAPPING_L2I] = (early_mapping_l3_phys as u64) + assert_eq!(tables.kernel_l2.data[EARLY_MAPPING_L2I], 0); + tables.kernel_l2.data[EARLY_MAPPING_L2I] = (early_mapping_l3_phys as u64) | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); - assert_eq!(KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I], 0); - KERNEL_TABLES.kernel_l1.data[DEVICE_MAPPING_L1I] = (device_mapping_l2_phys as u64) + assert_eq!(tables.kernel_l1.data[DEVICE_MAPPING_L1I], 0); + tables.kernel_l1.data[DEVICE_MAPPING_L1I] = (device_mapping_l2_phys as u64) | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); - assert_eq!(KERNEL_TABLES.l0.data[RAM_MAPPING_L0I], 0); - KERNEL_TABLES.l0.data[RAM_MAPPING_L0I] = + assert_eq!(tables.l0.data[RAM_MAPPING_L0I], 0); + tables.l0.data[RAM_MAPPING_L0I] = (ram_mapping_l1_phys as u64) | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); // TODO ENABLE EFER.NXE - let cr3 = &raw const KERNEL_TABLES.l0 as usize - KERNEL_VIRT_OFFSET; + let cr3 = (&raw const tables.l0).addr() - KERNEL_VIRT_OFFSET; CR3.set_address(cr3); } diff --git a/kernel/libk/libk-mm/interface/src/address.rs b/kernel/libk/libk-mm/interface/src/address.rs index 30aaccbb..933e4c14 100644 --- a/kernel/libk/libk-mm/interface/src/address.rs +++ b/kernel/libk/libk-mm/interface/src/address.rs @@ -14,18 +14,6 @@ use kernel_arch_interface::mem::KernelTableManager; #[repr(transparent)] pub struct PhysicalAddress(pub(crate) u64); -// /// Interface for converting addresses from their raw values to more specific types -// pub trait FromRaw { -// /// Converts a raw value into the address wrapper type -// fn from_raw(value: T) -> Self; -// } -// -// /// Interface for converting wrapper types into their raw address representations -// pub trait IntoRaw { -// /// Converts a wrapper type value into its raw address -// fn into_raw(self) -> T; -// } - /// Interface for obtaining physical addresses of values pub trait AsPhysicalAddress { /// Returns the value's physical address. diff --git a/kernel/src/arch/i686/exception.rs b/kernel/src/arch/i686/exception.rs index 0a9c9fb1..3d6d6392 100644 --- a/kernel/src/arch/i686/exception.rs +++ b/kernel/src/arch/i686/exception.rs @@ -1,9 +1,10 @@ -use core::{arch::global_asm, ptr::addr_of}; +use core::arch::global_asm; use abi::{primitive_enum, process::Signal, SyscallFunction}; use kernel_arch_i686::context::{ExceptionFrame, SyscallFrame}; use kernel_arch_x86::registers::{CR2, CR3}; use libk::task::thread::Thread; +use libk_util::sync::spin_rwlock::IrqSafeRwLock; use tock_registers::interfaces::Readable; use crate::{arch::x86::peripherals::i8259, syscall}; @@ -147,7 +148,7 @@ impl Entry { } } -static mut IDT: [Entry; SIZE] = [Entry::NULL; SIZE]; +static IDT: IrqSafeRwLock<[Entry; SIZE]> = IrqSafeRwLock::new([Entry::NULL; SIZE]); fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) { let thread = Thread::current(); @@ -267,11 +268,13 @@ pub unsafe fn init_exceptions() { fn __i686_syscall_vector(); } + let mut idt = IDT.write(); + for (i, &entry) in __i686_exception_vectors.iter().enumerate() { - IDT[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32); + idt[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32); } - for entry in IDT.iter_mut().skip(32) { + for entry in idt.iter_mut().skip(32) { *entry = Entry::new( __i686_dummy_vector as usize, 0x08, @@ -279,17 +282,17 @@ pub unsafe fn init_exceptions() { ); } - i8259::setup_vectors(&mut IDT[32..]); + i8259::setup_vectors(&mut idt[32..]); - IDT[0x80] = Entry::new( + idt[0x80] = Entry::new( __i686_syscall_vector as usize, 0x08, Entry::PRESENT | Entry::INT32 | Entry::DPL3, ); let idtr = Pointer { - limit: (IDT.len() * size_of::()) as u16 - 1, - offset: addr_of!(IDT) as usize, + limit: (idt.len() * size_of::()) as u16 - 1, + offset: idt.as_ptr().addr(), }; core::arch::asm!("wbinvd; lidt ({0})", in(reg) &idtr, options(att_syntax)); diff --git a/kernel/src/arch/x86_64/exception.rs b/kernel/src/arch/x86_64/exception.rs index edec8d1d..5069cfea 100644 --- a/kernel/src/arch/x86_64/exception.rs +++ b/kernel/src/arch/x86_64/exception.rs @@ -1,10 +1,11 @@ //! x86-64 exception and interrupt handling -use core::{arch::global_asm, mem::size_of, ptr::addr_of}; +use core::{arch::global_asm, mem::size_of}; use abi::{primitive_enum, process::Signal}; use kernel_arch_x86::registers::{CR2, CR3}; use kernel_arch_x86_64::context::ExceptionFrame; use libk::{arch::Cpu, task::thread::Thread}; +use libk_util::sync::spin_rwlock::IrqSafeRwLock; use tock_registers::interfaces::Readable; use crate::arch::x86_64::apic; @@ -111,7 +112,7 @@ impl Entry { } } -static mut IDT: [Entry; SIZE] = [Entry::NULL; SIZE]; +static IDT: IrqSafeRwLock<[Entry; SIZE]> = IrqSafeRwLock::new([Entry::NULL; SIZE]); fn dump_user_exception(kind: ExceptionKind, frame: &ExceptionFrame) { let thread = Thread::current(); @@ -215,20 +216,22 @@ extern "C" fn __x86_64_exception_handler(frame: *mut ExceptionFrame) { /// Only meant to be called once per each CPU during their init. pub unsafe fn init_exceptions(cpu_index: usize) { if cpu_index == 0 { + let mut idt = IDT.write(); extern "C" { static __x86_64_exception_vectors: [usize; 32]; } for (i, &entry) in __x86_64_exception_vectors.iter().enumerate() { - IDT[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32); + idt[i] = Entry::new(entry, 0x08, Entry::PRESENT | Entry::INT32); } - apic::setup_vectors(&mut IDT[32..]); + apic::setup_vectors(&mut idt[32..]); } + let idt = IDT.read(); let idtr = Pointer { - limit: (IDT.len() * size_of::()) as u16 - 1, - offset: addr_of!(IDT) as usize, + limit: (idt.len() * size_of::()) as u16 - 1, + offset: idt.as_ptr().addr(), }; core::arch::asm!("wbinvd; lidt ({0})", in(reg) &idtr, options(att_syntax)); diff --git a/kernel/src/arch/x86_64/smp.rs b/kernel/src/arch/x86_64/smp.rs index 4c55d7ac..1db9567d 100644 --- a/kernel/src/arch/x86_64/smp.rs +++ b/kernel/src/arch/x86_64/smp.rs @@ -44,7 +44,7 @@ unsafe fn start_ap_core(apic_id: u32) { let bsp_cpu = Cpu::local(); let bsp_apic = bsp_cpu.local_apic(); - let cr3 = KERNEL_TABLES.as_physical_address(); + let cr3 = KERNEL_TABLES.lock().as_physical_address(); let stack_base = phys::alloc_pages_contiguous(AP_STACK_PAGES) .unwrap() .virtualize(); @@ -93,9 +93,12 @@ pub unsafe fn start_ap_cores(info: &ProcessorInfo) { PageEntry::::table(identity_l2.as_physical_address(), PageAttributes::WRITABLE); identity_l2[0] = PageEntry::::block(PhysicalAddress::ZERO, PageAttributes::WRITABLE); - assert_eq!(KERNEL_TABLES.l0.data[0], 0); - KERNEL_TABLES.l0.data[0] = identity_l1.as_physical_address().into_u64() - | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); + { + let mut tables = KERNEL_TABLES.lock(); + assert_eq!(tables.l0.data[0], 0); + tables.l0.data[0] = identity_l1.as_physical_address().into_u64() + | (PageAttributes::WRITABLE | PageAttributes::PRESENT).bits(); + } // Load AP_BOOTSTRAP_CODE let mut code_ref = PhysicalRefMut::map_slice(AP_BOOTSTRAP_CODE, AP_BOOTSTRAP_BIN.len()); @@ -110,7 +113,7 @@ pub unsafe fn start_ap_cores(info: &ProcessorInfo) { // Remove the identity-map identity_l2[0] = PageEntry::INVALID; flush_tlb_entry(0); - KERNEL_TABLES.l0.data[0] = 0; + KERNEL_TABLES.lock().l0.data[0] = 0; PageTable::free::(identity_l1); PageTable::free::(identity_l2); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 6de84ddd..c5953d66 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -33,8 +33,6 @@ #![deny(missing_docs)] #![no_std] #![no_main] -// XXX FIXME TODO -#![allow(static_mut_refs)] use arch::Platform; use kernel_arch::{Architecture, ArchitectureImpl};