1pub use ax_memory_addr::{PAGE_SIZE_4K, PhysAddr, PhysAddrRange, VirtAddr, VirtAddrRange, pa, va};
4pub use ax_plat::mem::{
5 MemRegionFlags, PhysMemRegion, kernel_aspace, mmio_ranges, phys_ram_ranges, phys_to_virt,
6 reserved_phys_ram_ranges, total_ram_size, virt_to_phys,
7};
8use ax_plat::mem::{check_sorted_ranges_overlap, ranges_difference};
9use heapless::Vec;
10use spin::Lazy;
11
12#[allow(unused_imports)]
13use crate::addr_of_sym;
14
15const MAX_REGIONS: usize = 128;
16
17static ALL_MEM_REGIONS: Lazy<Vec<PhysMemRegion, MAX_REGIONS>> = Lazy::new(|| {
18 let mut all_regions = Vec::new();
19 let mut push = |r: PhysMemRegion| {
20 if r.size > 0 {
21 all_regions.push(r).expect("too many memory regions");
22 }
23 };
24
25 #[cfg(not(feature = "plat-dyn"))]
26 {
27 push(PhysMemRegion {
29 paddr: virt_to_phys(addr_of_sym!(_stext).into()),
30 size: addr_of_sym!(_etext) - addr_of_sym!(_stext),
31 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::EXECUTE,
32 name: ".text",
33 });
34 push(PhysMemRegion {
35 paddr: virt_to_phys(addr_of_sym!(_srodata).into()),
36 size: addr_of_sym!(_erodata) - addr_of_sym!(_srodata),
37 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ,
38 name: ".rodata",
39 });
40 push(PhysMemRegion {
41 paddr: virt_to_phys(addr_of_sym!(_sdata).into()),
42 size: addr_of_sym!(_edata) - addr_of_sym!(_sdata),
43 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
44 name: ".data .tdata .tbss .percpu",
45 });
46 push(PhysMemRegion {
47 paddr: virt_to_phys(addr_of_sym!(boot_stack).into()),
48 size: addr_of_sym!(boot_stack_top) - addr_of_sym!(boot_stack),
49 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
50 name: "boot stack",
51 });
52 push(PhysMemRegion {
53 paddr: virt_to_phys(addr_of_sym!(_sbss).into()),
54 size: addr_of_sym!(_ebss) - addr_of_sym!(_sbss),
55 flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE,
56 name: ".bss",
57 });
58 }
59
60 for &(start, size) in mmio_ranges() {
62 push(PhysMemRegion::new_mmio(start, size, "mmio"));
63 }
64 for &(start, size) in reserved_phys_ram_ranges() {
65 push(PhysMemRegion {
67 paddr: PhysAddr::from_usize(start),
68 size,
69 flags: MemRegionFlags::RESERVED
70 | MemRegionFlags::READ
71 | MemRegionFlags::WRITE
72 | MemRegionFlags::EXECUTE,
73 name: "reserved",
74 })
75 }
76
77 let mut reserved_ranges = reserved_phys_ram_ranges()
78 .iter()
79 .cloned()
80 .collect::<Vec<_, MAX_REGIONS>>();
81 #[cfg(not(feature = "plat-dyn"))]
82 {
83 let kernel_start = virt_to_phys(addr_of_sym!(_skernel).into()).as_usize();
85 let kernel_size = addr_of_sym!(_ekernel) - addr_of_sym!(_skernel);
86 reserved_ranges
87 .push((kernel_start, kernel_size))
88 .expect("too many memory regions"); }
90
91 reserved_ranges.sort_unstable_by_key(|&(start, _size)| start);
93 ranges_difference(phys_ram_ranges(), &reserved_ranges, |(start, size)| {
94 push(PhysMemRegion::new_ram(start, size, "free memory"));
95 })
96 .inspect_err(|(a, b)| error!("Reserved memory region {a:#x?} overlaps with {b:#x?}"))
97 .unwrap();
98
99 all_regions.sort_unstable_by_key(|r| r.paddr);
101 check_sorted_ranges_overlap(all_regions.iter().map(|r| (r.paddr.into(), r.size)))
102 .inspect_err(|(a, b)| error!("Physical memory region {a:#x?} overlaps with {b:#x?}"))
103 .unwrap();
104
105 all_regions
106});
107
108pub fn memory_regions() -> impl Iterator<Item = PhysMemRegion> {
110 ALL_MEM_REGIONS.iter().cloned()
111}
112
113pub fn boot_stack_bounds(cpu_id: usize) -> (VirtAddr, usize) {
114 #[cfg(plat_dyn)]
115 {
116 axplat_dyn::boot_stack_bounds(cpu_id)
117 }
118 #[cfg(not(plat_dyn))]
119 {
120 let _ = cpu_id;
121 let bottom = addr_of_sym!(boot_stack);
122 let top = addr_of_sym!(boot_stack_top);
123 (VirtAddr::from(bottom), top - bottom)
124 }
125}
126
127pub unsafe fn clear_bss() {
135 unsafe {
136 core::slice::from_raw_parts_mut(
137 _sbss as *mut u8,
138 (_ebss as *mut u8).offset_from_unsigned(_sbss as *mut u8),
139 )
140 .fill(0);
141 }
142}
143
144#[allow(dead_code)]
145unsafe extern "C" {
146 fn _stext();
147 fn _etext();
148 fn _srodata();
149 fn _erodata();
150 fn _sdata();
151 fn _edata();
152 fn _sbss();
153 fn _ebss();
154 fn _skernel();
155 fn _ekernel();
156 fn boot_stack();
157 fn boot_stack_top();
158}