Next Generation WASM Microkernel Operating System
at trap_handler 97 lines 2.8 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 crate::arch; 9use crate::mem::frame_alloc::{FRAME_ALLOC, FrameAllocator}; 10use crate::mem::frame_alloc::{Frame, frame_list::FrameList}; 11use alloc::sync::Arc; 12use core::alloc::Layout; 13use core::fmt::Debug; 14use core::iter; 15use core::num::NonZeroUsize; 16use spin::{LazyLock, OnceLock}; 17 18pub trait Provider: Debug { 19 // TODO make async 20 fn get_frame(&self, at_offset: usize, will_write: bool) -> crate::Result<Frame>; 21 // TODO make async 22 fn get_frames( 23 &self, 24 at_offset: usize, 25 len: NonZeroUsize, 26 will_write: bool, 27 ) -> crate::Result<FrameList>; 28 fn free_frame(&self, frame: Frame); 29 fn free_frames(&self, frames: FrameList); 30} 31 32pub static THE_ZERO_FRAME: LazyLock<Arc<TheZeroFrame>> = LazyLock::new(|| { 33 let frame_alloc = FRAME_ALLOC.get().unwrap(); 34 Arc::new(TheZeroFrame::new(frame_alloc)) 35}); 36 37#[derive(Debug)] 38pub struct TheZeroFrame { 39 frame_alloc: &'static FrameAllocator, 40 frame: OnceLock<Frame>, 41} 42 43impl TheZeroFrame { 44 pub fn new(frame_alloc: &'static FrameAllocator) -> Self { 45 Self { 46 frame_alloc, 47 frame: OnceLock::new(), 48 } 49 } 50 pub(super) fn frame(&self) -> &Frame { 51 self.frame.get_or_init(|| { 52 let frame = self.frame_alloc.alloc_one_zeroed().unwrap(); 53 tracing::trace!("THE_ZERO_FRAME: {}", frame.addr()); 54 frame 55 }) 56 } 57} 58 59impl Provider for TheZeroFrame { 60 fn get_frame(&self, _at_offset: usize, will_write: bool) -> crate::Result<Frame> { 61 if will_write { 62 self.frame_alloc.alloc_one_zeroed().map_err(Into::into) 63 } else { 64 Ok(self.frame().clone()) 65 } 66 } 67 68 fn get_frames( 69 &self, 70 _at_offset: usize, 71 len: NonZeroUsize, 72 will_write: bool, 73 ) -> crate::Result<FrameList> { 74 if will_write { 75 self.frame_alloc 76 .alloc_contiguous_zeroed( 77 Layout::from_size_align(len.get(), arch::PAGE_SIZE).unwrap(), 78 ) 79 .map_err(Into::into) 80 } else { 81 Ok(FrameList::from_iter(iter::repeat_n( 82 self.frame().clone(), 83 len.get(), 84 ))) 85 } 86 } 87 88 fn free_frame(&self, frame: Frame) { 89 drop(frame); 90 } 91 92 fn free_frames(&self, frames: FrameList) { 93 for frame in frames { 94 self.free_frame(frame); 95 } 96 } 97}