diff --git a/ostd/src/arch/riscv/io.rs b/ostd/src/arch/riscv/io.rs new file mode 100644 index 000000000..660f0a1bb --- /dev/null +++ b/ostd/src/arch/riscv/io.rs @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MPL-2.0 + +use alloc::vec::Vec; + +use crate::{boot::memory_region::MemoryRegionType, io::IoMemAllocatorBuilder}; + +/// Initializes the allocatable MMIO area based on the RISC-V memory +/// distribution map. +/// +/// Here we consider all the holes (filtering usable RAM) in the physical +/// address space as MMIO regions. +pub(super) fn construct_io_mem_allocator_builder() -> IoMemAllocatorBuilder { + let regions = &crate::boot::EARLY_INFO.get().unwrap().memory_regions; + let mut reserved_filter = regions.iter().filter(|r| { + r.typ() != MemoryRegionType::Unknown + && r.typ() != MemoryRegionType::Reserved + && r.typ() != MemoryRegionType::Framebuffer + }); + + let mut ranges = Vec::new(); + + let mut current_address = 0; + for region in reserved_filter { + if current_address < region.base() { + ranges.push(current_address..region.base()); + } + current_address = region.end(); + } + if current_address < usize::MAX { + ranges.push(current_address..usize::MAX); + } + + // SAFETY: The range is guaranteed not to access physical memory. + unsafe { IoMemAllocatorBuilder::new(ranges) } +} diff --git a/ostd/src/arch/riscv/mod.rs b/ostd/src/arch/riscv/mod.rs index 178ab313c..507f60213 100644 --- a/ostd/src/arch/riscv/mod.rs +++ b/ostd/src/arch/riscv/mod.rs @@ -5,6 +5,7 @@ pub mod boot; pub(crate) mod cpu; pub mod device; +mod io; pub(crate) mod iommu; pub(crate) mod irq; pub(crate) mod mm; @@ -24,6 +25,8 @@ pub(crate) unsafe fn late_init_on_bsp() { // SAFETY: This function is called in the boot context of the BSP. unsafe { trap::init() }; + let io_mem_builder = io::construct_io_mem_allocator_builder(); + // SAFETY: We're on the BSP and we're ready to boot all APs. unsafe { crate::boot::smp::boot_all_aps() }; @@ -32,6 +35,11 @@ pub(crate) unsafe fn late_init_on_bsp() { // been performed. unsafe { timer::init() }; let _ = pci::init(); + + // SAFETY: + // 1. All the system device memory have been removed from the builder. + // 2. RISC-V platforms do not have port I/O. + unsafe { crate::io::init(io_mem_builder) }; } pub(crate) unsafe fn init_on_ap() {