mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: root: drop boot info and refactor
This commit is contained in:
parent
6eb3a062c1
commit
78133158b6
@ -2,8 +2,7 @@ use crate::arch::{layout::mmap_phys_to_virt, trap::TrapContext, vspace::*};
|
|||||||
use crate::{objects::*, plat::trap::TrapContextOps, vspace::*};
|
use crate::{objects::*, plat::trap::TrapContextOps, vspace::*};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use log::debug;
|
use uapi::{cap::ObjectType, error::SysResult, fault::*, syscall::*};
|
||||||
use uapi::{cap::ObjectType, error::SysResult, fault::Fault, syscall::MessageInfo};
|
|
||||||
use utils::{
|
use utils::{
|
||||||
addr::*,
|
addr::*,
|
||||||
linked_list::{Link, LinkHelper},
|
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) {
|
pub fn configure_idle_thread(&mut self) {
|
||||||
self.trapframe.configure_idle_thread();
|
self.trapframe.configure_idle_thread();
|
||||||
self.vspace = CapEntry::new(TableCap::mint(unsafe { get_current_pagetable().paddr() }));
|
self.vspace = CapEntry::new(TableCap::mint(unsafe { get_current_pagetable().paddr() }));
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
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::objects::*;
|
use crate::objects::*;
|
||||||
|
use crate::plat::trap::TrapContextOps;
|
||||||
|
use crate::scheduler::SCHEDULER;
|
||||||
use crate::vspace::*;
|
use crate::vspace::*;
|
||||||
use core::{cmp::min, ops::Range};
|
use core::{cmp::min, ops::Range};
|
||||||
use elf::{abi::*, endian::AnyEndian, ElfBytes};
|
use elf::{abi::*, endian::AnyEndian, ElfBytes};
|
||||||
@ -30,25 +32,32 @@ pub fn setup_root_server(fdt: &Fdt) {
|
|||||||
let cnode_obj = cnode.as_object_mut();
|
let cnode_obj = cnode.as_object_mut();
|
||||||
cnode_obj[CNodeSlot::CNodeCap as usize] = cnode_entry.clone();
|
cnode_obj[CNodeSlot::CNodeCap as usize] = cnode_entry.clone();
|
||||||
|
|
||||||
// 2. insert current free memory [CNodeSlot::UntypedCap, memory_idx)
|
let mut free_idx = CNodeSlot::UntypedCap as usize;
|
||||||
let memory_idx = create_untyped_memory(cnode_obj);
|
|
||||||
|
|
||||||
// 3. insert device memory [memory_idx, device_idx)
|
// 2. insert current free memory
|
||||||
let device_idx = create_untyped_device(cnode_obj, memory_idx, fdt);
|
create_untyped_memory(cnode_obj, &mut free_idx);
|
||||||
|
|
||||||
|
// 3. insert device memory
|
||||||
|
create_untyped_device(cnode_obj, &mut free_idx, fdt);
|
||||||
|
|
||||||
// 4. create objects
|
// 4. create objects
|
||||||
create_objects(cnode_obj, device_idx);
|
create_objects(cnode_obj, &mut free_idx, &cnode_entry);
|
||||||
|
|
||||||
// 5. load root server
|
// 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)
|
// 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 {
|
fn create_untyped_memory(cnode_obj: &mut CNodeObject, free_idx: &mut usize) {
|
||||||
let mut memory_idx = CNodeSlot::UntypedCap as usize;
|
|
||||||
let mut ram = RAM_ALLOCATOR.lock();
|
let mut ram = RAM_ALLOCATOR.lock();
|
||||||
ram.blocks_mut()
|
ram.blocks_mut()
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@ -87,25 +96,22 @@ fn create_untyped_memory(cnode_obj: &mut CNodeObject) -> usize {
|
|||||||
|
|
||||||
trace!(
|
trace!(
|
||||||
"[root] creating untyped memory: {}: {:?} -> {:?}, slot #{}",
|
"[root] creating untyped memory: {}: {:?} -> {:?}, slot #{}",
|
||||||
memory_idx,
|
free_idx,
|
||||||
start,
|
start,
|
||||||
start + (1 << bits),
|
start + (1 << bits),
|
||||||
memory_idx
|
free_idx
|
||||||
);
|
);
|
||||||
|
|
||||||
let cap = UntypedCap::mint(0, bits, false, start);
|
let cap = UntypedCap::mint(0, bits, false, start);
|
||||||
let cap_entry = CapEntry::new(cap);
|
let cap_entry = CapEntry::new(cap);
|
||||||
cnode_obj[memory_idx] = cap_entry;
|
cnode_obj[*free_idx] = cap_entry;
|
||||||
memory_idx += 1;
|
*free_idx += 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(ram.blocks().iter().all(|b| b.is_none()));
|
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 {
|
fn create_untyped_device(cnode_obj: &mut CNodeObject, free_idx: &mut usize, fdt: &Fdt) {
|
||||||
let mut device_idx = memory_idx;
|
|
||||||
let memory = fdt.memory();
|
let memory = fdt.memory();
|
||||||
|
|
||||||
fdt.all_nodes().filter_map(|n| n.reg()).for_each(|r| {
|
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!(
|
trace!(
|
||||||
"[root] creating untyped device: {}: {:?} -> {:?}, slot #{}",
|
"[root] creating untyped device: {}: {:?} -> {:?}, slot #{}",
|
||||||
device_idx,
|
free_idx,
|
||||||
start,
|
start,
|
||||||
start + (1 << bits),
|
start + (1 << bits),
|
||||||
device_idx
|
free_idx
|
||||||
);
|
);
|
||||||
|
|
||||||
let cap = UntypedCap::mint(0, bits, true, start);
|
let cap = UntypedCap::mint(0, bits, true, start);
|
||||||
let cap_entry = CapEntry::new(cap);
|
let cap_entry = CapEntry::new(cap);
|
||||||
cnode_obj[device_idx] = cap_entry;
|
cnode_obj[*free_idx] = cap_entry;
|
||||||
device_idx += 1;
|
*free_idx += 1;
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
device_idx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_objects<T: KernelObject + ?Sized>(
|
fn alloc_objects<T: KernelObject + ?Sized>(
|
||||||
cnode_obj: &mut CNodeObject,
|
cnode_obj: &mut CNodeObject,
|
||||||
end_idx: usize,
|
free_idx: usize,
|
||||||
user_obj_bits: usize,
|
user_obj_bits: usize,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
) {
|
) {
|
||||||
@ -160,12 +164,12 @@ fn alloc_objects<T: KernelObject + ?Sized>(
|
|||||||
|
|
||||||
let (memory, slots) = {
|
let (memory, slots) = {
|
||||||
let (prologue, remain) = cnode_obj.split_at_mut(untyped_start);
|
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 {
|
match range {
|
||||||
r if r.end <= untyped_start => (memory, &mut prologue[r]),
|
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)]),
|
r if r.start >= free_idx => (memory, &mut epilogue[(r.start - free_idx)..(r.end - free_idx)]),
|
||||||
_ => panic!("init: slot range overlaps with untyped memory"),
|
_ => panic!("init: slot range overlaps with allocated objects"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,35 +191,39 @@ fn alloc_objects<T: KernelObject + ?Sized>(
|
|||||||
panic!("init: untyped memory is exhausted");
|
panic!("init: untyped memory is exhausted");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_objects(cnode_obj: &mut CNodeObject, end_idx: usize) {
|
fn create_objects(cnode_obj: &mut CNodeObject, free_idx: &mut usize, cnode_entry: &CapEntry) {
|
||||||
// tcb
|
|
||||||
{
|
|
||||||
let tcb_idx = CNodeSlot::TcbCap as usize;
|
|
||||||
trace!("[root] allocating tcb object at slot #{}", tcb_idx);
|
|
||||||
alloc_objects::<TcbObject>(cnode_obj, end_idx, 0, tcb_idx..tcb_idx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// vspace
|
// vspace
|
||||||
{
|
{
|
||||||
// root
|
// root
|
||||||
let vspace_idx = CNodeSlot::VSpaceCap as usize;
|
let vspace_idx = CNodeSlot::VSpaceCap as usize;
|
||||||
trace!("[root] allocating vspace object at slot #{}", vspace_idx);
|
trace!("[root] allocating vspace object at slot #{}", vspace_idx);
|
||||||
alloc_objects::<TableObject>(cnode_obj, end_idx, PAGE_BITS, vspace_idx..vspace_idx + 1);
|
alloc_objects::<TableObject>(cnode_obj, *free_idx, PAGE_BITS, vspace_idx..vspace_idx + 1);
|
||||||
|
|
||||||
// copy pagetable
|
// copy pagetable
|
||||||
let root = &cnode_obj[vspace_idx];
|
let root = &cnode_obj[vspace_idx];
|
||||||
copy_kernel_pagetable(root);
|
copy_kernel_pagetable(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bootinfo
|
// tcb
|
||||||
{
|
{
|
||||||
let bootinfo_idx = CNodeSlot::BootInfoFrameCap as usize;
|
let tcb_idx = CNodeSlot::TcbCap as usize;
|
||||||
trace!("[root] allocating bootinfo object at slot #{}", bootinfo_idx);
|
trace!("[root] allocating tcb object at slot #{}", tcb_idx);
|
||||||
alloc_objects::<FrameObject>(cnode_obj, end_idx, PAGE_BITS, bootinfo_idx..bootinfo_idx + 1);
|
alloc_objects::<TcbObject>(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 mut table = {
|
||||||
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();
|
||||||
@ -261,7 +269,6 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u
|
|||||||
|
|
||||||
let root_elf = ElfBytes::<AnyEndian>::minimal_parse(root_entry.data()).expect("init: invalid root server");
|
let root_elf = ElfBytes::<AnyEndian>::minimal_parse(root_entry.data()).expect("init: invalid root server");
|
||||||
|
|
||||||
let mut nxt_slot = end_idx;
|
|
||||||
root_elf
|
root_elf
|
||||||
.segments()
|
.segments()
|
||||||
.expect("init: root server has no 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);
|
debug_assert!(block_size >= PAGE_SIZE);
|
||||||
|
|
||||||
// allocate frame
|
// allocate frame
|
||||||
trace!("[initrd] allocating frame at slot #{}", nxt_slot);
|
trace!("[initrd] allocating frame at slot #{}", free_idx);
|
||||||
alloc_objects::<FrameObject>(cnode_obj, end_idx, block_bits, nxt_slot..nxt_slot + 1);
|
alloc_objects::<FrameObject>(cnode_obj, *free_idx, block_bits, *free_idx..*free_idx + 1);
|
||||||
nxt_slot += 1;
|
*free_idx += 1;
|
||||||
|
|
||||||
// copy data
|
// 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();
|
let mem = frame.as_object_mut();
|
||||||
copy(cur, mem);
|
copy(cur, mem);
|
||||||
|
|
||||||
@ -335,16 +342,16 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u
|
|||||||
};
|
};
|
||||||
|
|
||||||
let alloc_page = || {
|
let alloc_page = || {
|
||||||
trace!("[initrd] allocating pagetable at slot #{}", nxt_slot);
|
trace!("[initrd] allocating pagetable at slot #{}", free_idx);
|
||||||
|
|
||||||
alloc_objects::<TableObject>(cnode_obj, end_idx, PAGE_BITS, nxt_slot..nxt_slot + 1);
|
alloc_objects::<TableObject>(cnode_obj, *free_idx, PAGE_BITS, *free_idx..*free_idx + 1);
|
||||||
nxt_slot += 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 page = TableCap::try_from(page).unwrap();
|
||||||
let table: Table<Level0> = page.as_object(); // Any level is fine
|
let table: Table<Level0> = 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);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ pub enum CNodeSlot {
|
|||||||
TcbCap,
|
TcbCap,
|
||||||
CNodeCap,
|
CNodeCap,
|
||||||
VSpaceCap,
|
VSpaceCap,
|
||||||
BootInfoFrameCap,
|
|
||||||
UntypedCap,
|
UntypedCap,
|
||||||
// IrqControlCap
|
// IrqControlCap
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user