mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: root: done
This commit is contained in:
parent
72a04f2905
commit
92801fccdc
@ -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,45 +220,75 @@ 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) }
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let mut rootfs = unsafe {
|
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
|
||||||
.properties()
|
.properties()
|
||||||
.find(|n| n.name == "linux,initrd-start")
|
.find(|n| n.name == "linux,initrd-start")
|
||||||
.expect("linux,initrd-start is required")
|
.expect("linux,initrd-start is required")
|
||||||
.as_usize()
|
.as_usize()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let initrd_end = chosen
|
let initrd_end = chosen
|
||||||
.properties()
|
.properties()
|
||||||
.find(|n| n.name == "linux,initrd-end")
|
.find(|n| n.name == "linux,initrd-end")
|
||||||
.expect("linux,initrd-end is required")
|
.expect("linux,initrd-end is required")
|
||||||
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
9
uapi/src/consts.rs
Normal 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;
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user