Next Generation WASM Microkernel Operating System
at main 200 lines 6.9 kB view raw
1// Copyright 2025 Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use core::ops::{Deref, DerefMut, Range}; 9use core::{fmt, slice}; 10 11use kmem::{PhysicalAddress, VirtualAddress}; 12 13#[derive(Debug)] 14#[non_exhaustive] 15pub struct BootInfo { 16 pub cpu_mask: usize, 17 /// A map of the physical memory regions of the underlying machine. 18 /// 19 /// The loader parses this information from the firmware and also reports regions used 20 /// during initial mapping. Regions marked as usable can be freely 21 /// used by the kernel. 22 /// 23 /// Note: Memory regions are *guaranteed* to not overlap and be sorted by their start address. 24 /// But they might not be optimally packed, i.e. adjacent regions that could be merged are not. 25 pub memory_regions: MemoryRegions, 26 /// Physical addresses can be converted to virtual addresses by adding this offset to them. 27 /// 28 /// The mapping of the physical memory allows to access arbitrary physical frames. Accessing 29 /// frames that are also mapped at other virtual addresses can easily break memory safety and 30 /// cause undefined behavior. Only frames reported as `USABLE` by the memory map in the `BootInfo` 31 /// can be safely accessed. 32 pub physical_address_offset: VirtualAddress, 33 pub physical_memory_map: Range<VirtualAddress>, 34 /// The thread local storage (TLS) template of the kernel executable, if present. 35 pub tls_template: Option<TlsTemplate>, 36 /// Virtual address of the loaded kernel image. 37 pub kernel_virt: Range<VirtualAddress>, 38 /// Physical memory region where the kernel ELF file resides. 39 /// 40 /// This field can be used by the kernel to perform introspection of its own ELF file. 41 pub kernel_phys: Range<PhysicalAddress>, 42 43 pub rng_seed: [u8; 32], 44} 45unsafe impl Send for BootInfo {} 46unsafe impl Sync for BootInfo {} 47 48impl BootInfo { 49 /// Create a new boot info structure with the given memory map. 50 /// 51 /// The other fields are initialized with default values. 52 pub fn new(memory_regions: MemoryRegions) -> Self { 53 Self { 54 memory_regions, 55 cpu_mask: 0, 56 physical_address_offset: Default::default(), 57 physical_memory_map: Default::default(), 58 tls_template: None, 59 kernel_virt: Default::default(), 60 kernel_phys: Default::default(), 61 rng_seed: [0; 32], 62 } 63 } 64} 65 66/// FFI-safe slice of [`MemoryRegion`] structs, semantically equivalent to 67/// `&'static mut [MemoryRegion]`. 68/// 69/// This type implements the [`Deref`][core::ops::Deref] and [`DerefMut`][core::ops::DerefMut] 70/// traits, so it can be used like a `&mut [MemoryRegion]` slice. It also implements [`From`] 71/// and [`Into`] for easy conversions from and to `&'static mut [MemoryRegion]`. 72#[derive(Debug)] 73#[repr(C)] 74pub struct MemoryRegions { 75 pub(crate) ptr: *mut MemoryRegion, 76 pub(crate) len: usize, 77} 78 79impl Deref for MemoryRegions { 80 type Target = [MemoryRegion]; 81 82 fn deref(&self) -> &Self::Target { 83 unsafe { slice::from_raw_parts(self.ptr, self.len) } 84 } 85} 86 87impl DerefMut for MemoryRegions { 88 fn deref_mut(&mut self) -> &mut Self::Target { 89 unsafe { slice::from_raw_parts_mut(self.ptr, self.len) } 90 } 91} 92 93impl From<&'static mut [MemoryRegion]> for MemoryRegions { 94 fn from(regions: &'static mut [MemoryRegion]) -> Self { 95 MemoryRegions { 96 ptr: regions.as_mut_ptr(), 97 len: regions.len(), 98 } 99 } 100} 101 102impl From<MemoryRegions> for &'static mut [MemoryRegion] { 103 fn from(regions: MemoryRegions) -> &'static mut [MemoryRegion] { 104 unsafe { slice::from_raw_parts_mut(regions.ptr, regions.len) } 105 } 106} 107 108/// Represent a physical memory region. 109#[derive(Debug, Clone, Eq, PartialEq)] 110#[repr(C)] 111pub struct MemoryRegion { 112 /// The physical start address region. 113 pub range: Range<PhysicalAddress>, 114 /// The memory type of the memory region. 115 /// 116 /// Only [`Usable`][MemoryRegionKind::Usable] regions can be freely used. 117 pub kind: MemoryRegionKind, 118} 119 120/// Represents the different types of memory. 121#[derive(Debug, Copy, Clone, Eq, PartialEq)] 122#[non_exhaustive] 123#[repr(C)] 124pub enum MemoryRegionKind { 125 /// Unused conventional memory, can be used by the kernel. 126 Usable, 127 /// Memory mappings created by the loader, including the page table and boot info mappings. 128 /// 129 /// This memory should _not_ be used by the kernel. 130 Loader, 131 /// The memory region containing the flattened device tree (FDT). 132 FDT, 133} 134 135impl MemoryRegionKind { 136 pub fn is_usable(&self) -> bool { 137 matches!(self, MemoryRegionKind::Usable) 138 } 139} 140 141impl fmt::Display for BootInfo { 142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 143 writeln!( 144 f, 145 "{:<23} : {}", 146 "PHYSICAL ADDRESS OFFSET", self.physical_address_offset 147 )?; 148 writeln!( 149 f, 150 "{:<23} : {}..{}", 151 "PHYSICAL MEMORY MAP", self.physical_memory_map.start, self.physical_memory_map.end 152 )?; 153 writeln!( 154 f, 155 "{:<23} : {}..{}", 156 "KERNEL VIRT", self.kernel_virt.start, self.kernel_virt.end 157 )?; 158 writeln!( 159 f, 160 "{:<23} : {}..{}", 161 "KERNEL PHYS", self.kernel_phys.start, self.kernel_phys.end 162 )?; 163 if let Some(tls) = self.tls_template.as_ref() { 164 writeln!( 165 f, 166 "{:<23} : .tdata: {:?}..{:?}, .tbss: {:?}..{:?}", 167 "TLS TEMPLATE", 168 tls.start_addr, 169 tls.start_addr.add(tls.file_size), 170 tls.start_addr.add(tls.file_size), 171 tls.start_addr.add(tls.file_size + tls.mem_size) 172 )?; 173 } else { 174 writeln!(f, "{:<23} : None", "TLS TEMPLATE")?; 175 for (idx, region) in self.memory_regions.iter().enumerate() { 176 writeln!( 177 f, 178 "MEMORY REGION {:<10}: {}..{} {:?}", 179 idx, region.range.start, region.range.end, region.kind, 180 )?; 181 } 182 } 183 184 Ok(()) 185 } 186} 187 188#[repr(C)] 189#[derive(Debug, Clone)] 190pub struct TlsTemplate { 191 /// The address of TLS template 192 pub start_addr: VirtualAddress, 193 /// The size of the TLS segment in memory 194 pub mem_size: usize, 195 /// The size of the TLS segment in the elf file. 196 /// If the TLS segment contains zero-initialized data (tbss) then this size will be smaller than 197 /// `mem_size` 198 pub file_size: usize, 199 pub align: usize, 200}