diff --git a/kernel/src/cap/descriptor.rs b/kernel/src/cap/descriptor.rs index 2cab17e..48beb88 100644 --- a/kernel/src/cap/descriptor.rs +++ b/kernel/src/cap/descriptor.rs @@ -1,13 +1,18 @@ -// src/cap/descriptor.rs use crate::mem::address::PhysAddr; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Relation { + Strong, + Borrow, + Transfer, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CapObject { Empty, - Memory { frame: PhysAddr, size: usize }, - Thread { id: u64 }, - CNode { frame: PhysAddr, size: usize }, // Капа на таблицу других кап - Endpoint { id: u64 }, // Для IPC + Memory { phys: PhysAddr, size_pages: usize }, + CNode { phys: PhysAddr, slots: usize }, + PMActor { id: u64 }, } bitflags::bitflags! { @@ -16,7 +21,7 @@ bitflags::bitflags! { const READ = 1 << 0; const WRITE = 1 << 1; const EXECUTE = 1 << 2; - const GRANT = 1 << 3; // Право передавать эту капу дальше + const GRANT = 1 << 3; } } @@ -24,6 +29,8 @@ bitflags::bitflags! { pub struct Capability { pub object: CapObject, pub rights: CapRights, + pub relation: Relation, + pub token_sig: u64, } impl Capability { @@ -31,6 +38,12 @@ impl Capability { Self { object: CapObject::Empty, rights: CapRights::empty(), + relation: Relation::Borrow, + token_sig: 0, } } + + pub fn is_valid(&self) -> bool { + !matches!(self.object, CapObject::Empty) + } } diff --git a/kernel/src/cap/mod.rs b/kernel/src/cap/mod.rs index 2f7c823..47b66db 100644 --- a/kernel/src/cap/mod.rs +++ b/kernel/src/cap/mod.rs @@ -1,31 +1,75 @@ -// src/cap/mod.rs pub mod descriptor; +pub mod object; use alloc::vec::Vec; -pub use descriptor::{Capability, CapObject, CapRights}; +use crate::mem::allocator::Locked; +pub use descriptor::*; + +pub struct CNodeSlot { + pub cap: Capability, + pub parent_idx: Option, +} -/// CNode — это таблица возможностей. -/// Дескриптор (u64) — это просто индекс в этом векторе. pub struct CNode { - caps: Vec, + pub slots: Vec>, } impl CNode { pub fn new(size: usize) -> Self { - let mut caps = Vec::with_capacity(size); + let mut slots = Vec::with_capacity(size); for _ in 0..size { - caps.push(Capability::empty()); + slots.push(Locked::new(CNodeSlot { + cap: Capability::empty(), + parent_idx: None, + })); } - Self { caps } + Self { slots } } - pub fn insert(&mut self, slot: usize, cap: Capability) -> Result<(), &'static str> { - if slot >= self.caps.len() { return Err("Index out of bounds"); } - self.caps[slot] = cap; + pub fn insert(&self, slot: usize, cap: Capability) -> Result<(), &'static str> { + if slot >= self.slots.len() { return Err("Index out of bounds"); } + let mut s = self.slots[slot].lock(); + s.cap = cap; Ok(()) } - pub fn get(&self, slot: usize) -> Option<&Capability> { - self.caps.get(slot) + pub fn mint(&self, src: usize, dest: usize, relation: Relation, rights: CapRights) -> Result<(), &'static str> { + let mut slots = (self.slots[src].lock(), self.slots[dest].lock()); + let (src_slot, mut dest_slot) = (&slots.0, &mut slots.1); + + if !src_slot.cap.is_valid() { return Err("Source empty"); } + if !src_slot.cap.rights.contains(CapRights::GRANT) { return Err("Insufficient rights to mint"); } + + let final_rights = src_slot.cap.rights & rights; + + dest_slot.cap = src_slot.cap; + dest_slot.cap.rights = final_rights; + dest_slot.cap.relation = relation; + dest_slot.parent_idx = Some(src); + + Ok(()) + } + + pub fn revoke(&self, slot_idx: usize) { + for i in 0..self.slots.len() { + let mut should_clear = false; + { + let child = self.slots[i].lock(); + if child.parent_idx == Some(slot_idx) { + should_clear = true; + } + } + + if should_clear { + self.revoke(i); + let mut child = self.slots[i].lock(); + child.cap = Capability::empty(); + child.parent_idx = None; + } + } + } + + pub fn get_cap(&self, slot: usize) -> Option { + self.slots.get(slot).map(|s| s.lock().cap) } } diff --git a/kernel/src/cap/object.rs b/kernel/src/cap/object.rs new file mode 100644 index 0000000..9d25261 --- /dev/null +++ b/kernel/src/cap/object.rs @@ -0,0 +1,29 @@ +use crate::mem::address::PhysAddr; +use core::sync::atomic::{AtomicUsize, Ordering}; + +#[derive(Debug)] +pub enum ObjectType { + Untyped, + Frame, + CNode, + ThreadBlock, + PageTable, +} + +pub struct KernelObject { + pub phys_addr: PhysAddr, + pub size_bits: u8, + pub obj_type: ObjectType, + pub ref_count: AtomicUsize, + pub owner_id: u64, +} + +impl KernelObject { + pub fn add_ref(&self) { + self.ref_count.fetch_add(1, Ordering::Relaxed); + } + + pub fn release(&self) -> bool { + self.ref_count.fetch_sub(1, Ordering::Release) == 1 + } +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 4c521b8..b4e080a 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -12,6 +12,7 @@ use limine::request::{FramebufferRequest, RequestsEndMarker, RequestsStartMarker use crate::mem::paging::{PageTable, PageTableFlags}; use crate::mem::address::{PhysAddr, VirtAddr}; +use crate::cap::{Relation, CapRights, Capability, CapObject}; pub mod cap; mod mem; @@ -157,7 +158,6 @@ static _START_MARKER: RequestsStartMarker = RequestsStartMarker::new(); #[used] #[unsafe(link_section = ".requests_end_marker")] static _END_MARKER: RequestsEndMarker = RequestsEndMarker::new(); -// Точка входа #[unsafe(no_mangle)] unsafe extern "C" fn kmain() -> ! { assert!(BASE_REVISION.is_supported()); @@ -174,12 +174,10 @@ unsafe extern "C" fn kmain() -> ! { info!(console, "BOOT", "RINA Kernel Starting..."); - // 1. Инициализация PMM unsafe { mem::pmm::BitmapPMM::init(&mmap_res, hhdm_offset); } info!(console, "MEM", "Physical Memory Manager initialized."); - // 2. Инициализация страничного управления - let p4_phys = mem::pmm::alloc_page().expect("OOM: Failed to allocate P4 table"); + let p4_phys = mem::pmm::alloc_frame().expect("OOM: Failed to allocate P4 table"); let p4 = unsafe { &mut *p4_phys.to_virt(hhdm_offset).as_mut_ptr::() }; unsafe { core::ptr::write_bytes(p4 as *mut _ as *mut u8, 0, 4096); } @@ -199,11 +197,10 @@ unsafe extern "C" fn kmain() -> ! { info!(console, "MMU", "Switching to Kernel Page Tables..."); unsafe { p4.activate(p4_phys); } - // 3. Инициализация Кучи let heap_start = 0xFFFF_9000_0000_0000; let heap_size = 8 * 1024 * 1024; for i in (0..heap_size).step_by(4096) { - let frame = mem::pmm::alloc_page().expect("OOM: Heap allocation failed"); + let frame = mem::pmm::alloc_frame().expect("OOM: Heap allocation failed"); p4.map_page(VirtAddr(heap_start + i as u64), frame, flags, hhdm_offset); } @@ -213,28 +210,33 @@ unsafe extern "C" fn kmain() -> ! { } info!(console, "HEAP", "Global Allocator is online."); - // --- Инициализация Модели Capabilities --- - // Создаем корневой CNode для ядра на 256 слотов - let mut root_cnode = cap::CNode::new(256); + let root_cnode = cap::CNode::new(256); - // Пример: Превращаем физическую страницу в Capability "Memory" - if let Some(frame) = mem::pmm::alloc_page() { - let mem_cap = cap::Capability { - object: cap::CapObject::Memory { frame, size: 4096 }, - rights: cap::CapRights::READ | cap::CapRights::WRITE, + if let Some(frame) = mem::pmm::alloc_frame() { + let mem_cap = Capability { + object: CapObject::Memory { phys: frame, size_pages: 1 }, + rights: CapRights::all(), + relation: Relation::Strong, + token_sig: 0x1, }; - // Помещаем в слот 0. Теперь "Дескриптор 0" — это право доступа к этой памяти. root_cnode.insert(0, mem_cap).unwrap(); - info!(console, "CAP", "Created memory capability at slot 0"); + info!(console, "CAP", "Root capability created at slot 0"); } - // Проверка - if let Some(c) = root_cnode.get(0) { - info!(console, "CAP", "Slot 0 verification: {:?}", c.object); + root_cnode.mint(0, 10, Relation::Borrow, CapRights::READ | CapRights::WRITE).unwrap(); + + if let Some(c) = root_cnode.get_cap(10) { + info!(console, "CAP", "Slot 10 (Borrowed): {:?}", c.relation); } + root_cnode.revoke(0); + if let Some(c) = root_cnode.get_cap(10) { + if !c.is_valid() { + info!(console, "CAP", "Slot 10 successfully revoked."); + } + } let logo = r#" ########### ################## diff --git a/kernel/src/mem/mod.rs b/kernel/src/mem/mod.rs index 9492015..bbba724 100644 --- a/kernel/src/mem/mod.rs +++ b/kernel/src/mem/mod.rs @@ -12,8 +12,5 @@ pub fn init(memmap: &limine::response::MemoryMapResponse, hhdm_offset: u64) { #[allow(dead_code)] pub fn get_stats() -> (usize, usize) { - unsafe { - let pmm = pmm::get_pmm_unchecked(); - (pmm.used_pages(), pmm.total_pages()) - } + pmm::get_stats() } diff --git a/kernel/src/mem/paging.rs b/kernel/src/mem/paging.rs index 61a5127..76cf468 100644 --- a/kernel/src/mem/paging.rs +++ b/kernel/src/mem/paging.rs @@ -2,6 +2,7 @@ use crate::mem::address::{PhysAddr, VirtAddr}; use crate::mem::pmm; use core::arch::asm; use bitflags::bitflags; +use crate::mem::pmm::PMM; bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -63,10 +64,11 @@ impl PageTable { } } - fn get_or_create_next_table(&mut self, index: usize, hhdm: u64) -> &mut Self { +fn get_or_create_next_table(&mut self, index: usize, hhdm: u64) -> &mut Self { if self.entries[index] & PageTableFlags::PRESENT.bits() == 0 { - let pt_phys = pmm::alloc_page().expect("VMM: Table allocation failed"); + let pt_phys = pmm_alloc().expect("VMM: Out of memory for page tables"); let pt_virt = pt_phys.to_virt(hhdm); + unsafe { core::ptr::write_bytes(pt_virt.as_mut_ptr::(), 0, 4096); } self.entries[index] = pt_phys.0 | (PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER).bits(); @@ -75,3 +77,8 @@ impl PageTable { unsafe { &mut *next_pt_phys.to_virt(hhdm).as_mut_ptr() } } } + +pub fn pmm_alloc() -> Option { + PMM.lock().as_mut()?.alloc_frame() +} + diff --git a/kernel/src/mem/pm_manages.rs b/kernel/src/mem/pm_manages.rs new file mode 100644 index 0000000..30b86b1 --- /dev/null +++ b/kernel/src/mem/pm_manages.rs @@ -0,0 +1,25 @@ +use crate::cap::{Capability, CapObject, Relation, CapRights}; +use crate::mem::address::PhysAddr; + +pub struct PMActor { + pub root_untyped: Capability, + pub managed_range: (PhysAddr, PhysAddr), +} + +impl PMActor { + pub fn carve_region(&self, offset: usize, size: usize) -> Capability { + if let CapObject::Memory { phys, .. } = self.root_untyped.object { + Capability { + object: CapObject::Memory { + phys: PhysAddr(phys.0 + offset as u64), + size_pages: size / 4096, + }, + rights: CapRights::READ | CapRights::WRITE | CapRights::GRANT, + relation: Relation::Strong, + token_sig: 0xDEAD_BEEF, + } + } else { + panic!("PM: Root is not memory!"); + } + } +} diff --git a/kernel/src/mem/pmm.rs b/kernel/src/mem/pmm.rs index 38e744f..fa98a69 100644 --- a/kernel/src/mem/pmm.rs +++ b/kernel/src/mem/pmm.rs @@ -1,8 +1,8 @@ -use crate::mem::address::{PhysAddr}; +use crate::mem::address::PhysAddr; +use crate::mem::allocator::Locked; pub const PAGE_SIZE: u64 = 4096; -#[allow(dead_code)] pub struct BitmapPMM { bitmap: &'static mut [u8], total_pages: usize, @@ -10,7 +10,7 @@ pub struct BitmapPMM { last_idx: usize, } -static mut PMM: Option = None; +pub static PMM: Locked> = Locked::new(None); impl BitmapPMM { #[allow(dead_code)] @@ -33,7 +33,6 @@ impl BitmapPMM { .expect("PMM: Insufficient memory for bitmap"); let bitmap_virt_ptr = (bitmap_phys_addr + hhdm_offset) as *mut u8; - // Оборачиваем небезопасные операции let bitmap_slice = unsafe { core::slice::from_raw_parts_mut(bitmap_virt_ptr, bitmap_size) }; bitmap_slice.fill(0xFF); @@ -58,9 +57,7 @@ impl BitmapPMM { pmm.lock_frame(PhysAddr(0)); - unsafe { - core::ptr::write(core::ptr::addr_of_mut!(PMM), Some(pmm)); - } + *PMM.lock() = Some(pmm); } pub fn free_frame(&mut self, phys_addr: PhysAddr) { @@ -87,42 +84,48 @@ impl BitmapPMM { } } - pub fn alloc_frame(&mut self) -> Option { - for i in self.last_idx..self.total_pages { - let byte_idx = i / 8; - if self.bitmap[byte_idx] == 0xFF { continue; } - - let bit_idx = i % 8; - if (self.bitmap[byte_idx] & (1 << bit_idx)) == 0 { - let addr = PhysAddr(i as u64 * PAGE_SIZE); - self.lock_frame(addr); - self.last_idx = i; - return Some(addr); +pub fn alloc_frame(&mut self) -> Option { + let start_byte = self.last_idx / 8; + for i in start_byte..(self.bitmap.len()) { + if self.bitmap[i] != 0xFF { + for bit in 0..8 { + let idx = i * 8 + bit; + if idx >= self.total_pages { return None; } + + let addr = PhysAddr(idx as u64 * PAGE_SIZE); + if !self.is_locked(addr) { + self.lock_frame(addr); + self.last_idx = idx; + return Some(addr); + } + } } } None } -} -#[allow(dead_code)] -pub unsafe fn get_pmm_unchecked() -> &'static BitmapPMM { - let pmm_ptr = core::ptr::addr_of!(PMM); - unsafe { (*pmm_ptr).as_ref().expect("PMM: Not initialized") } -} - -pub fn alloc_page() -> Option { - unsafe { - let pmm_ptr = core::ptr::addr_of_mut!(PMM); - (*pmm_ptr).as_mut()?.alloc_frame() +#[inline] + fn is_locked(&self, addr: PhysAddr) -> bool { + let idx = (addr.0 / PAGE_SIZE) as usize; + (self.bitmap[idx / 8] & (1 << (idx % 8))) != 0 } } -#[allow(dead_code)] -pub fn free_page(addr: PhysAddr) { - unsafe { - let pmm_ptr = core::ptr::addr_of_mut!(PMM); - if let Some(pmm) = (*pmm_ptr).as_mut() { - pmm.free_frame(addr); - } + +pub fn alloc_frame() -> Option { + PMM.lock().as_mut()?.alloc_frame() +} + +pub fn free_frame(addr: PhysAddr) { + if let Some(pmm) = PMM.lock().as_mut() { + pmm.free_frame(addr); + } +} + +pub fn get_stats() -> (usize, usize) { + if let Some(pmm) = PMM.lock().as_ref() { + (pmm.used_pages(), pmm.total_pages()) + } else { + (0, 0) } }