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