diff --git a/src/acpi/mod.rs b/src/acpi/mod.rs index 990bf045c6..34125f31b4 100644 --- a/src/acpi/mod.rs +++ b/src/acpi/mod.rs @@ -8,7 +8,10 @@ use alloc::{boxed::Box, string::String, vec::Vec}; use hashbrown::HashMap; use spin::{Once, RwLock}; -use crate::memory::{KernelMapper, PageFlags, PhysicalAddress, RmmA, RmmArch}; +use crate::{ + acpi::rxsdt::RxsdtIter, + memory::{KernelMapper, PageFlags, PhysicalAddress, RmmA, RmmArch}, +}; use self::{hpet::Hpet, madt::Madt, rsdp::Rsdp, rsdt::Rsdt, rxsdt::Rxsdt, sdt::Sdt, xsdt::Xsdt}; @@ -78,24 +81,20 @@ pub enum RxsdtEnum { Xsdt(Xsdt), } impl Rxsdt for RxsdtEnum { - fn iter(&self) -> Box> { + fn iter(&self) -> RxsdtIter { match self { - Self::Rsdt(rsdt) => ::iter(rsdt), - Self::Xsdt(xsdt) => ::iter(xsdt), + Self::Rsdt(rsdt) => rsdt.iter(), + Self::Xsdt(xsdt) => xsdt.iter(), } } } pub static RXSDT_ENUM: Once = Once::new(); -/// Parse the ACPI tables to gather CPU, interrupt, and timer information -pub unsafe fn init(already_supplied_rsdp: Option>) { +/// Initialses the global `RXSDT_ENUM` if RSDT or XSDT was found and maps the SDT pages. +/// It does not perform any allocations +pub unsafe fn init_before_mem(already_supplied_rsdp: Option>) { unsafe { - { - let mut sdt_ptrs = SDT_POINTERS.write(); - *sdt_ptrs = Some(HashMap::new()); - } - // Search for RSDP let rsdp_opt = Rsdp::get_rsdp(already_supplied_rsdp); @@ -140,6 +139,22 @@ pub unsafe fn init(already_supplied_rsdp: Option>) { for sdt in rxsdt.iter() { get_sdt(sdt, &mut KernelMapper::lock_rw()); } + } else { + error!("NO RSDP FOUND"); + return; + } + } +} + +/// Parse the ACPI tables to gather CPU, interrupt, and timer information. The code performs allocations, so +/// it must be called only after the allocator is set up. +pub unsafe fn init_after_mem(already_supplied_rsdp: Option>) { + if let Some(rxsdt) = RXSDT_ENUM.get() { + unsafe { + { + let mut sdt_ptrs = SDT_POINTERS.write(); + *sdt_ptrs = Some(HashMap::new()); + } for sdt_address in rxsdt.iter() { let sdt = &*(RmmA::phys_to_virt(sdt_address).data() as *const Sdt); @@ -162,8 +177,6 @@ pub unsafe fn init(already_supplied_rsdp: Option>) { Hpet::init(); #[cfg(target_arch = "aarch64")] gtdt::Gtdt::init(); - } else { - error!("NO RSDP FOUND"); } } } diff --git a/src/acpi/rsdt.rs b/src/acpi/rsdt.rs index e5e7d54428..c4031f7d1a 100644 --- a/src/acpi/rsdt.rs +++ b/src/acpi/rsdt.rs @@ -2,6 +2,8 @@ use alloc::boxed::Box; use core::convert::TryFrom; use rmm::PhysicalAddress; +use crate::acpi::rxsdt::RxsdtIter; + use super::{rxsdt::Rxsdt, sdt::Sdt}; #[derive(Debug)] @@ -24,29 +26,7 @@ impl Rsdt { } impl Rxsdt for Rsdt { - fn iter(&self) -> Box> { - Box::new(RsdtIter { sdt: self.0, i: 0 }) - } -} - -pub struct RsdtIter { - sdt: &'static Sdt, - i: usize, -} - -impl Iterator for RsdtIter { - type Item = PhysicalAddress; - fn next(&mut self) -> Option { - if self.i < self.sdt.data_len() / size_of::() { - let item = unsafe { - (self.sdt.data_address() as *const u32) - .add(self.i) - .read_unaligned() - }; - self.i += 1; - Some(PhysicalAddress::new(item as usize)) - } else { - None - } + fn iter(&self) -> RxsdtIter { + RxsdtIter { sdt: self.0, i: 0 } } } diff --git a/src/acpi/rxsdt.rs b/src/acpi/rxsdt.rs index a4bc6c967f..8969200579 100644 --- a/src/acpi/rxsdt.rs +++ b/src/acpi/rxsdt.rs @@ -1,6 +1,28 @@ use alloc::boxed::Box; use rmm::PhysicalAddress; +use crate::acpi::sdt::Sdt; + pub trait Rxsdt { - fn iter(&self) -> Box>; + fn iter(&self) -> RxsdtIter; +} + +pub struct RxsdtIter { + pub sdt: &'static Sdt, + pub i: usize, +} + +impl Iterator for RxsdtIter { + type Item = PhysicalAddress; + fn next(&mut self) -> Option { + if self.i < self.sdt.data_len() / size_of::() { + let item = unsafe { + core::ptr::read_unaligned((self.sdt.data_address() as *const u64).add(self.i)) + }; + self.i += 1; + Some(PhysicalAddress::new(item as usize)) + } else { + None + } + } } diff --git a/src/acpi/xsdt.rs b/src/acpi/xsdt.rs index bb59065e52..c9ac11d98e 100644 --- a/src/acpi/xsdt.rs +++ b/src/acpi/xsdt.rs @@ -2,6 +2,8 @@ use alloc::boxed::Box; use core::convert::TryFrom; use rmm::PhysicalAddress; +use crate::acpi::rxsdt::RxsdtIter; + use super::{rxsdt::Rxsdt, sdt::Sdt}; #[derive(Debug)] @@ -24,27 +26,7 @@ impl Xsdt { } impl Rxsdt for Xsdt { - fn iter(&self) -> Box> { - Box::new(XsdtIter { sdt: self.0, i: 0 }) - } -} - -pub struct XsdtIter { - sdt: &'static Sdt, - i: usize, -} - -impl Iterator for XsdtIter { - type Item = PhysicalAddress; - fn next(&mut self) -> Option { - if self.i < self.sdt.data_len() / size_of::() { - let item = unsafe { - core::ptr::read_unaligned((self.sdt.data_address() as *const u64).add(self.i)) - }; - self.i += 1; - Some(PhysicalAddress::new(item as usize)) - } else { - None - } + fn iter(&self) -> RxsdtIter { + RxsdtIter { sdt: self.0, i: 0 } } } diff --git a/src/arch/x86_shared/start.rs b/src/arch/x86_shared/start.rs index 7a7c0ae815..7c4ff43133 100644 --- a/src/arch/x86_shared/start.rs +++ b/src/arch/x86_shared/start.rs @@ -102,13 +102,20 @@ unsafe extern "C" fn start(args_ptr: *const KernelArgs, stack_end: usize) -> ! { // Initialize RMM #[cfg(target_arch = "x86")] - crate::startup::memory::init(&args, Some(0x100000), Some(0x40000000)); + let bump_allocator = + crate::startup::memory::init(&args, Some(0x100000), Some(0x40000000)); #[cfg(target_arch = "x86_64")] - crate::startup::memory::init(&args, Some(0x100000), None); + let bump_allocator = crate::startup::memory::init(&args, Some(0x100000), None); // Initialize paging paging::init(); + if cfg!(feature = "acpi") { + crate::acpi::init_before_mem(args.acpi_rsdp()); + } + + crate::memory::init_mm(bump_allocator); + #[cfg(target_arch = "x86_64")] crate::arch::alternative::early_init(true); @@ -130,7 +137,7 @@ unsafe extern "C" fn start(args_ptr: *const KernelArgs, stack_end: usize) -> ! { // Read ACPI tables, starts APs if cfg!(feature = "acpi") { - crate::acpi::init(args.acpi_rsdp()); + crate::acpi::init_after_mem(args.acpi_rsdp()); device::init_after_acpi(); } crate::profiling::init(); diff --git a/src/startup/memory.rs b/src/startup/memory.rs index 26922dde0a..6a19d90719 100644 --- a/src/startup/memory.rs +++ b/src/startup/memory.rs @@ -394,7 +394,11 @@ unsafe fn map_memory(areas: &[MemoryArea], mut bump_allocator: &mut Bum } } -pub unsafe fn init(args: &KernelArgs, low_limit: Option, high_limit: Option) { +pub unsafe fn init( + args: &KernelArgs, + low_limit: Option, + high_limit: Option, +) -> BumpAllocator { register_memory_from_kernel_args(args); unsafe { @@ -441,7 +445,6 @@ pub unsafe fn init(args: &KernelArgs, low_limit: Option, high_limit: Opti // Create the physical memory map let offset = bump_allocator.offset(); info!("Permanently used: {} KB", offset.div_ceil(KILOBYTE)); - - crate::memory::init_mm(bump_allocator); + bump_allocator } }