use core::fmt;
#[doc(no_inline)]
pub use memory_addr::{MemoryAddr, PhysAddr, VirtAddr, PAGE_SIZE_4K};
bitflags::bitflags! {
pub struct MemRegionFlags: usize {
const READ = 1 << 0;
const WRITE = 1 << 1;
const EXECUTE = 1 << 2;
const DEVICE = 1 << 4;
const UNCACHED = 1 << 5;
const RESERVED = 1 << 6;
const FREE = 1 << 7;
}
}
impl fmt::Debug for MemRegionFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
#[derive(Debug)]
pub struct MemRegion {
pub paddr: PhysAddr,
pub size: usize,
pub flags: MemRegionFlags,
pub name: &'static str,
}
#[inline]
pub const fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
pa!(vaddr.as_usize() - axconfig::PHYS_VIRT_OFFSET)
}
#[inline]
pub const fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
va!(paddr.as_usize() + axconfig::PHYS_VIRT_OFFSET)
}
pub fn memory_regions() -> impl Iterator<Item = MemRegion> {
kernel_image_regions().chain(crate::platform::mem::platform_regions())
}
fn kernel_image_regions() -> impl Iterator<Item = MemRegion> {
[
MemRegion {
paddr: virt_to_phys((_stext as usize).into()),
size: _etext as usize - _stext as usize,
flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::EXECUTE,
name: ".text",
},
MemRegion {
paddr: virt_to_phys((_srodata as usize).into()),
size: _erodata as usize - _srodata as usize,
flags: MemRegionFlags::RESERVED | MemRegionFlags::READ,
name: ".rodata",
},
MemRegion {
paddr: virt_to_phys((_sdata as usize).into()),
size: _edata as usize - _sdata as usize,
flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
name: ".data .tdata .tbss .percpu",
},
MemRegion {
paddr: virt_to_phys((boot_stack as usize).into()),
size: boot_stack_top as usize - boot_stack as usize,
flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
name: "boot stack",
},
MemRegion {
paddr: virt_to_phys((_sbss as usize).into()),
size: _ebss as usize - _sbss as usize,
flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
name: ".bss",
},
]
.into_iter()
}
#[allow(dead_code)]
pub(crate) fn default_mmio_regions() -> impl Iterator<Item = MemRegion> {
axconfig::MMIO_REGIONS.iter().map(|reg| MemRegion {
paddr: reg.0.into(),
size: reg.1,
flags: MemRegionFlags::RESERVED
| MemRegionFlags::DEVICE
| MemRegionFlags::READ
| MemRegionFlags::WRITE,
name: "mmio",
})
}
#[allow(dead_code)]
pub(crate) fn default_free_regions() -> impl Iterator<Item = MemRegion> {
let start = virt_to_phys((_ekernel as usize).into()).align_up_4k();
let end = pa!(axconfig::PHYS_MEMORY_END).align_down_4k();
core::iter::once(MemRegion {
paddr: start,
size: end.as_usize() - start.as_usize(),
flags: MemRegionFlags::FREE | MemRegionFlags::READ | MemRegionFlags::WRITE,
name: "free memory",
})
}
#[allow(dead_code)]
pub(crate) fn clear_bss() {
unsafe {
core::slice::from_raw_parts_mut(_sbss as usize as *mut u8, _ebss as usize - _sbss as usize)
.fill(0);
}
}
extern "C" {
fn _stext();
fn _etext();
fn _srodata();
fn _erodata();
fn _sdata();
fn _edata();
fn _sbss();
fn _ebss();
fn _ekernel();
fn boot_stack();
fn boot_stack_top();
}