Next Generation WASM Microkernel Operating System
at trap_handler 100 lines 3.7 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::wasm::compile::Compiler; 10use crate::wasm::cranelift::CraneliftCompiler; 11use crate::wasm::type_registry::TypeRegistry; 12use alloc::sync::Arc; 13use core::sync::atomic::AtomicU64; 14use cranelift_codegen::settings::{Configurable, Flags}; 15use rand::{Rng, SeedableRng}; 16use rand_chacha::ChaCha20Rng; 17use spin::{Mutex, MutexGuard}; 18 19/// Global context for the runtime. 20/// 21/// An engine can be safely shared across threads and is a cheap cloneable 22/// handle to the actual engine. The engine itself will be deallocated once all 23/// references to it have gone away. 24#[derive(Debug, Clone)] 25pub struct Engine(Arc<EngineInner>); 26 27#[derive(Debug)] 28pub struct EngineInner { 29 compiler: CraneliftCompiler, 30 type_registry: TypeRegistry, 31 rng: Option<Mutex<ChaCha20Rng>>, 32 asid_alloc: Mutex<arch::AsidAllocator>, 33 epoch_counter: AtomicU64, 34} 35 36impl Default for Engine { 37 fn default() -> Self { 38 let isa_builder = cranelift_codegen::isa::lookup(target_lexicon::HOST).unwrap(); 39 let mut b = cranelift_codegen::settings::builder(); 40 b.set("opt_level", "speed_and_size").unwrap(); 41 b.set("libcall_call_conv", "isa_default").unwrap(); 42 b.set("preserve_frame_pointers", "true").unwrap(); 43 b.set("enable_probestack", "true").unwrap(); 44 b.set("probestack_strategy", "inline").unwrap(); 45 let target_isa = isa_builder.finish(Flags::new(b)).unwrap(); 46 47 Self(Arc::new(EngineInner { 48 compiler: CraneliftCompiler::new(target_isa), 49 type_registry: TypeRegistry::default(), 50 rng: None, 51 asid_alloc: Mutex::new(arch::AsidAllocator::new()), 52 epoch_counter: AtomicU64::new(0), 53 })) 54 } 55} 56 57impl Engine { 58 pub fn new(rng: &mut impl Rng) -> Self { 59 let isa_builder = cranelift_codegen::isa::lookup(target_lexicon::HOST).unwrap(); 60 let mut b = cranelift_codegen::settings::builder(); 61 b.set("opt_level", "speed_and_size").unwrap(); 62 b.set("libcall_call_conv", "isa_default").unwrap(); 63 b.set("preserve_frame_pointers", "true").unwrap(); 64 b.set("enable_probestack", "true").unwrap(); 65 b.set("probestack_strategy", "inline").unwrap(); 66 let target_isa = isa_builder.finish(Flags::new(b)).unwrap(); 67 68 Self(Arc::new(EngineInner { 69 compiler: CraneliftCompiler::new(target_isa), 70 type_registry: TypeRegistry::default(), 71 rng: Some(Mutex::new(ChaCha20Rng::from_rng(rng))), 72 asid_alloc: Mutex::new(arch::AsidAllocator::new()), 73 epoch_counter: AtomicU64::new(0), 74 })) 75 } 76 77 pub fn same(lhs: &Engine, rhs: &Engine) -> bool { 78 Arc::ptr_eq(&lhs.0, &rhs.0) 79 } 80 81 pub fn compiler(&self) -> &dyn Compiler { 82 &self.0.compiler 83 } 84 85 /// Returns the type registry of this engine, used to canonicalize types. 86 pub fn type_registry(&self) -> &TypeRegistry { 87 &self.0.type_registry 88 } 89 90 pub fn allocate_asid(&self) -> u16 { 91 let mut alloc = self.0.asid_alloc.lock(); 92 alloc.alloc().expect("out of address space identifiers") 93 } 94 pub fn rng(&self) -> Option<MutexGuard<'_, ChaCha20Rng>> { 95 Some(self.0.rng.as_ref()?.lock()) 96 } 97 pub fn epoch_counter(&self) -> &AtomicU64 { 98 &self.0.epoch_counter 99 } 100}