use crate::header::{KernelObjectHeader, NONE_SENTINEL}; use crate::object_tag::ObjectTag; use crate::untyped::{self, UntypedState}; pub trait KernelObject: Sized { const TAG: ObjectTag; const METADATA_SIZE: usize; const METADATA_ALIGN: usize; fn init_default(header: KernelObjectHeader) -> Self; } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct EndpointObject { pub header: KernelObjectHeader, pub sender_head: u16, pub sender_tail: u16, pub sender_len: u16, pub receiver_head: u16, pub receiver_tail: u16, pub receiver_len: u16, pub holder: u16, pub _pad: [u8; 18], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for EndpointObject { const TAG: ObjectTag = ObjectTag::Endpoint; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, sender_head: NONE_SENTINEL, sender_tail: NONE_SENTINEL, sender_len: 0, receiver_head: NONE_SENTINEL, receiver_tail: NONE_SENTINEL, receiver_len: 0, holder: NONE_SENTINEL, _pad: [0; 18], } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct NotificationObject { pub header: KernelObjectHeader, pub word: u64, pub waiters: [u16; 4], pub waiter_count: u8, pub _pad: [u8; 15], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for NotificationObject { const TAG: ObjectTag = ObjectTag::Notification; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, word: 0, waiters: [0xFFFF; 4], waiter_count: 0, _pad: [0; 15], } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct SchedContextObject { pub header: KernelObjectHeader, pub budget_us: u64, pub period_us: u64, pub remaining_us: u64, pub replenish_remaining_us: u32, pub attached_pid: u16, pub priority: u8, pub flags: u8, } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for SchedContextObject { const TAG: ObjectTag = ObjectTag::SchedContext; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, budget_us: 0, period_us: 0, remaining_us: 0, replenish_remaining_us: 0, attached_pid: 0xFFFF, priority: 0, flags: 0, } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct UntypedObject { pub header: KernelObjectHeader, pub phys_base: u64, pub watermark: u32, pub child_count: u32, pub first_child: u16, pub size_bits: u8, pub is_device: u8, pub _pad: [u8; 12], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for UntypedObject { const TAG: ObjectTag = ObjectTag::Untyped; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, phys_base: 0, watermark: 0, child_count: 0, first_child: 0xFFFF, size_bits: 0, is_device: 0, _pad: [0; 12], } } } impl UntypedObject { pub const fn to_state(&self) -> UntypedState { UntypedState::from_parts( self.watermark, self.size_bits, self.is_device != 0, self.child_count, ) } pub fn apply_state(&mut self, state: &UntypedState) { self.watermark = state.watermark(); self.size_bits = state.size_bits(); self.is_device = match state.is_device() { true => 1, false => 0, }; self.child_count = state.child_count(); } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct IrqHandlerObject { pub header: KernelObjectHeader, pub vector: u8, pub source_kind: u8, pub port_base: u16, pub port_count: u16, pub _pad1: [u8; 2], pub source_data: u32, pub _pad2: [u8; 20], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for IrqHandlerObject { const TAG: ObjectTag = ObjectTag::IrqHandler; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, vector: 0, source_kind: 0, port_base: 0, port_count: 0, _pad1: [0; 2], source_data: 0, _pad2: [0; 20], } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct FramebufferObject { pub header: KernelObjectHeader, pub phys_addr: u64, pub byte_size: u64, pub width: u32, pub height: u32, pub pitch: u32, pub bpp: u16, pub _pad: [u8; 2], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for FramebufferObject { const TAG: ObjectTag = ObjectTag::Framebuffer; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, phys_addr: 0, byte_size: 0, width: 0, height: 0, pitch: 0, bpp: 0, _pad: [0; 2], } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct PciDeviceObject { pub header: KernelObjectHeader, pub device_table_idx: u8, pub _pad: [u8; 31], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for PciDeviceObject { const TAG: ObjectTag = ObjectTag::PciDevice; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, device_table_idx: 0, _pad: [0; 31], } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct ProcessObject { pub header: KernelObjectHeader, pub pid: u16, pub _pad: [u8; 30], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for ProcessObject { const TAG: ObjectTag = ObjectTag::Process; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, pid: 0xFFFF, _pad: [0; 30], } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct FrameObject { pub header: KernelObjectHeader, pub phys_addr: u64, pub size_bits: u8, pub _pad: [u8; 23], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for FrameObject { const TAG: ObjectTag = ObjectTag::Frame; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, phys_addr: 0, size_bits: 12, _pad: [0; 23], } } } #[derive(Debug, Clone, Copy)] #[repr(C)] pub struct CNodeObject { pub header: KernelObjectHeader, pub slots_phys: u64, pub size_bits: u8, pub frame_count: u8, pub _pad: [u8; 22], } const _: () = assert!(core::mem::size_of::() == 64); impl KernelObject for CNodeObject { const TAG: ObjectTag = ObjectTag::CNode; const METADATA_SIZE: usize = core::mem::size_of::(); const METADATA_ALIGN: usize = 64; fn init_default(header: KernelObjectHeader) -> Self { Self { header, slots_phys: 0, size_bits: 0, frame_count: 0, _pad: [0; 22], } } } macro_rules! assert_layout_matches { ($obj:ty, $size:expr, $align:expr) => { const _: () = assert!(<$obj>::METADATA_SIZE as u32 == $size); const _: () = assert!(<$obj>::METADATA_ALIGN as u32 == $align); }; } assert_layout_matches!(EndpointObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(NotificationObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(SchedContextObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(UntypedObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(IrqHandlerObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(FramebufferObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(PciDeviceObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(ProcessObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(FrameObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN); assert_layout_matches!(CNodeObject, untyped::FIXED_OBJECT_SIZE, untyped::FIXED_OBJECT_ALIGN);