diff --git a/kernel/src/objects/tcb.rs b/kernel/src/objects/tcb.rs index 3f3f8b4..65ad343 100644 --- a/kernel/src/objects/tcb.rs +++ b/kernel/src/objects/tcb.rs @@ -2,8 +2,7 @@ use crate::arch::{layout::mmap_phys_to_virt, trap::TrapContext, vspace::*}; use crate::{objects::*, plat::trap::TrapContextOps, vspace::*}; use core::fmt::Debug; use core::sync::atomic::{AtomicUsize, Ordering}; -use log::debug; -use uapi::{cap::ObjectType, error::SysResult, fault::Fault, syscall::MessageInfo}; +use uapi::{cap::ObjectType, error::SysResult, fault::*, syscall::*}; use utils::{ addr::*, linked_list::{Link, LinkHelper}, @@ -60,6 +59,19 @@ impl TcbObject { } } + pub fn set_cspace(&mut self, cspace: CapEntry) { + CNodeCap::try_from(&cspace).expect("set_cspace: invalid cap"); + self.cspace = cspace; + } + + pub fn set_vspace(&mut self, vspace: CapEntry) { + let cap = TableCap::try_from(&vspace).expect("set_vspace: invalid cap"); + cap.set_mapped(true); + cap.set_mapped_asid(self.tid); + cap.set_mapped_vaddr(VirtAddr(0)); + self.vspace = vspace; + } + pub fn configure_idle_thread(&mut self) { self.trapframe.configure_idle_thread(); self.vspace = CapEntry::new(TableCap::mint(unsafe { get_current_pagetable().paddr() })); diff --git a/kernel/src/root.rs b/kernel/src/root.rs index b2b215b..1d8d78a 100644 --- a/kernel/src/root.rs +++ b/kernel/src/root.rs @@ -1,6 +1,8 @@ use crate::arch::layout::{mmap_phys_to_virt, mmap_virt_to_phys, PAGE_BITS, PAGE_SIZE}; use crate::arch::vspace::{copy_kernel_pagetable, map_range, RAM_ALLOCATOR}; use crate::objects::*; +use crate::plat::trap::TrapContextOps; +use crate::scheduler::SCHEDULER; use crate::vspace::*; use core::{cmp::min, ops::Range}; use elf::{abi::*, endian::AnyEndian, ElfBytes}; @@ -30,25 +32,32 @@ pub fn setup_root_server(fdt: &Fdt) { let cnode_obj = cnode.as_object_mut(); cnode_obj[CNodeSlot::CNodeCap as usize] = cnode_entry.clone(); - // 2. insert current free memory [CNodeSlot::UntypedCap, memory_idx) - let memory_idx = create_untyped_memory(cnode_obj); + let mut free_idx = CNodeSlot::UntypedCap as usize; - // 3. insert device memory [memory_idx, device_idx) - let device_idx = create_untyped_device(cnode_obj, memory_idx, fdt); + // 2. insert current free memory + create_untyped_memory(cnode_obj, &mut free_idx); + + // 3. insert device memory + create_untyped_device(cnode_obj, &mut free_idx, fdt); // 4. create objects - create_objects(cnode_obj, device_idx); + create_objects(cnode_obj, &mut free_idx, &cnode_entry); // 5. load root server - let root_server_idx = load_root_server(cnode_obj, device_idx, fdt); + load_root_server(cnode_obj, &mut free_idx, fdt); // 6. map other memory (fdt, initrd) + // TODO: map fdt and initrd - // 7. setup threads + // 7. insert into scheduler + SCHEDULER.add( + TcbCap::try_from(&cnode_obj[CNodeSlot::TcbCap as usize]) + .unwrap() + .as_object_mut(), + ); } -fn create_untyped_memory(cnode_obj: &mut CNodeObject) -> usize { - let mut memory_idx = CNodeSlot::UntypedCap as usize; +fn create_untyped_memory(cnode_obj: &mut CNodeObject, free_idx: &mut usize) { let mut ram = RAM_ALLOCATOR.lock(); ram.blocks_mut() .iter_mut() @@ -87,25 +96,22 @@ fn create_untyped_memory(cnode_obj: &mut CNodeObject) -> usize { trace!( "[root] creating untyped memory: {}: {:?} -> {:?}, slot #{}", - memory_idx, + free_idx, start, start + (1 << bits), - memory_idx + free_idx ); let cap = UntypedCap::mint(0, bits, false, start); let cap_entry = CapEntry::new(cap); - cnode_obj[memory_idx] = cap_entry; - memory_idx += 1; + cnode_obj[*free_idx] = cap_entry; + *free_idx += 1; }); assert!(ram.blocks().iter().all(|b| b.is_none())); - - memory_idx } -fn create_untyped_device(cnode_obj: &mut CNodeObject, memory_idx: usize, fdt: &Fdt) -> usize { - let mut device_idx = memory_idx; +fn create_untyped_device(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt) { let memory = fdt.memory(); fdt.all_nodes().filter_map(|n| n.reg()).for_each(|r| { @@ -134,25 +140,23 @@ fn create_untyped_device(cnode_obj: &mut CNodeObject, memory_idx: usize, fdt: &F trace!( "[root] creating untyped device: {}: {:?} -> {:?}, slot #{}", - device_idx, + free_idx, start, start + (1 << bits), - device_idx + free_idx ); let cap = UntypedCap::mint(0, bits, true, start); let cap_entry = CapEntry::new(cap); - cnode_obj[device_idx] = cap_entry; - device_idx += 1; + cnode_obj[*free_idx] = cap_entry; + *free_idx += 1; }) }); - - device_idx } fn alloc_objects( cnode_obj: &mut CNodeObject, - end_idx: usize, + free_idx: usize, user_obj_bits: usize, range: Range, ) { @@ -160,12 +164,12 @@ fn alloc_objects( let (memory, slots) = { let (prologue, remain) = cnode_obj.split_at_mut(untyped_start); - let (memory, epilogue) = remain.split_at_mut(end_idx - untyped_start); + let (memory, epilogue) = remain.split_at_mut(free_idx - untyped_start); match range { r if r.end <= untyped_start => (memory, &mut prologue[r]), - r if r.start >= end_idx => (memory, &mut epilogue[(r.start - end_idx)..(r.end - end_idx)]), - _ => panic!("init: slot range overlaps with untyped memory"), + r if r.start >= free_idx => (memory, &mut epilogue[(r.start - free_idx)..(r.end - free_idx)]), + _ => panic!("init: slot range overlaps with allocated objects"), } }; @@ -187,35 +191,39 @@ fn alloc_objects( panic!("init: untyped memory is exhausted"); } -fn create_objects(cnode_obj: &mut CNodeObject, end_idx: usize) { - // tcb - { - let tcb_idx = CNodeSlot::TcbCap as usize; - trace!("[root] allocating tcb object at slot #{}", tcb_idx); - alloc_objects::(cnode_obj, end_idx, 0, tcb_idx..tcb_idx + 1); - } - +fn create_objects(cnode_obj: &mut CNodeObject, free_idx: &mut usize, cnode_entry: &CapEntry) { // vspace { // root let vspace_idx = CNodeSlot::VSpaceCap as usize; trace!("[root] allocating vspace object at slot #{}", vspace_idx); - alloc_objects::(cnode_obj, end_idx, PAGE_BITS, vspace_idx..vspace_idx + 1); + alloc_objects::(cnode_obj, *free_idx, PAGE_BITS, vspace_idx..vspace_idx + 1); // copy pagetable let root = &cnode_obj[vspace_idx]; copy_kernel_pagetable(root); } - // bootinfo + // tcb { - let bootinfo_idx = CNodeSlot::BootInfoFrameCap as usize; - trace!("[root] allocating bootinfo object at slot #{}", bootinfo_idx); - alloc_objects::(cnode_obj, end_idx, PAGE_BITS, bootinfo_idx..bootinfo_idx + 1); + let tcb_idx = CNodeSlot::TcbCap as usize; + trace!("[root] allocating tcb object at slot #{}", tcb_idx); + alloc_objects::(cnode_obj, *free_idx, 0, tcb_idx..tcb_idx + 1); + + let tcb = &cnode_obj[CNodeSlot::TcbCap as usize]; + let vspace = &cnode_obj[CNodeSlot::VSpaceCap as usize]; + + let mut tcb_cap = TcbCap::try_from(tcb).unwrap(); + let tcb = tcb_cap.as_object_mut(); + + *tcb = TcbObject::new(); + tcb.set_cspace(cnode_entry.clone()); + tcb.set_vspace(vspace.clone()); + tcb.set_state(tcb::ThreadState::Idle); } } -fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> usize { +fn load_root_server(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt) { let mut table = { let root = &cnode_obj[CNodeSlot::VSpaceCap as usize]; let root_vaddr = TableCap::try_from(root).unwrap().as_object::().vaddr(); @@ -261,7 +269,6 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u let root_elf = ElfBytes::::minimal_parse(root_entry.data()).expect("init: invalid root server"); - let mut nxt_slot = end_idx; root_elf .segments() .expect("init: root server has no segments") @@ -306,12 +313,12 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u debug_assert!(block_size >= PAGE_SIZE); // allocate frame - trace!("[initrd] allocating frame at slot #{}", nxt_slot); - alloc_objects::(cnode_obj, end_idx, block_bits, nxt_slot..nxt_slot + 1); - nxt_slot += 1; + trace!("[initrd] allocating frame at slot #{}", free_idx); + alloc_objects::(cnode_obj, *free_idx, block_bits, *free_idx..*free_idx + 1); + *free_idx += 1; // copy data - let mut frame = FrameCap::try_from(&cnode_obj[nxt_slot - 1]).unwrap(); + let mut frame = FrameCap::try_from(&cnode_obj[*free_idx - 1]).unwrap(); let mem = frame.as_object_mut(); copy(cur, mem); @@ -335,16 +342,16 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u }; let alloc_page = || { - trace!("[initrd] allocating pagetable at slot #{}", nxt_slot); + trace!("[initrd] allocating pagetable at slot #{}", free_idx); - alloc_objects::(cnode_obj, end_idx, PAGE_BITS, nxt_slot..nxt_slot + 1); - nxt_slot += 1; + alloc_objects::(cnode_obj, *free_idx, PAGE_BITS, *free_idx..*free_idx + 1); + *free_idx += 1; - let page = &cnode_obj[nxt_slot - 1]; + let page = &cnode_obj[*free_idx - 1]; let page = TableCap::try_from(page).unwrap(); let table: Table = page.as_object(); // Any level is fine - unsafe { mmap_virt_to_phys(table.vaddr()) } + table.paddr() }; map_range(alloc_page, &mut table, vaddr, paddr, block_size, attr); @@ -354,5 +361,7 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u } }); - nxt_slot + let mut tcb_cap = TcbCap::try_from(&cnode_obj[CNodeSlot::TcbCap as usize]).unwrap(); + let tcb = tcb_cap.as_object_mut(); + tcb.trapframe.set_pc(root_elf.ehdr.e_entry as usize); } diff --git a/uapi/src/cspace.rs b/uapi/src/cspace.rs index 3840fe1..98d7ecc 100644 --- a/uapi/src/cspace.rs +++ b/uapi/src/cspace.rs @@ -4,7 +4,6 @@ pub enum CNodeSlot { TcbCap, CNodeCap, VSpaceCap, - BootInfoFrameCap, UntypedCap, // IrqControlCap }