//! Translation table. #[cfg(target_arch = "aarch64")] use crate::arch::aarch64::memory::mmu::translation_table as arch_translation_table; use { super::{AttributeFields, MemoryRegion}, crate::memory::{Address, Physical, Virtual}, }; //-------------------------------------------------------------------------------------------------- // Architectural Public Reexports //-------------------------------------------------------------------------------------------------- #[cfg(target_arch = "aarch64")] pub use arch_translation_table::FixedSizeTranslationTable; //-------------------------------------------------------------------------------------------------- // Public Definitions //-------------------------------------------------------------------------------------------------- /// Translation table interfaces. pub mod interface { use super::*; /// Translation table operations. pub trait TranslationTable { /// Anything that needs to run before any of the other provided functions can be used. /// /// # Safety /// /// - Implementor must ensure that this function can run only once or is harmless if invoked /// multiple times. fn init(&mut self); /// The translation table's base address to be used for programming the MMU. fn phys_base_address(&self) -> Address; /// Map the given virtual memory region to the given physical memory region. /// /// # Safety /// /// - Using wrong attributes can cause multiple issues of different nature in the system. /// - It is not required that the architectural implementation prevents aliasing. That is, /// mapping to the same physical memory using multiple virtual addresses, which would /// break Rust's ownership assumptions. This should be protected against in the kernel's /// generic MMU code. unsafe fn map_at( &mut self, virt_region: &MemoryRegion, phys_region: &MemoryRegion, attr: &AttributeFields, ) -> Result<(), &'static str>; } } //-------------------------------------------------------------------------------------------------- // Testing //-------------------------------------------------------------------------------------------------- #[cfg(test)] mod tests { use { super::*, crate::memory::mmu::{AccessPermissions, MemAttributes, PageAddress}, arch_translation_table::MinSizeTranslationTable, interface::TranslationTable, }; /// Sanity checks for the TranslationTable implementation. #[test_case] fn translation_table_implementation_sanity() { // This will occupy a lot of space on the stack. let mut tables = MinSizeTranslationTable::new(); tables.init(); let virt_start_page_addr: PageAddress = PageAddress::from(0); let virt_end_exclusive_page_addr: PageAddress = virt_start_page_addr.checked_offset(5).unwrap(); let phys_start_page_addr: PageAddress = PageAddress::from(0); let phys_end_exclusive_page_addr: PageAddress = phys_start_page_addr.checked_offset(5).unwrap(); let virt_region = MemoryRegion::new(virt_start_page_addr, virt_end_exclusive_page_addr); let phys_region = MemoryRegion::new(phys_start_page_addr, phys_end_exclusive_page_addr); let attr = AttributeFields { mem_attributes: MemAttributes::CacheableDRAM, acc_perms: AccessPermissions::ReadWrite, execute_never: true, }; unsafe { assert_eq!(tables.map_at(&virt_region, &phys_region, &attr), Ok(())) }; } }