#[cfg(target_arch = "aarch64")]
#[path = "../../_arch/aarch64/memory/mmu/translation_table.rs"]
mod arch_translation_table;
use super::super::super::memory::{Address, Physical, Virtual};
use super::{AttributeFields, MemoryRegion};
#[cfg(target_arch = "aarch64")]
pub use arch_translation_table::FixedSizeTranslationTable;
pub mod interface
{
use crate::systems::rpi::memory::mmu::PageAddress;
use super::*;
pub trait TranslationTable
{
fn init(&mut self) -> Result<(), &'static str>;
unsafe fn map_at(
&mut self,
virt_region: &MemoryRegion<Virtual>,
phys_region: &MemoryRegion<Physical>,
attr: &AttributeFields,
) -> Result<(), &'static str>;
fn try_virt_page_addr_to_phys_page_addr(
&self,
virt_page_addr: PageAddress<Virtual>,
) -> Result<PageAddress<Physical>, &'static str>;
fn try_page_attributes(
&self,
virt_page_addr: PageAddress<Virtual>,
) -> Result<AttributeFields, &'static str>;
fn try_virt_addr_to_phys_addr(
&self,
virt_addr: Address<Virtual>,
) -> Result<Address<Physical>, &'static str>;
}
}
#[cfg(test)]
mod tests
{
use super::*;
use crate::memory::mmu::{AccessPermissions, MemAttributes, PageAddress};
use arch_translation_table::MinSizeTranslationTable;
use interface::TranslationTable;
#[test_case]
fn translationtable_implementation_sanity()
{
let mut tables = MinSizeTranslationTable::new_for_runtime();
assert_eq!(tables.init(), Ok(()));
let virt_end_exclusive_page_addr: PageAddress<Virtual> = PageAddress::MAX;
let virt_start_page_addr: PageAddress<Virtual> =
virt_end_exclusive_page_addr.checked_offset(-5).unwrap();
let phys_start_page_addr: PageAddress<Physical> = PageAddress::from(0);
let phys_end_exclusive_page_addr: PageAddress<Physical> =
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(())) };
assert_eq!(
tables.try_virt_page_addr_to_phys_page_addr(virt_start_page_addr),
Ok(phys_start_page_addr)
);
assert_eq!(
tables.try_page_attributes(virt_start_page_addr.checked_offset(-1).unwrap()),
Err("Page marked invalid")
);
assert_eq!(tables.try_page_attributes(virt_start_page_addr), Ok(attr));
let virt_addr = virt_start_page_addr.into_inner() + 0x100;
let phys_addr = phys_start_page_addr.into_inner() + 0x100;
assert_eq!(tables.try_virt_addr_to_phys_addr(virt_addr), Ok(phys_addr));
}
}