mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
Compare commits
No commits in common. "93c4d3c5fbbcb2ea811155b55cfc50b464ea29a3" and "bf6297c5ace3952bbaed3b2083735eb97907f804" have entirely different histories.
93c4d3c5fb
...
bf6297c5ac
@ -1,4 +1,4 @@
|
|||||||
pub const TIMER_TICKS: u64 = 100_000;
|
pub const TIMER_TICKS: u64 = 100_000; // 100ms
|
||||||
|
|
||||||
// devices
|
// devices
|
||||||
pub const UART0_BASE: usize = 0x1000_0000;
|
pub const UART0_BASE: usize = 0x1000_0000;
|
||||||
|
@ -79,7 +79,7 @@ impl TrapContextOps for TrapContext {
|
|||||||
T::Interrupt(I::SupervisorTimer) => {
|
T::Interrupt(I::SupervisorTimer) => {
|
||||||
Timer::do_tick();
|
Timer::do_tick();
|
||||||
if !from_kernel {
|
if !from_kernel {
|
||||||
tcb.do_tick();
|
tcb.timer_tick();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
T::Exception(E::UserEnvCall) => {
|
T::Exception(E::UserEnvCall) => {
|
||||||
@ -110,16 +110,16 @@ impl TrapContextOps for TrapContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_reg(&self, index: usize) -> usize {
|
fn get_reg(&self, index: usize) -> usize {
|
||||||
// x9(a0) ~ x16(a7): Function arguments
|
// x10 ~ x17: Function arguments
|
||||||
assert!(index < 8, "TrapContext get_reg index out of range");
|
assert!(index < 8, "TrapContext get_reg index out of range");
|
||||||
self.gprs[index + 9]
|
self.gprs[index + 10]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_reg(&mut self, index: usize, value: usize) {
|
fn set_reg(&mut self, index: usize, value: usize) {
|
||||||
// x9(a0) ~ x16(a7): Function arguments
|
// x10 ~ x17: Function arguments
|
||||||
// x9(a0) ~ x10(a1): Function return values
|
// x10 ~ x11: Function return values
|
||||||
assert!(index < 8, "TrapContext set_reg index out of range");
|
assert!(index < 8, "TrapContext set_reg index out of range");
|
||||||
self.gprs[index + 9] = value;
|
self.gprs[index + 10] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,12 +38,6 @@ trait GenericPhysAddrPage: AddressOps {
|
|||||||
self.extract_ppn() << Self::PPN_OFFSET
|
self.extract_ppn() << Self::PPN_OFFSET
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_ppn(ppn: usize) -> usize {
|
|
||||||
let addr = ppn << Self::PG_OFFSET;
|
|
||||||
let bits = Self::PG_OFFSET + Self::PPN_BITS;
|
|
||||||
sign_extend(addr, bits)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_pte(pte: usize) -> usize {
|
fn from_pte(pte: usize) -> usize {
|
||||||
let addr = ((pte & Self::PTE_PPN_MASK) >> Self::PPN_OFFSET) << Self::PG_OFFSET;
|
let addr = ((pte & Self::PTE_PPN_MASK) >> Self::PPN_OFFSET) << Self::PG_OFFSET;
|
||||||
let bits = Self::PPN_BITS + Self::PG_OFFSET;
|
let bits = Self::PPN_BITS + Self::PG_OFFSET;
|
||||||
|
@ -21,10 +21,6 @@ impl PhysAddrPage for PhysAddr {
|
|||||||
GenericPhysAddrPage::extract_ppn_shifted(self)
|
GenericPhysAddrPage::extract_ppn_shifted(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_ppn(ppn: usize) -> PhysAddr {
|
|
||||||
PhysAddr::from(<PhysAddr as GenericPhysAddrPage>::from_ppn(ppn))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_pte(pte: usize) -> PhysAddr {
|
fn from_pte(pte: usize) -> PhysAddr {
|
||||||
PhysAddr::from(<PhysAddr as GenericPhysAddrPage>::from_pte(pte))
|
PhysAddr::from(<PhysAddr as GenericPhysAddrPage>::from_pte(pte))
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,9 @@ pub unsafe fn setup_kernel_paging() {
|
|||||||
pub unsafe fn install_kernel_pagetable() {
|
pub unsafe fn install_kernel_pagetable() {
|
||||||
info!("Setting up new kernel pagetable");
|
info!("Setting up new kernel pagetable");
|
||||||
|
|
||||||
let paddr = KERNEL_PAGETABLE.lock().as_ref().expect("No kernel pagetable found").paddr();
|
let vaddr = KERNEL_PAGETABLE.lock().as_ref().expect("No kernel pagetable found").vaddr();
|
||||||
|
let paddr = mmap_virt_to_phys(vaddr);
|
||||||
|
|
||||||
install_pagetable(paddr)
|
install_pagetable(paddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +174,7 @@ pub fn copy_kernel_pagetable(root: &CapEntry) {
|
|||||||
let mut root = TableCap::try_from(root).expect("Invalid vspace cap");
|
let mut root = TableCap::try_from(root).expect("Invalid vspace cap");
|
||||||
let to: Table<Level0> = root.as_object_mut();
|
let to: Table<Level0> = root.as_object_mut();
|
||||||
|
|
||||||
for (from, to) in from.entries.iter().zip(to.entries.iter_mut()) {
|
for (i, (from, to)) in from.entries.iter().zip(to.entries.iter_mut()).enumerate() {
|
||||||
if !from.is_valid() {
|
if !from.is_valid() {
|
||||||
to.clear();
|
to.clear();
|
||||||
continue;
|
continue;
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
use crate::{
|
use crate::{arch::layout::PAGE_SIZE, vspace::*};
|
||||||
arch::layout::{mmap_virt_to_phys, PAGE_SIZE},
|
|
||||||
vspace::*,
|
|
||||||
};
|
|
||||||
use utils::addr::*;
|
use utils::addr::*;
|
||||||
|
|
||||||
impl<'a, T: TableLevel> TableOps<'a, T> for Table<'a, T> {
|
impl<'a, T: TableLevel> TableOps<'a, T> for Table<'a, T> {
|
||||||
@ -18,10 +15,6 @@ impl<'a, T: TableLevel> TableOps<'a, T> for Table<'a, T> {
|
|||||||
VirtAddr::from(self.entries.as_ptr())
|
VirtAddr::from(self.entries.as_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paddr(&self) -> PhysAddr {
|
|
||||||
unsafe { mmap_virt_to_phys(self.vaddr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map(&mut self, from: VirtAddr, to: PhysAddr, attr: MapAttr) -> PageResult {
|
fn map(&mut self, from: VirtAddr, to: PhysAddr, attr: MapAttr) -> PageResult {
|
||||||
if !from.is_aligned(T::LEVEL_SIZE) || !to.is_aligned(PAGE_SIZE) {
|
if !from.is_aligned(T::LEVEL_SIZE) || !to.is_aligned(PAGE_SIZE) {
|
||||||
return Err(PageError::NotAligned);
|
return Err(PageError::NotAligned);
|
||||||
|
@ -12,7 +12,7 @@ pub static ALLOC_COUNT: core::sync::atomic::AtomicUsize = core::sync::atomic::At
|
|||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
fn alloc_callback() {
|
fn alloc_callback() {
|
||||||
ALLOC_COUNT.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
|
let cnt = ALLOC_COUNT.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(debug_assertions, tracer::trace_callback(log = true, callback = alloc_callback))]
|
#[cfg_attr(debug_assertions, tracer::trace_callback(log = true, callback = alloc_callback))]
|
||||||
@ -100,12 +100,3 @@ pub unsafe fn install_pagetable(addr: PhysAddr) {
|
|||||||
riscv::register::satp::set(page_table_mode(), 0, addr.extract_ppn());
|
riscv::register::satp::set(page_table_mode(), 0, addr.extract_ppn());
|
||||||
riscv::asm::sfence_vma_all();
|
riscv::asm::sfence_vma_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn get_current_pagetable() -> Table<'static, Level0> {
|
|
||||||
let satp = riscv::register::satp::read();
|
|
||||||
let paddr = PhysAddr::from_ppn(satp.ppn());
|
|
||||||
if paddr == PhysAddr(0) {
|
|
||||||
panic!("get_current_pagetable() could only be called with MMU enabled!");
|
|
||||||
}
|
|
||||||
Table::new(mmap_phys_to_virt(paddr))
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,7 @@ use crate::plat::console::{set_console, ConsoleDevice, ConsoleDriver, CONSOLE};
|
|||||||
use crate::plat::lowlevel::{Hardware, LowLevel};
|
use crate::plat::lowlevel::{Hardware, LowLevel};
|
||||||
use crate::plat::timer::{Timer, TimerOps};
|
use crate::plat::timer::{Timer, TimerOps};
|
||||||
use crate::plat::trap::{Trap, TrapOps};
|
use crate::plat::trap::{Trap, TrapOps};
|
||||||
use crate::scheduler::{IDLE_THREAD, SCHEDULER};
|
use crate::scheduler::SCHEDULER;
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use fdt::Fdt;
|
use fdt::Fdt;
|
||||||
@ -35,9 +35,6 @@ pub fn rust_main() -> ! {
|
|||||||
Trap::init();
|
Trap::init();
|
||||||
Timer::init();
|
Timer::init();
|
||||||
|
|
||||||
SCHEDULER.init();
|
|
||||||
SCHEDULER.add(&IDLE_THREAD);
|
|
||||||
|
|
||||||
SCHEDULER.schedule();
|
SCHEDULER.schedule();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -4,21 +4,6 @@ use core::fmt::Write;
|
|||||||
use core::sync::atomic::Ordering;
|
use core::sync::atomic::Ordering;
|
||||||
use log::{LevelFilter, Log, Metadata, Record};
|
use log::{LevelFilter, Log, Metadata, Record};
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! print {
|
|
||||||
($($arg:tt)*) => {{
|
|
||||||
use core::fmt::Write;
|
|
||||||
use crate::plat::console::CONSOLE;
|
|
||||||
CONSOLE.lock().write_fmt(format_args!($($arg)*)).unwrap();
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! println {
|
|
||||||
($msg:expr) => { print!(concat!($msg, "\n")) };
|
|
||||||
($fmt:expr, $($arg:tt)*) => { print!(concat!($fmt, "\n"), $($arg)*) };
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SimpleLogger;
|
struct SimpleLogger;
|
||||||
|
|
||||||
impl Log for SimpleLogger {
|
impl Log for SimpleLogger {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::objects::*;
|
use crate::objects::*;
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::fmt::Debug;
|
use core::fmt::{write, Debug};
|
||||||
use uapi::cap::ObjectType;
|
use uapi::cap::ObjectType;
|
||||||
use utils::addr::PhysAddr;
|
use utils::addr::PhysAddr;
|
||||||
use utils::{
|
use utils::{
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
use super::{
|
||||||
|
cap::{CapEntry, RawCap},
|
||||||
|
Cap, KernelObject,
|
||||||
|
};
|
||||||
use crate::arch::layout::mmap_phys_to_virt;
|
use crate::arch::layout::mmap_phys_to_virt;
|
||||||
use crate::objects::*;
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use uapi::{cap::ObjectType, fault::LookupFailure};
|
use uapi::{cap::ObjectType, fault::LookupFailure};
|
||||||
use utils::addr::{AddressOps, PhysAddr};
|
use utils::addr::{AddressOps, PhysAddr};
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
use crate::{arch::layout::mmap_phys_to_virt, objects::*, vspace::*};
|
use super::{cap::RawCap, Cap, KernelObject};
|
||||||
|
use crate::{
|
||||||
|
arch::layout::{mmap_phys_to_virt, PAGE_SIZE},
|
||||||
|
objects::cap::CapEntry,
|
||||||
|
vspace::*,
|
||||||
|
};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use uapi::{
|
use uapi::{
|
||||||
cap::ObjectType,
|
cap::ObjectType,
|
||||||
|
@ -31,10 +31,10 @@ pub mod untyped;
|
|||||||
pub use cap::{CapEntry, RawCap};
|
pub use cap::{CapEntry, RawCap};
|
||||||
pub use cnode::{CNodeCap, CNodeObject};
|
pub use cnode::{CNodeCap, CNodeObject};
|
||||||
pub use frame::{FrameCap, FrameObject};
|
pub use frame::{FrameCap, FrameObject};
|
||||||
pub use null::NullCap;
|
pub use null::{NullCap, NullObject};
|
||||||
pub use table::{TableCap, TableObject};
|
pub use table::{TableCap, TableObject};
|
||||||
pub use tcb::{TcbCap, TcbObject};
|
pub use tcb::{TcbCap, TcbObject};
|
||||||
pub use untyped::UntypedCap;
|
pub use untyped::{UntypedCap, UntypedObject};
|
||||||
|
|
||||||
/// Cap is the high-level wrapper of RawCap, it's a typed reference to RawCap (which is untyped in Rust)
|
/// Cap is the high-level wrapper of RawCap, it's a typed reference to RawCap (which is untyped in Rust)
|
||||||
/// For the typed objects, we should bound it with an empty traits `KernelObject`
|
/// For the typed objects, we should bound it with an empty traits `KernelObject`
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::objects::*;
|
use super::cap::RawCap;
|
||||||
|
use super::{Cap, KernelObject};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use uapi::cap::ObjectType;
|
use uapi::cap::ObjectType;
|
||||||
use utils::addr::PhysAddr;
|
use utils::addr::PhysAddr;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{arch::layout::mmap_phys_to_virt, objects::*, vspace::*};
|
use super::{cap::RawCap, Cap, KernelObject};
|
||||||
|
use crate::{arch::layout::mmap_phys_to_virt, vspace::*};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use uapi::{
|
use uapi::{
|
||||||
cap::ObjectType,
|
cap::ObjectType,
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
use crate::arch::{layout::mmap_phys_to_virt, trap::TrapContext, vspace::*};
|
use super::{
|
||||||
use crate::{objects::*, plat::trap::TrapContextOps, vspace::*};
|
cap::{CapEntry, RawCap},
|
||||||
|
cnode::CNodeCap,
|
||||||
|
null::NullCap,
|
||||||
|
Cap, KernelObject,
|
||||||
|
};
|
||||||
|
use crate::{
|
||||||
|
arch::{layout::mmap_phys_to_virt, trap::TrapContext},
|
||||||
|
plat::trap::TrapContextOps,
|
||||||
|
};
|
||||||
use core::fmt::Debug;
|
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::Fault, syscall::MessageInfo};
|
||||||
use utils::{
|
use utils::{
|
||||||
addr::*,
|
addr::*,
|
||||||
@ -10,9 +16,7 @@ use utils::{
|
|||||||
LinkHelperImpl,
|
LinkHelperImpl,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static TID_ALLOCATOR: AtomicUsize = AtomicUsize::new(0);
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
pub enum ThreadState {
|
pub enum ThreadState {
|
||||||
Inactive,
|
Inactive,
|
||||||
Running,
|
Running,
|
||||||
@ -34,7 +38,6 @@ pub struct TcbObject {
|
|||||||
|
|
||||||
state: ThreadState,
|
state: ThreadState,
|
||||||
time_tick: usize,
|
time_tick: usize,
|
||||||
tid: usize,
|
|
||||||
pub link: Link<Self>,
|
pub link: Link<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,29 +58,19 @@ impl TcbObject {
|
|||||||
fault_handler: CapEntry::new(NullCap::mint()),
|
fault_handler: CapEntry::new(NullCap::mint()),
|
||||||
state: ThreadState::Inactive,
|
state: ThreadState::Inactive,
|
||||||
time_tick: 0,
|
time_tick: 0,
|
||||||
tid: TID_ALLOCATOR.fetch_add(1, Ordering::SeqCst),
|
|
||||||
link: Link::default(),
|
link: Link::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.state = ThreadState::Idle;
|
self.state = ThreadState::Idle;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tid(&self) -> usize {
|
|
||||||
self.tid
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn state(&self) -> ThreadState {
|
pub fn state(&self) -> ThreadState {
|
||||||
self.state
|
self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedulable(&self) -> bool {
|
|
||||||
self.state != ThreadState::Blocked && self.state != ThreadState::Inactive
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_state(&mut self, state: ThreadState) {
|
pub fn set_state(&mut self, state: ThreadState) {
|
||||||
self.state = state;
|
self.state = state;
|
||||||
}
|
}
|
||||||
@ -90,18 +83,17 @@ impl TcbObject {
|
|||||||
self.time_tick = timeslice;
|
self.time_tick = timeslice;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_tick(&mut self) {
|
pub fn timer_tick(&mut self) {
|
||||||
self.time_tick = self.time_tick.saturating_sub(1);
|
self.time_tick = self.time_tick.saturating_sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate_vspace(&self) {
|
pub fn install_vspace(&self) {
|
||||||
let cap = TableCap::try_from(&self.vspace).expect("activate_vspace: invalid cap");
|
// setup pagetable
|
||||||
let paddr = cap.as_object::<Level0>().paddr();
|
todo!("TcbObject::install_vspace");
|
||||||
unsafe { install_pagetable(paddr) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate(&mut self) {
|
pub fn activate(&mut self) {
|
||||||
self.activate_vspace();
|
self.install_vspace();
|
||||||
self.trapframe.restore();
|
self.trapframe.restore();
|
||||||
self.trapframe.handle_trap(false);
|
self.trapframe.handle_trap(false);
|
||||||
}
|
}
|
||||||
@ -114,9 +106,9 @@ impl TcbObject {
|
|||||||
let cap_ptr = self.trapframe.get_reg(1);
|
let cap_ptr = self.trapframe.get_reg(1);
|
||||||
let cap = cspace.resolve_address_bits(cap_ptr, usize::BITS as usize);
|
let cap = cspace.resolve_address_bits(cap_ptr, usize::BITS as usize);
|
||||||
|
|
||||||
debug!("handle_syscall: info={:?}, cap={:?}", info, cap);
|
|
||||||
|
|
||||||
todo!("handle_syscall");
|
todo!("handle_syscall");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
handle_syscall_inner().unwrap();
|
handle_syscall_inner().unwrap();
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::objects::*;
|
use super::cap::RawCap;
|
||||||
|
use super::cnode::{CNodeCap, CNodeObject};
|
||||||
|
use super::null::NullCap;
|
||||||
|
use super::{Cap, FrameCap, KernelObject, TableCap, TcbCap};
|
||||||
use crate::vspace::MapAttr;
|
use crate::vspace::MapAttr;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use uapi::cap::ObjectType;
|
use uapi::cap::ObjectType;
|
||||||
|
@ -12,7 +12,7 @@ use utils::{addr::*, bin::prev_power_of_two};
|
|||||||
|
|
||||||
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(|i| CapEntry::new(NullCap::mint())));
|
||||||
|
|
||||||
pub fn setup_root_server(fdt: &Fdt) {
|
pub fn setup_root_server(fdt: &Fdt) {
|
||||||
// Root Server is using statically allocated ROOT_CNODE
|
// Root Server is using statically allocated ROOT_CNODE
|
||||||
@ -216,13 +216,9 @@ fn create_objects(cnode_obj: &mut CNodeObject, end_idx: usize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> usize {
|
fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> usize {
|
||||||
let mut table = {
|
let table: Table<Level0> = TableCap::try_from(&cnode_obj[CNodeSlot::VSpaceCap as usize])
|
||||||
let root = &cnode_obj[CNodeSlot::VSpaceCap as usize];
|
.unwrap()
|
||||||
let root_vaddr = TableCap::try_from(root).unwrap().as_object::<Level0>().vaddr();
|
.as_object_mut();
|
||||||
|
|
||||||
// use unsafe to workaround borrow checker
|
|
||||||
unsafe { Table::new(root_vaddr) }
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut rootfs = unsafe {
|
let mut rootfs = unsafe {
|
||||||
let chosen = fdt.find_node("/chosen").expect("/chosen is required");
|
let chosen = fdt.find_node("/chosen").expect("/chosen is required");
|
||||||
@ -259,6 +255,7 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u
|
|||||||
})
|
})
|
||||||
.expect("init: root server not found");
|
.expect("init: root server not found");
|
||||||
|
|
||||||
|
let root_start = VirtAddr::from(root_entry.data().as_ptr());
|
||||||
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;
|
let mut nxt_slot = end_idx;
|
||||||
@ -275,6 +272,7 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u
|
|||||||
phdr.p_vaddr + phdr.p_memsz
|
phdr.p_vaddr + phdr.p_memsz
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let seg_start = root_start + phdr.p_offset as usize;
|
||||||
let seg_addr = VirtAddr::from(phdr.p_vaddr);
|
let seg_addr = VirtAddr::from(phdr.p_vaddr);
|
||||||
|
|
||||||
// Currently, we only support loading segments that are aligned to PAGE_SIZE
|
// Currently, we only support loading segments that are aligned to PAGE_SIZE
|
||||||
@ -288,7 +286,6 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u
|
|||||||
dest.fill(0);
|
dest.fill(0);
|
||||||
} else {
|
} else {
|
||||||
let len = min(phdr.p_filesz as usize - offset, dest.len());
|
let len = min(phdr.p_filesz as usize - offset, dest.len());
|
||||||
let offset = phdr.p_offset as usize + offset;
|
|
||||||
let src = &root_entry.data()[offset..offset + len];
|
let src = &root_entry.data()[offset..offset + len];
|
||||||
dest[..len].copy_from_slice(src);
|
dest[..len].copy_from_slice(src);
|
||||||
dest[len..].fill(0);
|
dest[len..].fill(0);
|
||||||
@ -316,6 +313,10 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u
|
|||||||
copy(cur, mem);
|
copy(cur, mem);
|
||||||
|
|
||||||
// map frame to vspace
|
// map frame to vspace
|
||||||
|
let root = &cnode_obj[CNodeSlot::VSpaceCap as usize];
|
||||||
|
let root_vaddr = TableCap::try_from(root).unwrap().as_object::<Level0>().vaddr();
|
||||||
|
let mut root = unsafe { Table::new(root_vaddr) }; // use unsafe to workaround borrow checker
|
||||||
|
|
||||||
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 = {
|
||||||
@ -347,7 +348,7 @@ fn load_root_server(cnode_obj: &mut CNodeObject, end_idx: usize, fdt: &Fdt) -> u
|
|||||||
unsafe { mmap_virt_to_phys(table.vaddr()) }
|
unsafe { mmap_virt_to_phys(table.vaddr()) }
|
||||||
};
|
};
|
||||||
|
|
||||||
map_range(alloc_page, &mut table, vaddr, paddr, block_size, attr);
|
map_range(alloc_page, &mut root, vaddr, paddr, block_size, attr);
|
||||||
|
|
||||||
// update pointer
|
// update pointer
|
||||||
cur += block_size;
|
cur += block_size;
|
||||||
|
@ -2,17 +2,17 @@ use crate::objects::*;
|
|||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
use log::error;
|
use log::error;
|
||||||
use spin::lazy::Lazy;
|
use spin::lazy::Lazy;
|
||||||
use utils::{container_of, linked_list::Link};
|
use utils::linked_list::Link;
|
||||||
|
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
pub static IDLE_THREAD: Lazy<TcbObject> = Lazy::new(|| {
|
static IDLE_THREAD: Lazy<TcbObject> = Lazy::new(|| {
|
||||||
let mut idle_thread = TcbObject::new();
|
let mut idle_thread = TcbObject::new();
|
||||||
idle_thread.configure_idle_thread();
|
idle_thread.configure_idle_thread();
|
||||||
idle_thread
|
idle_thread
|
||||||
});
|
});
|
||||||
|
|
||||||
#[thread_local]
|
#[thread_local]
|
||||||
pub static SCHEDULER: Scheduler = Scheduler::new();
|
pub static SCHEDULER: Lazy<Scheduler> = Lazy::new(|| Scheduler::new(&IDLE_THREAD));
|
||||||
|
|
||||||
// TODO: add a shared buffer to transfer TCB between cores
|
// TODO: add a shared buffer to transfer TCB between cores
|
||||||
|
|
||||||
@ -24,14 +24,14 @@ pub struct Scheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Scheduler {
|
impl Scheduler {
|
||||||
pub const fn new() -> Self {
|
pub fn new(idle_thread: &TcbObject) -> Self {
|
||||||
Self { head: Link::new() }
|
// link idle_thread
|
||||||
}
|
idle_thread.link.set_prev(Some(NonNull::from(idle_thread)));
|
||||||
|
idle_thread.link.set_next(Some(NonNull::from(idle_thread)));
|
||||||
|
|
||||||
pub fn init(&self) {
|
Self {
|
||||||
let head = unsafe { Some(NonNull::from(&*container_of!(&self.head, TcbObject, link))) };
|
head: idle_thread.link.clone(),
|
||||||
self.head.set_next(head);
|
}
|
||||||
self.head.set_prev(head);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&self, tcb: &TcbObject) {
|
pub fn add(&self, tcb: &TcbObject) {
|
||||||
@ -40,17 +40,19 @@ impl Scheduler {
|
|||||||
|
|
||||||
pub fn schedule(&self) {
|
pub fn schedule(&self) {
|
||||||
while let Some(next) = self.head.next_mut() {
|
while let Some(next) = self.head.next_mut() {
|
||||||
if next.timetick() > 0 && next.schedulable() {
|
// TODO: also need to check whether it is schedulable
|
||||||
|
if next.timetick() > 0 {
|
||||||
|
// Available to run, activate it
|
||||||
next.activate();
|
next.activate();
|
||||||
} else if next.timetick() == 0 {
|
} else if next.timetick() == 0 {
|
||||||
|
// No time left, refill time tick and move to the end of the queue
|
||||||
next.set_timetick(TIME_SLICE);
|
next.set_timetick(TIME_SLICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// put to the end of the queue
|
// put to the end of the queue
|
||||||
if next.timetick() == 0 || !next.schedulable() {
|
// todo: only move blocked and time expired threads to the end
|
||||||
next.link.detach();
|
next.link.detach();
|
||||||
self.head.prepend(next);
|
self.head.prepend(next);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error!("[Scheduler] No thread to schedule! Where is IDLE thread?");
|
error!("[Scheduler] No thread to schedule! Where is IDLE thread?");
|
||||||
|
@ -22,9 +22,6 @@ pub trait PhysAddrPage: AddressOps {
|
|||||||
/// Almost the same as `paddr_extract_ppn`, but the PPN remains shifted in the address.
|
/// Almost the same as `paddr_extract_ppn`, but the PPN remains shifted in the address.
|
||||||
fn extract_ppn_shifted(&self) -> usize;
|
fn extract_ppn_shifted(&self) -> usize;
|
||||||
|
|
||||||
/// Converts a Physical Page Number (PPN) into a Physical Address.
|
|
||||||
fn from_ppn(ppn: usize) -> Self;
|
|
||||||
|
|
||||||
/// Converts a PTE into a Physical Address.
|
/// Converts a PTE into a Physical Address.
|
||||||
fn from_pte(pte: usize) -> Self;
|
fn from_pte(pte: usize) -> Self;
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ pub trait TableOps<'a, T: TableLevel> {
|
|||||||
/// `location` must be a page-aligned virtual address and will not be dropped.
|
/// `location` must be a page-aligned virtual address and will not be dropped.
|
||||||
unsafe fn new(location: VirtAddr) -> Self;
|
unsafe fn new(location: VirtAddr) -> Self;
|
||||||
fn vaddr(&self) -> VirtAddr;
|
fn vaddr(&self) -> VirtAddr;
|
||||||
fn paddr(&self) -> PhysAddr;
|
|
||||||
|
|
||||||
// following methods only works at current level
|
// following methods only works at current level
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user