#![no_std] #![forbid(unsafe_code)] use types::{ address::{EntryPoint, PhysicalAddress, StackPointer, VirtualAddress}, id::{CoreId, IrqId, ProcessId}, mapping::PagePerms, time::Ticks, }; /// Supplies frames for page tables while the platform builds an address /// space. The kernel charges each frame to the address space's owner. pub trait FrameSource { fn alloc_table_frame(&mut self) -> Option; } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MapError { /// The frame source refused to supply a page-table frame. OutOfFrames, /// The address is outside the user window or not page aligned. InvalidAddress, /// The process has no address space. NoAddressSpace, } /// The kernel's contract with an architecture. The kernel decides what is /// mapped where; the platform only applies those decisions to hardware. pub trait Platform { /// User mappings live in `[USER_VA_START, USER_VA_END)`; nothing else is mapped there in any space. const USER_VA_START: usize; const USER_VA_END: usize; fn create_address_space( &mut self, process: ProcessId, frames: &mut dyn FrameSource, ) -> Result<(), MapError>; /// Forgets the address space. The kernel frees its frames afterwards, /// so the platform must stop using them before returning. fn destroy_address_space(&mut self, process: ProcessId); fn map_page( &mut self, process: ProcessId, va: VirtualAddress, pa: PhysicalAddress, perms: PagePerms, frames: &mut dyn FrameSource, ) -> Result<(), MapError>; /// Removes the mapping at `va` and flushes it from the TLB. fn unmap_page(&mut self, process: ProcessId, va: VirtualAddress); /// The frame `va` maps to in `process`, if any. Advisory: the kernel confirms against its frame table. fn translate(&self, process: ProcessId, va: VirtualAddress) -> Option; /// Fills a frame with zeros before it is handed to a process. fn zero_frame(&mut self, pa: PhysicalAddress); fn enable_user_mode(&mut self, entry: EntryPoint, stack: StackPointer) -> !; /// Makes sure this core takes a timer interrupt by `deadline`, on top /// of its scheduling tick. fn wake_at(&mut self, deadline: Ticks); fn current_ticks(&self) -> Ticks; fn mask_irq(&mut self, irq: IrqId); fn unmask_irq(&mut self, irq: IrqId); fn send_ipi(&mut self, target: CoreId); fn core_id(&self) -> CoreId; fn num_cores(&self) -> u8; fn halt(&self) -> !; fn debug_putchar(&self, byte: u8); }