mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 01:35:19 +08:00
feat: objects: add initial support for TcbObj
This commit is contained in:
parent
f005c8254b
commit
8897e6467c
@ -1,7 +1,9 @@
|
||||
use crate::entry::HART_ID;
|
||||
use crate::objects::tcb::TcbObject;
|
||||
use crate::plat::console::CONSOLE;
|
||||
use crate::plat::timer::{Timer, TimerOps};
|
||||
use crate::plat::trap::{Trap, TrapContextOps, TrapOps};
|
||||
use core::ops::{Index, IndexMut};
|
||||
use log::trace;
|
||||
use riscv::register::scause::{Exception as E, Interrupt as I, Trap as T};
|
||||
use riscv::register::stvec::TrapMode;
|
||||
@ -19,7 +21,7 @@ extern "C" fn kernel_trap_handler(tf: &mut TrapContext) {
|
||||
// No trap in kernel, except from IDLE thread
|
||||
// TODO: Replace CONSOLE Mutex to ReentrantLock
|
||||
unsafe { CONSOLE.force_unlock() }
|
||||
tf.trap_handler(true);
|
||||
tf.handle_trap(true);
|
||||
}
|
||||
|
||||
impl TrapOps for Trap {
|
||||
@ -54,7 +56,7 @@ impl TrapContextOps for TrapContext {
|
||||
self.sstatus = (1 << 5) | (1 << 8); // SPIE + SPP
|
||||
}
|
||||
|
||||
fn trap_handler(&mut self, from_kernel: bool) {
|
||||
fn handle_trap(&mut self, from_kernel: bool) {
|
||||
let scause = riscv::register::scause::read();
|
||||
trace!("[Trap] cpu@{} scause: {:?}", HART_ID.get(), scause.cause());
|
||||
|
||||
@ -71,10 +73,17 @@ impl TrapContextOps for TrapContext {
|
||||
};
|
||||
}
|
||||
|
||||
let tcb = self.as_object_mut();
|
||||
|
||||
match scause.cause() {
|
||||
T::Interrupt(I::SupervisorTimer) => Timer::do_tick(),
|
||||
T::Interrupt(I::SupervisorTimer) => {
|
||||
Timer::do_tick();
|
||||
if !from_kernel {
|
||||
tcb.timer_tick();
|
||||
}
|
||||
},
|
||||
T::Exception(E::UserEnvCall) => {
|
||||
// TODO: handle syscall
|
||||
tcb.handle_syscall();
|
||||
self.sepc += 4;
|
||||
},
|
||||
T::Interrupt(I::SupervisorExternal) => {
|
||||
@ -90,7 +99,27 @@ impl TrapContextOps for TrapContext {
|
||||
}
|
||||
|
||||
Timer::set_next();
|
||||
trace!("[Trap] exiting...");
|
||||
}
|
||||
|
||||
fn as_object(&self) -> &TcbObject {
|
||||
unsafe { &*(self as *const TrapContext as *const TcbObject) }
|
||||
}
|
||||
|
||||
fn as_object_mut(&mut self) -> &mut TcbObject {
|
||||
unsafe { &mut *(self as *mut TrapContext as *mut TcbObject) }
|
||||
}
|
||||
|
||||
fn get_reg(&self, index: usize) -> usize {
|
||||
// x10 ~ x17: Function arguments
|
||||
assert!(index < 8, "TrapContext get_reg index out of range");
|
||||
self.gprs[index + 10]
|
||||
}
|
||||
|
||||
fn set_reg(&mut self, index: usize, value: usize) {
|
||||
// x10 ~ x17: Function arguments
|
||||
// x10 ~ x11: Function return values
|
||||
assert!(index < 8, "TrapContext set_reg index out of range");
|
||||
self.gprs[index + 10] = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,6 +159,24 @@ pub struct GeneralRegs {
|
||||
pub t6: usize,
|
||||
}
|
||||
|
||||
impl Index<usize> for GeneralRegs {
|
||||
type Output = usize;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
assert!(index < 32, "GeneralRegs index out of range");
|
||||
let regs = unsafe { &*(self as *const _ as *const [usize; 32]) };
|
||||
®s[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<usize> for GeneralRegs {
|
||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||
assert!(index < 32, "GeneralRegs index out of range");
|
||||
let regs = unsafe { &mut *(self as *mut _ as *mut [usize; 32]) };
|
||||
&mut regs[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct TrapContext {
|
||||
|
@ -10,9 +10,9 @@ use utils::{
|
||||
/// RawCap is the specific implementation of capability which stores in CNode
|
||||
#[derive(Copy, Clone, Default, PartialEq, Eq)]
|
||||
pub struct RawCap {
|
||||
// TODO: this could be an enum, figure out a way to do this
|
||||
/// args: in vanilla seL4 implementation, a cap use two 64-bit words to store all information,
|
||||
/// but we'll waste some space rather than using bitfield to simplify the implementation
|
||||
// TODO: use u64 rather than usize
|
||||
pub args: [usize; 2],
|
||||
/// ptr: vanilla seL4 stores the pointer with either higher bits or lower bits cut off,
|
||||
/// which limits the address space. Use an independent field to store the pointer.
|
||||
|
@ -26,6 +26,7 @@ pub mod cnode;
|
||||
pub mod frame;
|
||||
pub mod null;
|
||||
pub mod table;
|
||||
pub mod tcb;
|
||||
pub mod untyped;
|
||||
|
||||
/// Cap is the high-level wrapper of RawCap, it's a typed reference to RawCap (which is untyped in Rust)
|
||||
|
110
kernel/src/objects/tcb.rs
Normal file
110
kernel/src/objects/tcb.rs
Normal file
@ -0,0 +1,110 @@
|
||||
use super::{
|
||||
cap::{CapEntry, RawCap},
|
||||
null::NullCap,
|
||||
Cap, KernelObject,
|
||||
};
|
||||
use crate::{
|
||||
arch::{layout::mmap_phys_to_virt, trap::TrapContext},
|
||||
plat::trap::TrapContextOps,
|
||||
};
|
||||
use uapi::cap::ObjectType;
|
||||
use utils::{
|
||||
addr::*,
|
||||
linked_list::{Link, LinkHelper},
|
||||
LinkHelperImpl,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ThreadState {
|
||||
Inactive,
|
||||
Running,
|
||||
Restart,
|
||||
Blocked,
|
||||
Idle,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct TcbObject {
|
||||
pub trapframe: TrapContext, // must be the first field
|
||||
|
||||
cspace: CapEntry,
|
||||
vspace: CapEntry,
|
||||
|
||||
// TODO: add reply, buffer, fault, caller ... priority, dom
|
||||
state: ThreadState,
|
||||
time_slice: usize,
|
||||
pub link: Link<Self>,
|
||||
}
|
||||
|
||||
LinkHelperImpl!(TcbObject:link);
|
||||
|
||||
impl TcbObject {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
trapframe: TrapContext::default(),
|
||||
cspace: CapEntry::new(NullCap::mint()),
|
||||
vspace: CapEntry::new(NullCap::mint()),
|
||||
state: ThreadState::Inactive,
|
||||
time_slice: 0,
|
||||
link: Link::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configure_idle_thread(&mut self) {
|
||||
self.trapframe.configure_idle_thread();
|
||||
self.state = ThreadState::Idle;
|
||||
}
|
||||
|
||||
pub fn timeslice(&self) -> usize {
|
||||
self.time_slice
|
||||
}
|
||||
|
||||
pub fn set_timeslice(&mut self, timeslice: usize) {
|
||||
self.time_slice = timeslice;
|
||||
}
|
||||
|
||||
pub fn timer_tick(&mut self) {
|
||||
self.time_slice = self.time_slice.saturating_sub(1);
|
||||
}
|
||||
|
||||
pub fn install_vspace(&self) {
|
||||
// setup pagetable
|
||||
todo!("TcbObject::install_vspace");
|
||||
}
|
||||
|
||||
pub fn activate(&mut self) {
|
||||
self.install_vspace();
|
||||
self.trapframe.restore();
|
||||
self.trapframe.handle_trap(false);
|
||||
}
|
||||
|
||||
pub fn handle_syscall(&mut self) {
|
||||
todo!("TcbObject::handle_syscall");
|
||||
}
|
||||
}
|
||||
|
||||
impl KernelObject for TcbObject {
|
||||
const OBJ_TYPE: ObjectType = ObjectType::TCB;
|
||||
}
|
||||
|
||||
pub type TcbCap<'a> = Cap<'a, TcbObject>;
|
||||
|
||||
impl<'a> TcbCap<'a> {
|
||||
pub fn mint(ptr: PhysAddr) -> RawCap {
|
||||
RawCap::new(0, 0, ptr, ObjectType::TCB)
|
||||
}
|
||||
|
||||
pub fn as_object(&self) -> &TcbObject {
|
||||
unsafe {
|
||||
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr);
|
||||
&*(virt.as_const_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_object_mut(&mut self) -> &mut TcbObject {
|
||||
unsafe {
|
||||
let virt = mmap_phys_to_virt(self.cte.cap.get().ptr);
|
||||
&mut *(virt.as_mut_ptr())
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
use crate::objects::tcb::TcbObject;
|
||||
|
||||
pub struct Trap;
|
||||
|
||||
pub trait TrapOps {
|
||||
@ -7,5 +9,11 @@ pub trait TrapOps {
|
||||
pub trait TrapContextOps {
|
||||
fn restore(&mut self);
|
||||
fn configure_idle_thread(&mut self);
|
||||
fn trap_handler(&mut self, from_kernel: bool);
|
||||
fn handle_trap(&mut self, from_kernel: bool);
|
||||
|
||||
fn as_object(&self) -> &TcbObject;
|
||||
fn as_object_mut(&mut self) -> &mut TcbObject;
|
||||
|
||||
fn get_reg(&self, index: usize) -> usize;
|
||||
fn set_reg(&mut self, index: usize, value: usize);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user