#[cfg(feature = "uspace")]
pub use crate::arch::current::asm::install_user_address_space;
pub use crate::arch::current::asm::{
address_space_tag_capacity, flush_tlb, read_kernel_page_table, read_user_page_table,
write_kernel_page_table, write_user_page_table,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct HardwareAddressSpace {
root: ax_memory_addr::PhysAddr,
tag: u16,
}
impl HardwareAddressSpace {
pub const fn new(root: ax_memory_addr::PhysAddr, tag: u16) -> Self {
Self { root, tag }
}
pub const fn root(self) -> ax_memory_addr::PhysAddr {
self.root
}
pub const fn hardware_tag(self) -> u16 {
self.tag
}
}
pub fn flush_tlb_range(start: crate::VirtAddr, size: usize) {
flush_range_with(start, size, flush_tlb);
}
pub(crate) fn flush_range_with(
start: crate::VirtAddr,
size: usize,
flush_tlb: impl Fn(Option<crate::VirtAddr>),
) {
if size == 0 {
return;
}
struct RestoreIrqs(bool);
impl Drop for RestoreIrqs {
fn drop(&mut self) {
if self.0 {
crate::interrupt::enable_irqs();
}
}
}
let _restore = RestoreIrqs(crate::interrupt::irqs_enabled());
crate::interrupt::disable_irqs();
let Some(last) = start.as_usize().checked_add(size - 1) else {
flush_tlb(None);
return;
};
const PAGE_SIZE: usize = ax_memory_addr::PAGE_SIZE_4K;
let first = start.as_usize() & !(PAGE_SIZE - 1);
let pages = (last - first) / PAGE_SIZE + 1;
if pages > crate::arch::current::TLB_RANGE_PAGE_LIMIT {
flush_tlb(None);
return;
}
for page in 0..pages {
flush_tlb(Some(crate::VirtAddr::from_usize(first + page * PAGE_SIZE)));
}
}
pub fn update_mmu_cache(vaddr: crate::VirtAddr) {
let base = vaddr.as_usize() & !(ax_memory_addr::PAGE_SIZE_4K - 1);
crate::arch::current::asm::update_mmu_cache(crate::VirtAddr::from_usize(base));
}
#[cfg(target_arch = "aarch64")]
pub use El1 as Native;
#[cfg(target_arch = "aarch64")]
pub use crate::arch::current::mmu::{El1, El2};
#[cfg(not(target_arch = "aarch64"))]
pub struct Native;
#[cfg(not(target_arch = "aarch64"))]
impl Native {
pub fn read_kernel_page_table() -> crate::PhysAddr {
read_kernel_page_table()
}
pub unsafe fn write_kernel_page_table(root: crate::PhysAddr) {
unsafe { write_kernel_page_table(root) };
}
pub fn flush_tlb(address: Option<crate::VirtAddr>) {
flush_tlb(address);
}
pub fn flush_tlb_range(start: crate::VirtAddr, size: usize) {
flush_tlb_range(start, size);
}
pub fn address_space_tag_capacity() -> u32 {
address_space_tag_capacity()
}
}
#[cfg(target_arch = "riscv64")]
pub use crate::arch::current::mmu::{Satp, SatpMode, install_page_table, read_satp};