1use core::fmt;
4
5use axconfig::plat::{PHYS_MEMORY_BASE, PHYS_MEMORY_SIZE, PHYS_VIRT_OFFSET};
6
7#[doc(no_inline)]
8pub use memory_addr::{MemoryAddr, PAGE_SIZE_4K, PhysAddr, VirtAddr};
9
10bitflags::bitflags! {
11 pub struct MemRegionFlags: usize {
13 const READ = 1 << 0;
15 const WRITE = 1 << 1;
17 const EXECUTE = 1 << 2;
19 const DEVICE = 1 << 4;
21 const UNCACHED = 1 << 5;
23 const RESERVED = 1 << 6;
25 const FREE = 1 << 7;
27 }
28}
29
30impl fmt::Debug for MemRegionFlags {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 fmt::Debug::fmt(&self.0, f)
33 }
34}
35
36#[derive(Debug)]
38pub struct MemRegion {
39 pub paddr: PhysAddr,
41 pub size: usize,
43 pub flags: MemRegionFlags,
45 pub name: &'static str,
47}
48
49#[inline]
56pub const fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
57 assert!(
58 vaddr.as_usize() >= PHYS_VIRT_OFFSET,
59 "Converted address is invalid, check if the virtual address is in kernel space"
60 );
61 pa!(vaddr.as_usize() - PHYS_VIRT_OFFSET)
62}
63
64#[inline]
71pub const fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
72 va!(paddr.as_usize() + PHYS_VIRT_OFFSET)
73}
74
75pub fn memory_regions() -> impl Iterator<Item = MemRegion> {
77 kernel_image_regions().chain(crate::platform::mem::platform_regions())
78}
79
80fn kernel_image_regions() -> impl Iterator<Item = MemRegion> {
82 [
83 MemRegion {
84 paddr: virt_to_phys((_stext as usize).into()),
85 size: _etext as usize - _stext as usize,
86 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::EXECUTE,
87 name: ".text",
88 },
89 MemRegion {
90 paddr: virt_to_phys((_srodata as usize).into()),
91 size: _erodata as usize - _srodata as usize,
92 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ,
93 name: ".rodata",
94 },
95 MemRegion {
96 paddr: virt_to_phys((_sdata as usize).into()),
97 size: _edata as usize - _sdata as usize,
98 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
99 name: ".data .tdata .tbss .percpu",
100 },
101 MemRegion {
102 paddr: virt_to_phys((boot_stack as usize).into()),
103 size: boot_stack_top as usize - boot_stack as usize,
104 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
105 name: "boot stack",
106 },
107 MemRegion {
108 paddr: virt_to_phys((_sbss as usize).into()),
109 size: _ebss as usize - _sbss as usize,
110 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
111 name: ".bss",
112 },
113 ]
114 .into_iter()
115}
116
117#[allow(dead_code)]
119pub(crate) fn default_mmio_regions() -> impl Iterator<Item = MemRegion> {
120 axconfig::devices::MMIO_REGIONS.iter().map(|reg| MemRegion {
121 paddr: reg.0.into(),
122 size: reg.1,
123 flags: MemRegionFlags::RESERVED
124 | MemRegionFlags::DEVICE
125 | MemRegionFlags::READ
126 | MemRegionFlags::WRITE,
127 name: "mmio",
128 })
129}
130
131#[allow(dead_code)]
133pub(crate) fn default_free_regions() -> impl Iterator<Item = MemRegion> {
134 let start = virt_to_phys((_ekernel as usize).into()).align_up_4k();
135 let end = pa!(PHYS_MEMORY_BASE + PHYS_MEMORY_SIZE).align_down_4k();
136 core::iter::once(MemRegion {
137 paddr: start,
138 size: end.as_usize() - start.as_usize(),
139 flags: MemRegionFlags::FREE | MemRegionFlags::READ | MemRegionFlags::WRITE,
140 name: "free memory",
141 })
142}
143
144#[allow(dead_code)]
146pub(crate) fn clear_bss() {
147 unsafe {
148 core::slice::from_raw_parts_mut(_sbss as usize as *mut u8, _ebss as usize - _sbss as usize)
149 .fill(0);
150 }
151}
152
153unsafe extern "C" {
154 fn _stext();
155 fn _etext();
156 fn _srodata();
157 fn _erodata();
158 fn _sdata();
159 fn _edata();
160 fn _sbss();
161 fn _ebss();
162 fn _ekernel();
163 fn boot_stack();
164 fn boot_stack_top();
165}