feat: root: done

This commit is contained in:
Paul Pan 2024-06-16 23:35:48 +08:00
parent 72a04f2905
commit 92801fccdc
4 changed files with 111 additions and 38 deletions

View File

@ -1,18 +1,21 @@
use crate::arch::layout::{mmap_phys_to_virt, mmap_virt_to_phys, PAGE_BITS, PAGE_SIZE}; 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::arch::vspace::{copy_kernel_pagetable, map_range, RAM_ALLOCATOR};
use crate::arch::FDT;
use crate::objects::*; use crate::objects::*;
use crate::plat::trap::TrapContextOps; use crate::plat::trap::TrapContextOps;
use crate::scheduler::SCHEDULER; use crate::scheduler::SCHEDULER;
use crate::vspace::*; use crate::vspace::*;
use core::{cmp::min, ops::Range}; use core::{cmp::min, ops::Range, sync::atomic::Ordering};
use elf::{abi::*, endian::AnyEndian, ElfBytes}; use elf::{abi::*, endian::AnyEndian, ElfBytes};
use fdt::Fdt; use fdt::Fdt;
use log::{debug, trace}; use log::{debug, trace};
use spin::Lazy; use spin::Lazy;
use uapi::{cspace::CNodeSlot, error::SysError}; use uapi::{consts::*, cspace::CNodeSlot, error::SysError};
use utils::{addr::*, bin::prev_power_of_two}; use utils::{addr::*, bin::prev_power_of_two};
const ROOT_ASID: usize = 1;
const ROOT_CNODE_SIZE: usize = 128; const ROOT_CNODE_SIZE: usize = 128;
static mut ROOT_CNODE: Lazy<[CapEntry; ROOT_CNODE_SIZE]> = static mut ROOT_CNODE: Lazy<[CapEntry; ROOT_CNODE_SIZE]> =
Lazy::new(|| core::array::from_fn(|_| CapEntry::new(NullCap::mint()))); Lazy::new(|| core::array::from_fn(|_| CapEntry::new(NullCap::mint())));
@ -47,7 +50,7 @@ pub fn setup_root_server(fdt: &Fdt) {
load_root_server(cnode_obj, &mut free_idx, fdt); load_root_server(cnode_obj, &mut free_idx, fdt);
// 6. map other memory (fdt, initrd) // 6. map other memory (fdt, initrd)
// TODO: map fdt and initrd map_misc(cnode_obj, &mut free_idx, fdt);
// 7. insert into scheduler // 7. insert into scheduler
SCHEDULER.add( SCHEDULER.add(
@ -217,22 +220,48 @@ fn create_objects(cnode_obj: &mut CNodeObject, free_idx: &mut usize, cnode_entry
let tcb = tcb_cap.as_object_mut(); let tcb = tcb_cap.as_object_mut();
*tcb = TcbObject::new(); *tcb = TcbObject::new();
assert!(tcb.tid() == ROOT_ASID, "init: root tcb tid is invalid");
tcb.set_cspace(cnode_entry.clone()); tcb.set_cspace(cnode_entry.clone());
tcb.set_vspace(vspace.clone()); tcb.set_vspace(vspace.clone());
tcb.set_state(tcb::ThreadState::Idle); tcb.set_state(tcb::ThreadState::Idle);
} }
} }
fn load_root_server(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt) { macro_rules! get_root_table {
let mut table = { ($cnode_obj:expr) => {{
let root = &cnode_obj[CNodeSlot::VSpaceCap as usize]; let root = &$cnode_obj[CNodeSlot::VSpaceCap as usize];
let root_vaddr = TableCap::try_from(root).unwrap().as_object::<Level0>().vaddr(); let root_vaddr = TableCap::try_from(root).unwrap().as_object::<Level0>().vaddr();
// use unsafe to workaround borrow checker // use unsafe to workaround borrow checker
unsafe { Table::new(root_vaddr) } unsafe { Table::new(root_vaddr) }
}; }};
}
let mut rootfs = unsafe { // TODO: figure out a better way to create a `load_page` function for `map_range`
macro_rules! create_load_page {
($cnode_obj:expr, $free_idx:expr) => {
|mapped_addr| {
trace!("[root] allocating pagetable at slot #{}", $free_idx);
alloc_objects::<TableObject>($cnode_obj, *$free_idx, PAGE_BITS, *$free_idx..*$free_idx + 1);
*$free_idx += 1;
let page = &$cnode_obj[*$free_idx - 1];
let page = TableCap::try_from(page).unwrap();
page.set_mapped(true);
page.set_mapped_asid(ROOT_ASID);
page.set_mapped_vaddr(mapped_addr);
let table: Table<Level0> = page.as_object(); // Any level is fine
table.paddr()
}
};
}
fn get_rootfs(fdt: &Fdt) -> cpio::Reader<'static> {
let chosen = fdt.find_node("/chosen").expect("/chosen is required"); let chosen = fdt.find_node("/chosen").expect("/chosen is required");
let initrd_start = chosen let initrd_start = chosen
@ -249,13 +278,17 @@ fn load_root_server(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt
.as_usize() .as_usize()
.unwrap(); .unwrap();
let vaddr = mmap_phys_to_virt(PhysAddr(initrd_start)); let vaddr = unsafe { mmap_phys_to_virt(PhysAddr(initrd_start)) };
let len = initrd_end - initrd_start; let len = initrd_end - initrd_start;
let data = core::slice::from_raw_parts(vaddr.as_const_ptr(), len); let data = unsafe { core::slice::from_raw_parts(vaddr.as_const_ptr(), len) };
cpio::Reader::new(data) cpio::Reader::new(data)
}; }
fn load_root_server(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt) {
let mut table = get_root_table!(cnode_obj);
let mut rootfs = get_rootfs(fdt);
let root_entry = rootfs let root_entry = rootfs
.find_map(|entry| { .find_map(|entry| {
if let Ok(entry) = entry { if let Ok(entry) = entry {
@ -322,7 +355,7 @@ fn load_root_server(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt
let mem = frame.as_object_mut(); let mem = frame.as_object_mut();
copy(cur, mem); copy(cur, mem);
// map frame to vspace // map attributes
let vaddr = seg_addr + cur; let vaddr = seg_addr + cur;
let paddr = unsafe { mmap_virt_to_phys(VirtAddr::from(mem as *const _ as *const u8)) }; let paddr = unsafe { mmap_virt_to_phys(VirtAddr::from(mem as *const _ as *const u8)) };
let attr = { let attr = {
@ -341,19 +374,12 @@ fn load_root_server(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt
attr attr
}; };
let alloc_page = || { // manually set frame object
trace!("[initrd] allocating pagetable at slot #{}", free_idx); frame.set_mapped_asid(ROOT_ASID);
frame.set_mapped_vaddr(vaddr);
alloc_objects::<TableObject>(cnode_obj, *free_idx, PAGE_BITS, *free_idx..*free_idx + 1);
*free_idx += 1;
let page = &cnode_obj[*free_idx - 1];
let page = TableCap::try_from(page).unwrap();
let table: Table<Level0> = page.as_object(); // Any level is fine
table.paddr()
};
// map to vspace
let alloc_page = create_load_page!(cnode_obj, free_idx);
map_range(alloc_page, &mut table, vaddr, paddr, block_size, attr); map_range(alloc_page, &mut table, vaddr, paddr, block_size, attr);
// update pointer // update pointer
@ -365,3 +391,36 @@ fn load_root_server(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt
let tcb = tcb_cap.as_object_mut(); let tcb = tcb_cap.as_object_mut();
tcb.trapframe.set_pc(root_elf.ehdr.e_entry as usize); tcb.trapframe.set_pc(root_elf.ehdr.e_entry as usize);
} }
fn map_misc(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt) {
// NOTE: there are no FrameObjects referencing these memory regions
let mut table = get_root_table!(cnode_obj);
let attr = MapAttr::USER_ACCESSIBLE | MapAttr::READABLE;
// map fdt
{
assert!(fdt.total_size() < ROOT_FDT_MAX_SIZE, "init: fdt is too large");
let fdt_vaddr = FDT.load(Ordering::Relaxed);
let fdt_vaddr = VirtAddr::from(fdt_vaddr);
let fdt_paddr = unsafe { mmap_virt_to_phys(fdt_vaddr) };
let fdt_size = align_up(fdt.total_size(), PAGE_SIZE);
let alloc_page = create_load_page!(cnode_obj, free_idx);
map_range(alloc_page, &mut table, ROOT_FDT_ADDR, fdt_paddr, fdt_size, attr);
}
// map rootfs
{
let rootfs = get_rootfs(fdt);
assert!(rootfs.data().len() < ROOT_INITRD_MAX_SIZE, "init: initrd is too large");
let initrd_vaddr = VirtAddr::from(rootfs.data().as_ptr());
let initrd_paddr = unsafe { mmap_virt_to_phys(initrd_vaddr) };
let initrd_size = align_up(rootfs.data().len(), PAGE_SIZE);
let alloc_page = create_load_page!(cnode_obj, free_idx);
map_range(alloc_page, &mut table, ROOT_INITRD_ADDR, initrd_paddr, initrd_size, attr);
}
}

View File

@ -166,6 +166,10 @@ impl<'a> Reader<'a> {
pub fn new(data: &'a [u8]) -> Self { pub fn new(data: &'a [u8]) -> Self {
Reader { data } Reader { data }
} }
pub fn data(&self) -> &'a [u8] {
self.data
}
} }
impl<'a> Iterator for Reader<'a> { impl<'a> Iterator for Reader<'a> {

9
uapi/src/consts.rs Normal file
View File

@ -0,0 +1,9 @@
use utils::{addr::VirtAddr, size::MIB};
pub const ROOT_FDT_ADDR: VirtAddr = VirtAddr(0xfbf0_0000);
pub const ROOT_FDT_MAX_SIZE: usize = 1 * MIB;
pub const ROOT_FDT_MAX_BITS: usize = ROOT_FDT_MAX_SIZE.ilog2() as usize;
pub const ROOT_INITRD_ADDR: VirtAddr = VirtAddr(0xfc00_0000);
pub const ROOT_INITRD_MAX_SIZE: usize = 64 * MIB;
pub const ROOT_INITRD_MAX_BITS: usize = ROOT_INITRD_MAX_SIZE.ilog2() as usize;

View File

@ -5,6 +5,7 @@
extern crate num_derive; extern crate num_derive;
pub mod cap; pub mod cap;
pub mod consts;
pub mod cspace; pub mod cspace;
pub mod error; pub mod error;
pub mod fault; pub mod fault;