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 pa!(vaddr.as_usize() - PHYS_VIRT_OFFSET)
58}
59
60#[inline]
67pub const fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
68 va!(paddr.as_usize() + PHYS_VIRT_OFFSET)
69}
70
71pub fn memory_regions() -> impl Iterator<Item = MemRegion> {
73 kernel_image_regions().chain(crate::platform::mem::platform_regions())
74}
75
76fn kernel_image_regions() -> impl Iterator<Item = MemRegion> {
78 [
79 MemRegion {
80 paddr: virt_to_phys((_stext as usize).into()),
81 size: _etext as usize - _stext as usize,
82 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::EXECUTE,
83 name: ".text",
84 },
85 MemRegion {
86 paddr: virt_to_phys((_srodata as usize).into()),
87 size: _erodata as usize - _srodata as usize,
88 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ,
89 name: ".rodata",
90 },
91 MemRegion {
92 paddr: virt_to_phys((_sdata as usize).into()),
93 size: _edata as usize - _sdata as usize,
94 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
95 name: ".data .tdata .tbss .percpu",
96 },
97 MemRegion {
98 paddr: virt_to_phys((boot_stack as usize).into()),
99 size: boot_stack_top as usize - boot_stack as usize,
100 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
101 name: "boot stack",
102 },
103 MemRegion {
104 paddr: virt_to_phys((_sbss as usize).into()),
105 size: _ebss as usize - _sbss as usize,
106 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
107 name: ".bss",
108 },
109 ]
110 .into_iter()
111}
112
113#[allow(dead_code)]
115pub(crate) fn default_mmio_regions() -> impl Iterator<Item = MemRegion> {
116 axconfig::devices::MMIO_REGIONS.iter().map(|reg| MemRegion {
117 paddr: reg.0.into(),
118 size: reg.1,
119 flags: MemRegionFlags::RESERVED
120 | MemRegionFlags::DEVICE
121 | MemRegionFlags::READ
122 | MemRegionFlags::WRITE,
123 name: "mmio",
124 })
125}
126
127#[allow(dead_code)]
129pub(crate) fn default_free_regions() -> impl Iterator<Item = MemRegion> {
130 let start = virt_to_phys((_ekernel as usize).into()).align_up_4k();
131 let end = pa!(PHYS_MEMORY_BASE + PHYS_MEMORY_SIZE).align_down_4k();
132 core::iter::once(MemRegion {
133 paddr: start,
134 size: end.as_usize() - start.as_usize(),
135 flags: MemRegionFlags::FREE | MemRegionFlags::READ | MemRegionFlags::WRITE,
136 name: "free memory",
137 })
138}
139
140#[allow(dead_code)]
142pub(crate) fn clear_bss() {
143 unsafe {
144 core::slice::from_raw_parts_mut(_sbss as usize as *mut u8, _ebss as usize - _sbss as usize)
145 .fill(0);
146 }
147}
148
149unsafe extern "C" {
150 fn _stext();
151 fn _etext();
152 fn _srodata();
153 fn _erodata();
154 fn _sdata();
155 fn _edata();
156 fn _sbss();
157 fn _ebss();
158 fn _ekernel();
159 fn boot_stack();
160 fn boot_stack_top();
161}