diff --git a/kernel/src/cpu/paging.rs b/kernel/src/cpu/paging.rs index 38d1ea3..e03771c 100644 --- a/kernel/src/cpu/paging.rs +++ b/kernel/src/cpu/paging.rs @@ -1,5 +1,6 @@ use core::{ arch::asm, + cell::OnceCell, panic, sync::atomic::{AtomicBool, AtomicU64, Ordering}, }; @@ -12,7 +13,7 @@ use kernel_common::{ }; use log::info; -use crate::sys::{locks::Spinlock, smp::smp_invalidate_tlb}; +use crate::sys::{locks::Spinlock, process::get_kernel_process, smp::smp_invalidate_tlb}; extern "C" { static _text_start: u8; @@ -26,13 +27,12 @@ extern "C" { } pub struct AddressSpace { - pub pml4: Option>, + pub pml4: OnceCell>, } static PAGING_ACTIVE: AtomicBool = AtomicBool::new(false); -pub static CURRENT_ADDRESS_SPACE: Spinlock = Spinlock::new(AddressSpace { pml4: None }); static HEAP_PHYS_START: AtomicU64 = AtomicU64::new(0); -static PHYSICAL_FRAMES: Spinlock>> = Spinlock::new(None); +static PHYSICAL_FRAMES: Spinlock>> = Spinlock::new(OnceCell::new()); static HEAP_PHYS_MAPPING: Spinlock> = Spinlock::new(Vec::new()); const KERNEL_MAPPINGS_START: u64 = 0xfffffffd00000000; const KERNEL_MAPPINGS_END: u64 = 0xfffffffe00000000; @@ -44,7 +44,7 @@ impl AddressSpace { let directory_i = virt_page / 512 % 512; let pdpt_i = virt_page / 512 / 512 % 512; let pml4_i = virt_page / 512 / 512 / 512 % 512; - let pdpt = &mut self.pml4.as_mut().unwrap().entries_virt[pml4_i]; + let pdpt = &mut self.pml4.get_mut().unwrap().entries_virt[pml4_i]; if let Some(pdpt) = pdpt { let directory = &mut pdpt.entries_virt[pdpt_i]; if let Some(directory) = directory { @@ -84,8 +84,8 @@ impl AddressSpace { { let mut frames_vec = PHYSICAL_FRAMES.lock(); let frame = phys as usize / 0x1000; - if frame < frames_vec.as_ref().unwrap().len() { - frames_vec.as_mut().unwrap().set(frame, true); + if frame < frames_vec.get().unwrap().len() { + frames_vec.get_mut().unwrap().set(frame, true); } } let virt_page = virt as usize / 0x1000; @@ -93,7 +93,7 @@ impl AddressSpace { let directory_i = virt_page / 512 % 512; let pdpt_i = virt_page / 512 / 512 % 512; let pml4_i = virt_page / 512 / 512 / 512 % 512; - let pdpt = get_table_entry(self.pml4.as_mut().unwrap(), pml4_i); + let pdpt = get_table_entry(self.pml4.get_mut().unwrap(), pml4_i); let directory = get_table_entry(pdpt, pdpt_i); let table = get_table_entry(directory, directory_i); let should_invalidate = table.entries_phys[table_i].present() == 1; @@ -151,8 +151,9 @@ impl AddressSpace { fn _get_free_frame() -> u64 { let frames_vec = PHYSICAL_FRAMES.lock(); - for i in 0..frames_vec.as_ref().unwrap().len() { - if !frames_vec.as_ref().unwrap()[i] { + let frames_vec = frames_vec.get().unwrap(); + for i in 0..frames_vec.len() { + if !frames_vec[i] { return i as u64; } } @@ -198,8 +199,8 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u info!("Memory size: {} MB", memory_size * 0x1000 / 1024 / 1024); { let mut frames_vec = PHYSICAL_FRAMES.lock(); - *frames_vec = Some(BitVec::::repeat(true, memory_size as usize)); - let frames_vec = frames_vec.as_mut().unwrap(); + frames_vec.set(BitVec::::repeat(true, memory_size as usize)).unwrap_or_else(|_| panic!()); + let frames_vec = frames_vec.get_mut().unwrap(); for i in &loader_struct.available_memory { for j in 0..i.page_count { let page = i.initial_page + j; @@ -227,12 +228,17 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u bss_start = &_bss_start as *const u8 as u64 / 0x1000; bss_end = (&_bss_end as *const u8 as u64 + 0xfff) / 0x1000; } - let mut address_space = CURRENT_ADDRESS_SPACE.lock(); - address_space.pml4 = Some(Box::new(PageTable { - entries_phys: [PageEntry(0); 512], - entries_virt: [const { None }; 512], - })); - let pml4 = address_space.pml4.as_mut().unwrap(); + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + let address_space = &mut kernel_proc.address_space; + address_space + .pml4 + .set(Box::new(PageTable { + entries_phys: [PageEntry(0); 512], + entries_virt: [const { None }; 512], + })) + .unwrap_or_else(|_| panic!()); + let pml4 = address_space.pml4.get_mut().unwrap(); let pml4_address = pml4.as_ref() as *const PageTable as u64; for i in 256..512 { get_table_entry(pml4, i); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 9999802..32cbc26 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -116,7 +116,7 @@ fn panic(info: &PanicInfo) -> ! { error!("{}", info); let str = format!("{}", info); let mut display = PANIC_DISPLAY.lock(); - if let Some(display) = display.as_mut() { + if let Some(display) = display.get_mut() { display.clear(); display.print(&str); } diff --git a/kernel/src/misc/display.rs b/kernel/src/misc/display.rs index 3617aef..5e93a8a 100644 --- a/kernel/src/misc/display.rs +++ b/kernel/src/misc/display.rs @@ -1,3 +1,5 @@ +use core::cell::OnceCell; + use alloc::{string::ToString, vec}; use embedded_graphics::{ mono_font::{iso_8859_13::FONT_10X20, MonoTextStyle}, @@ -7,7 +9,10 @@ use embedded_graphics::{ }; use kernel_common::loader_struct::FramebufferInfo; -use crate::{cpu::paging::CURRENT_ADDRESS_SPACE, misc::draw_target::FramebufferTarget, sys::locks::Spinlock}; +use crate::{ + misc::draw_target::FramebufferTarget, + sys::{locks::Spinlock, process::get_kernel_process}, +}; pub struct Display { framebuffer: FramebufferTarget, @@ -19,8 +24,8 @@ pub struct Display { } //TODO: Change to mutex -pub static DISPLAY: Spinlock> = Spinlock::new(None); -pub static PANIC_DISPLAY: Spinlock> = Spinlock::new(None); +pub static DISPLAY: Spinlock> = Spinlock::new(OnceCell::new()); +pub static PANIC_DISPLAY: Spinlock> = Spinlock::new(OnceCell::new()); impl Display { fn write_char(&mut self, x: usize, y: usize, c: char) { @@ -71,7 +76,12 @@ impl Display { } } pub fn setup_display(info: FramebufferInfo) { - let addr = unsafe { CURRENT_ADDRESS_SPACE.lock().map_physical(info.address, info.height * info.stride * 4, true) }; + let addr; + { + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + addr = unsafe { kernel_proc.address_space.map_physical(info.address, info.height * info.stride * 4, true) }; + } let fb = vec![0; info.height as usize * info.stride as usize * 4]; let display = Display { framebuffer: FramebufferTarget { @@ -86,7 +96,7 @@ pub fn setup_display(info: FramebufferInfo) { current_x: 0, current_y: 0, }; - *PANIC_DISPLAY.lock() = Some(display); + PANIC_DISPLAY.lock().set(display).unwrap_or_else(|_| panic!()); let fb = vec![0; info.height as usize * info.stride as usize * 4]; let display = Display { framebuffer: FramebufferTarget { @@ -101,5 +111,5 @@ pub fn setup_display(info: FramebufferInfo) { current_x: 0, current_y: 0, }; - *DISPLAY.lock() = Some(display); + DISPLAY.lock().set(display).unwrap_or_else(|_| panic!()); } diff --git a/kernel/src/sys/acpica_osl.rs b/kernel/src/sys/acpica_osl.rs index d129b87..adaa7bb 100644 --- a/kernel/src/sys/acpica_osl.rs +++ b/kernel/src/sys/acpica_osl.rs @@ -13,7 +13,6 @@ use kernel_common::{ }; use crate::{ - cpu::paging::CURRENT_ADDRESS_SPACE, misc::wrapped_alloc::{wrapped_alloc, wrapped_dealloc}, sys::ioapic::{register_irq_handler, set_irq_override}, RSDP_ADDRESS, @@ -26,6 +25,7 @@ use super::{ hpet::get_current_time, lapic::get_current_lapic_id, locks::Spinlock, + process::get_kernel_process, sync::{create_semaphore, lock_semaphore, unlock_semaphore, RawSemaphore, RawSpinlock}, task::{CURRENT_TASKS, MULTITASKING_ENABLED}, }; @@ -117,7 +117,9 @@ extern "C" fn AcpiOsInstallInterruptHandler(gsi: UINT32, handler: ACPI_OSD_HANDL } #[no_mangle] extern "C" fn AcpiOsMapMemory(phys: ACPI_PHYSICAL_ADDRESS, size: ACPI_SIZE) -> *mut c_void { - unsafe { CURRENT_ADDRESS_SPACE.lock().map_physical(phys, size, false) as *mut c_void } + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + unsafe { kernel_proc.address_space.map_physical(phys, size, false) as *mut c_void } } #[no_mangle] extern "C" fn AcpiOsPhysicalTableOverride(_existing: *mut ACPI_TABLE_HEADER, new_address: *mut ACPI_PHYSICAL_ADDRESS, new_length: *mut UINT32) -> ACPI_STATUS { @@ -199,8 +201,10 @@ extern "C" fn AcpiOsTerminate() -> ACPI_STATUS { } #[no_mangle] extern "C" fn AcpiOsUnmapMemory(address: *mut c_void, size: ACPI_SIZE) { + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); unsafe { - CURRENT_ADDRESS_SPACE.lock().unmap_physical(address as u64, size); + kernel_proc.address_space.unmap_physical(address as u64, size); } } #[no_mangle] diff --git a/kernel/src/sys/early_acpi.rs b/kernel/src/sys/early_acpi.rs index da0b02f..343379d 100644 --- a/kernel/src/sys/early_acpi.rs +++ b/kernel/src/sys/early_acpi.rs @@ -2,21 +2,25 @@ use core::ptr::NonNull; use acpi::{AcpiHandler, PhysicalMapping}; -use crate::cpu::paging::CURRENT_ADDRESS_SPACE; +use super::process::get_kernel_process; #[derive(Clone, Copy)] pub struct EarlyACPIHandler {} impl AcpiHandler for EarlyACPIHandler { unsafe fn map_physical_region(&self, phys: usize, size: usize) -> PhysicalMapping { + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); unsafe { - let virt = CURRENT_ADDRESS_SPACE.lock().map_physical(phys as u64, size as u64, false); + let virt = kernel_proc.address_space.map_physical(phys as u64, size as u64, false); PhysicalMapping::new(phys, NonNull::new(virt as *mut T).unwrap(), size, size, *self) } } fn unmap_physical_region(region: &PhysicalMapping) { + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); unsafe { - CURRENT_ADDRESS_SPACE.lock().unmap_physical(region.virtual_start().as_ptr() as u64, region.mapped_length() as u64); + kernel_proc.address_space.unmap_physical(region.virtual_start().as_ptr() as u64, region.mapped_length() as u64); } } } diff --git a/kernel/src/sys/hpet.rs b/kernel/src/sys/hpet.rs index 96f18e1..f10b97e 100644 --- a/kernel/src/sys/hpet.rs +++ b/kernel/src/sys/hpet.rs @@ -7,13 +7,12 @@ use acpi::{AcpiTables, HpetInfo}; use alloc::vec::Vec; use kernel_common::instructions::pause; -use crate::cpu::paging::CURRENT_ADDRESS_SPACE; - use super::{ early_acpi::EarlyACPIHandler, ioapic::register_irq_handler, lapic::get_current_lapic_id, locks::Spinlock, + process::get_kernel_process, scheduler::{yield_task, SCHEDULER}, task::{Task, TaskState, CURRENT_TASKS, MULTITASKING_ENABLED}, }; @@ -118,7 +117,12 @@ pub fn sleep_internal(task: Task) { } pub fn setup_hpet(tables: &AcpiTables) { let hpet_info = HpetInfo::new(tables).unwrap(); - let address = unsafe { CURRENT_ADDRESS_SPACE.lock().map_physical(hpet_info.base_address as u64, 0x200, false) } as *mut u64; + let address; + { + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + address = unsafe { kernel_proc.address_space.map_physical(hpet_info.base_address as u64, 0x200, false) } as *mut u64; + } ADDRESS.store(address, Ordering::SeqCst); let period = unsafe { address.add(REGISTER_CAPABILITIES).read_volatile() >> 32 } as usize; PERIOD.store(period, Ordering::SeqCst); diff --git a/kernel/src/sys/ioapic.rs b/kernel/src/sys/ioapic.rs index 3e2dea9..bd969af 100644 --- a/kernel/src/sys/ioapic.rs +++ b/kernel/src/sys/ioapic.rs @@ -6,8 +6,8 @@ use core::{ use bitfield::bitfield; use crate::{ - cpu::{isr::ISR_HANDLERS, paging::CURRENT_ADDRESS_SPACE}, - sys::lapic::BSP_LAPIC_ID, + cpu::isr::ISR_HANDLERS, + sys::{lapic::BSP_LAPIC_ID, process::get_kernel_process}, }; struct IOAPIC { @@ -98,7 +98,12 @@ pub fn register_irq_handler(vector: usize, handler: fn()) { } } pub fn setup_ioapic(phys: u64, gsi_base: usize) { - let address = unsafe { CURRENT_ADDRESS_SPACE.lock().map_physical(phys, 0x14, false) as *mut u32 }; + let address; + { + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + address = unsafe { kernel_proc.address_space.map_physical(phys, 0x14, false) as *mut u32 }; + } let next_id = NEXT_IOAPIC_ID.fetch_add(1, Ordering::SeqCst); IOAPICS[next_id].address.store(address, Ordering::SeqCst); IOAPICS[next_id].start_gsi.store(gsi_base, Ordering::SeqCst); diff --git a/kernel/src/sys/lapic.rs b/kernel/src/sys/lapic.rs index 4c0bf0c..c0355f9 100644 --- a/kernel/src/sys/lapic.rs +++ b/kernel/src/sys/lapic.rs @@ -5,9 +5,9 @@ use core::{ use kernel_common::instructions::get_rflags; -use crate::cpu::{isr::ISR_SCHEDULER, paging::CURRENT_ADDRESS_SPACE}; +use crate::cpu::isr::ISR_SCHEDULER; -use super::hpet::sleep; +use super::{hpet::sleep, process::get_kernel_process}; pub struct LAPIC { pub lapic_id: AtomicUsize, @@ -49,7 +49,9 @@ pub fn get_current_lapic_id() -> usize { } pub fn setup_lapic(phys: u64) { if phys != 0 { - let address = unsafe { CURRENT_ADDRESS_SPACE.lock().map_physical(phys, 0x400, false) as *mut u32 }; + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + let address = unsafe { kernel_proc.address_space.map_physical(phys, 0x400, false) as *mut u32 }; ADDRESS.store(address, Ordering::SeqCst); BSP_LAPIC_ID.store(get_current_lapic_id(), Ordering::SeqCst); } diff --git a/kernel/src/sys/mod.rs b/kernel/src/sys/mod.rs index bf363c6..4edbffd 100644 --- a/kernel/src/sys/mod.rs +++ b/kernel/src/sys/mod.rs @@ -6,6 +6,7 @@ pub mod lapic; pub mod locks; pub mod madt; pub mod pic; +pub mod process; pub mod scheduler; pub mod smp; pub mod sync; diff --git a/kernel/src/sys/process.rs b/kernel/src/sys/process.rs new file mode 100644 index 0000000..aeda292 --- /dev/null +++ b/kernel/src/sys/process.rs @@ -0,0 +1,22 @@ +use core::cell::{LazyCell, OnceCell}; + +use alloc::sync::Arc; + +use crate::cpu::paging::AddressSpace; + +use super::locks::Spinlock; + +pub struct Process { + pub address_space: AddressSpace, +} + +static KERNEL_PROCESS: Spinlock>>> = Spinlock::new(LazyCell::new(|| { + let process = Process { + address_space: AddressSpace { pml4: OnceCell::new() }, + }; + Arc::new(Spinlock::new(process)) +})); + +pub fn get_kernel_process() -> Arc> { + KERNEL_PROCESS.lock().clone() +} diff --git a/kernel/src/sys/smp.rs b/kernel/src/sys/smp.rs index b5a7496..2b386b3 100644 --- a/kernel/src/sys/smp.rs +++ b/kernel/src/sys/smp.rs @@ -4,16 +4,14 @@ use alloc::{vec, vec::Vec}; use kernel_common::{instructions::pause, paging::PageTable}; use crate::{ - cpu::{ - isr::ISR_INVALIDATE_TLB, - paging::{virt_to_phys, CURRENT_ADDRESS_SPACE}, - }, + cpu::{isr::ISR_INVALIDATE_TLB, paging::virt_to_phys}, BROADCASTED_PANIC, }; use super::{ hpet::sleep, lapic::{get_current_lapic_id, send_ipi, BSP_LAPIC_ID, LAPICS, NEXT_LAPIC_ID}, + process::get_kernel_process, sync::RawSpinlock, task::{ALL_APS_STARTED, STACK_SIZE, STARTING_AP_ID}, }; @@ -34,9 +32,11 @@ pub fn start_aps() { let stack: Vec = vec![0; STACK_SIZE]; let pml4_phys_addr; { - let mut address_space = CURRENT_ADDRESS_SPACE.lock(); + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + let address_space = &mut kernel_proc.address_space; let pml4 = &address_space.pml4; - let pml4_phys_addr_u64 = virt_to_phys(pml4.as_ref().unwrap().as_ref() as *const PageTable as u64); + let pml4_phys_addr_u64 = virt_to_phys(pml4.get().unwrap().as_ref() as *const PageTable as u64); pml4_phys_addr = u32::try_from(pml4_phys_addr_u64).unwrap(); unsafe { address_space.map_range(0x1000, 0x1000, 0x1000, false, true, false, false); @@ -67,7 +67,9 @@ pub fn start_aps() { } ALL_APS_STARTED.store(true, Ordering::SeqCst); unsafe { - CURRENT_ADDRESS_SPACE.lock().unmap(0x1000); + let kernel_proc = get_kernel_process(); + let mut kernel_proc = kernel_proc.lock(); + kernel_proc.address_space.unmap(0x1000); } } pub fn smp_invalidate_tlb() { diff --git a/kernel/src/sys/task.rs b/kernel/src/sys/task.rs index bf65d1e..510d238 100644 --- a/kernel/src/sys/task.rs +++ b/kernel/src/sys/task.rs @@ -16,6 +16,7 @@ use super::{ hpet::sleep_internal, lapic::{get_current_lapic_id, schedule_timer_interrupt}, locks::Spinlock, + process::{get_kernel_process, Process}, scheduler::yield_task, sync::{lock_semaphore_internal, RawSemaphore}, }; @@ -31,6 +32,7 @@ pub enum TaskState { pub struct Task { pub id: usize, + _process: Arc>, state: ISRState, _kernel_stack: Vec, initial_func: fn(), @@ -70,10 +72,11 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) { _current_task[get_current_lapic_id()] = Some(new_task); schedule_timer_interrupt(); } -pub fn create_task(func: fn()) -> Task { +pub fn create_task(process: Arc>, func: fn()) -> Task { let stack = vec![0; STACK_SIZE]; Task { id: NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst), + _process: process, state: ISRState { rax: 0, rbx: 0, @@ -107,7 +110,8 @@ pub fn create_task(func: fn()) -> Task { } } fn create_idle_task() { - let mut idle_task = create_task(idle_main); + let kernel_proc = get_kernel_process(); + let mut idle_task = create_task(kernel_proc, idle_main); idle_task.task_state = TaskState::Idle; { IDLE_TASKS.lock().push(idle_task); @@ -147,7 +151,11 @@ pub fn setup_multitasking() -> ! { for _ in 0..NEXT_LAPIC_ID.load(Ordering::SeqCst) { create_idle_task(); } - let task = create_task(main); + let task; + { + let kernel_proc = get_kernel_process(); + task = create_task(kernel_proc, main); + } SCHEDULER.lock().add_task(task); MULTITASKING_ENABLED.store(true, Ordering::SeqCst); yield_task();