mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
Compare commits
5 Commits
0300ac3c5d
...
272fdf303c
Author | SHA1 | Date | |
---|---|---|---|
272fdf303c | |||
392d5ce59e | |||
a2c5ba1494 | |||
261f7dd68e | |||
308b523e7e |
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,3 +2,6 @@
|
|||||||
/target
|
/target
|
||||||
/replay.*
|
/replay.*
|
||||||
/kernel.asm
|
/kernel.asm
|
||||||
|
/*.log
|
||||||
|
/*.dtb
|
||||||
|
/*.dts
|
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -83,9 +83,8 @@ checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdt"
|
name = "fdt"
|
||||||
version = "0.1.5"
|
version = "0.2.0-alpha1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/panpaul/fdt.git#68e763be166bfbe150d7824387399cf0a4ac1ce7"
|
||||||
checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
|
4
Makefile
4
Makefile
@ -28,11 +28,13 @@ CARGO_BUILD_ARGS += $(CARGO_TARGET_ARGS)
|
|||||||
|
|
||||||
QEMU = qemu-system-$(ARCH)
|
QEMU = qemu-system-$(ARCH)
|
||||||
|
|
||||||
QEMU_ARGS = -nographic -serial mon:stdio -smp 1
|
QEMU_ARGS = -nographic -serial mon:stdio -smp 4
|
||||||
QEMU_ARGS += -machine virt # TODO: override by $(BOARD)
|
QEMU_ARGS += -machine virt # TODO: override by $(BOARD)
|
||||||
QEMU_ARGS += -kernel target/$(BUILD_TARGET)/$(MODE)/kernel
|
QEMU_ARGS += -kernel target/$(BUILD_TARGET)/$(MODE)/kernel
|
||||||
QEMU_ARGS += -initrd root/init.cpio
|
QEMU_ARGS += -initrd root/init.cpio
|
||||||
|
ifeq ($(MODE), debug)
|
||||||
QEMU_ARGS += -append "loglevel=4"
|
QEMU_ARGS += -append "loglevel=4"
|
||||||
|
endif
|
||||||
|
|
||||||
kernel:
|
kernel:
|
||||||
env RUSTFLAGS="$(RUSTFLAGS)" cargo build --bin kernel $(CARGO_BUILD_ARGS)
|
env RUSTFLAGS="$(RUSTFLAGS)" cargo build --bin kernel $(CARGO_BUILD_ARGS)
|
||||||
|
@ -29,7 +29,7 @@ utils = { path = "../lib/utils", default-features = false }
|
|||||||
bitflags = "2.5"
|
bitflags = "2.5"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
elf = { version = "0.7", default-features = false }
|
elf = { version = "0.7", default-features = false }
|
||||||
fdt = "0.1"
|
fdt = { git = "https://github.com/panpaul/fdt.git" } # fork from upstream
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
num-derive = "0.4"
|
num-derive = "0.4"
|
||||||
num-traits = { version = "0.2", default-features = false }
|
num-traits = { version = "0.2", default-features = false }
|
||||||
|
8
kernel/src/drivers/irq/mod.rs
Normal file
8
kernel/src/drivers/irq/mod.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use crate::drivers::Driver;
|
||||||
|
use crate::plat::irq::IrqController;
|
||||||
|
|
||||||
|
pub trait IrqDriver: Driver + IrqController {}
|
||||||
|
|
||||||
|
mod plic;
|
||||||
|
|
||||||
|
pub use plic::IrqPlic;
|
175
kernel/src/drivers/irq/plic.rs
Normal file
175
kernel/src/drivers/irq/plic.rs
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
use super::IrqDriver;
|
||||||
|
use crate::drivers::Driver;
|
||||||
|
use crate::entry::HART_ID;
|
||||||
|
use crate::plat::irq::IrqController;
|
||||||
|
use fdt::{node::FdtNode, Fdt};
|
||||||
|
use log::trace;
|
||||||
|
use spin::Mutex;
|
||||||
|
|
||||||
|
const IRQ_INVALID: usize = u32::MAX as usize;
|
||||||
|
const IRQ_S_EXT: usize = 9;
|
||||||
|
const IRQ_M_EXT: usize = 11;
|
||||||
|
|
||||||
|
const PLIC_PRIORITY_OFFSET: usize = 0;
|
||||||
|
const PLIC_PENDING_OFFSET: usize = 0x1000;
|
||||||
|
const PLIC_ENABLE_OFFSET: usize = 0x2000;
|
||||||
|
const PLIC_ENABLE_STRIDE: usize = 0x80;
|
||||||
|
const PLIC_CONTROL_OFFSET: usize = 0x200000;
|
||||||
|
const PLIC_CONTROL_STRIDE: usize = 0x1000;
|
||||||
|
|
||||||
|
#[repr(C, align(0x1000))]
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct PlicCtrl {
|
||||||
|
threshold: *mut u32,
|
||||||
|
claim: *mut u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct IrqPlic
|
||||||
|
where IrqPlic: IrqDriver
|
||||||
|
{
|
||||||
|
priority: *mut u32,
|
||||||
|
pending: *mut u32,
|
||||||
|
enable: *mut u32,
|
||||||
|
control: *mut PlicCtrl,
|
||||||
|
|
||||||
|
nr_irqs: usize,
|
||||||
|
lock: Mutex<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Driver for IrqPlic {
|
||||||
|
fn compatible() -> &'static [&'static str] {
|
||||||
|
&["riscv,plic0"]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(node: FdtNode, fdt: &Fdt) -> Self {
|
||||||
|
let base_address = node
|
||||||
|
.reg()
|
||||||
|
.expect("no PLIC base address available")
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.starting_address as *mut u8;
|
||||||
|
|
||||||
|
let nr_irqs = node
|
||||||
|
.property("riscv,ndev")
|
||||||
|
.expect("riscv,ndev property not available")
|
||||||
|
.as_usize();
|
||||||
|
|
||||||
|
let mut ctx_id = None;
|
||||||
|
for (i, ctx) in node.interrupts_extended().expect("no PLIC context available").enumerate() {
|
||||||
|
assert!(ctx.interrupts().count() == 1, "PLIC interrupts should have only one cell");
|
||||||
|
|
||||||
|
let phandle = ctx.phandle; // cpu intc
|
||||||
|
let irq = ctx.interrupts().next().unwrap(); // IRQ_M_EXT/IRQ_S_EXT
|
||||||
|
|
||||||
|
if irq == IRQ_INVALID {
|
||||||
|
trace!("[IrqPlic] context {} taken by SBI", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cpu = fdt
|
||||||
|
.cpus()
|
||||||
|
.find(|cpu| {
|
||||||
|
cpu.as_fdt_node().children().any(|node| {
|
||||||
|
node.property("phandle")
|
||||||
|
.is_some_and(|prop| prop.as_usize().unwrap() == phandle as usize)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.expect("PLIC context should be connected to a CPU");
|
||||||
|
let hart = cpu.ids().first(); // TODO: support SMT
|
||||||
|
|
||||||
|
if irq != IRQ_S_EXT || hart != HART_ID.get() {
|
||||||
|
trace!("[IrqPlic] context {} is not for us, irq = {}", i, irq);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace!("[IrqPlic] context {} is for us", i);
|
||||||
|
ctx_id = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ctx_id = ctx_id.expect("No PLIC context found for us");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
priority: unsafe { base_address.add(PLIC_PRIORITY_OFFSET) as *mut u32 },
|
||||||
|
pending: unsafe { base_address.add(PLIC_PENDING_OFFSET) as *mut u32 },
|
||||||
|
enable: unsafe { base_address.add(PLIC_ENABLE_OFFSET + ctx_id * PLIC_ENABLE_STRIDE) as *mut u32 },
|
||||||
|
control: unsafe { (base_address.add(PLIC_CONTROL_OFFSET) as *mut PlicCtrl).add(ctx_id) },
|
||||||
|
nr_irqs: nr_irqs.unwrap(),
|
||||||
|
lock: Mutex::new(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrqController for IrqPlic {
|
||||||
|
fn enable(&self, irq: usize) {
|
||||||
|
if irq == 0 || irq >= self.nr_irqs {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let word = irq / 32;
|
||||||
|
let bit = irq % 32;
|
||||||
|
|
||||||
|
{
|
||||||
|
let guard = self.lock.lock();
|
||||||
|
|
||||||
|
let val = unsafe { self.enable.add(word).read_volatile() };
|
||||||
|
let val = val | (1 << bit);
|
||||||
|
unsafe { self.enable.add(word).write_volatile(val) };
|
||||||
|
|
||||||
|
drop(guard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn disable(&self, irq: usize) {
|
||||||
|
if irq == 0 || irq >= self.nr_irqs {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let word = irq / 32;
|
||||||
|
let bit = irq % 32;
|
||||||
|
|
||||||
|
{
|
||||||
|
let guard = self.lock.lock();
|
||||||
|
|
||||||
|
let val = unsafe { self.enable.add(word).read_volatile() };
|
||||||
|
let val = val & !(1 << bit);
|
||||||
|
unsafe { self.enable.add(word).write_volatile(val) };
|
||||||
|
|
||||||
|
drop(guard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_pending(&self, irq: usize) -> bool {
|
||||||
|
if irq == 0 || irq >= self.nr_irqs {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let word = irq / 32;
|
||||||
|
let bit = irq % 32;
|
||||||
|
|
||||||
|
let val = unsafe { self.pending.add(word).read_volatile() };
|
||||||
|
val & (1 << bit) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn claim(&self) -> Option<usize> {
|
||||||
|
let val = unsafe { self.control.as_ref().unwrap().claim.read_volatile() };
|
||||||
|
|
||||||
|
if val > 0 {
|
||||||
|
Some(val as usize)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn complete(&self, irq: usize) {
|
||||||
|
if irq == 0 || irq >= self.nr_irqs {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let val = irq as u32;
|
||||||
|
unsafe { self.control.as_ref().unwrap().claim.write_volatile(val) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrqDriver for IrqPlic {}
|
@ -1,11 +1,12 @@
|
|||||||
// This will only implement some basic drivers (PLIC, UART, ...) to boot the kernel.
|
// This will only implement some basic drivers (PLIC, UART, ...) to boot the kernel.
|
||||||
// For the rest of the drivers, we will implement them in root server.
|
// For the rest of the drivers, we will implement them in root server.
|
||||||
|
|
||||||
|
pub mod irq;
|
||||||
pub mod serial;
|
pub mod serial;
|
||||||
|
|
||||||
use fdt::node::FdtNode;
|
use fdt::{node::FdtNode, Fdt};
|
||||||
|
|
||||||
pub trait Driver {
|
pub trait Driver {
|
||||||
fn compatible() -> &'static [&'static str];
|
fn compatible() -> &'static [&'static str];
|
||||||
fn setup(_: FdtNode) -> Self;
|
fn setup(_: FdtNode, _: &Fdt) -> Self;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use crate::drivers::serial::SerialDriver;
|
|||||||
use crate::drivers::Driver;
|
use crate::drivers::Driver;
|
||||||
use crate::plat::console::ConsoleDevice;
|
use crate::plat::console::ConsoleDevice;
|
||||||
use core::sync::atomic::{AtomicPtr, Ordering};
|
use core::sync::atomic::{AtomicPtr, Ordering};
|
||||||
use fdt::node::FdtNode;
|
use fdt::{node::FdtNode, Fdt};
|
||||||
use utils::addr::PhysAddr;
|
use utils::addr::PhysAddr;
|
||||||
|
|
||||||
// https://static.dev.sifive.com/FU540-C000-v1.0.pdf
|
// https://static.dev.sifive.com/FU540-C000-v1.0.pdf
|
||||||
@ -122,8 +122,8 @@ impl Driver for UartSifive {
|
|||||||
&["sifive,uart0"]
|
&["sifive,uart0"]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(fdt: FdtNode) -> Self {
|
fn setup(node: FdtNode, _: &Fdt) -> Self {
|
||||||
let addr = fdt.reg().unwrap().next().unwrap().starting_address;
|
let addr = node.reg().unwrap().next().unwrap().starting_address;
|
||||||
let addr = unsafe { mmap_phys_to_virt(PhysAddr::from(addr)) };
|
let addr = unsafe { mmap_phys_to_virt(PhysAddr::from(addr)) };
|
||||||
let addr: *mut u32 = addr.into();
|
let addr: *mut u32 = addr.into();
|
||||||
let uart = unsafe {
|
let uart = unsafe {
|
||||||
|
@ -3,6 +3,7 @@ use crate::drivers::serial::SerialDriver;
|
|||||||
use crate::drivers::Driver;
|
use crate::drivers::Driver;
|
||||||
use crate::plat::console::ConsoleDevice;
|
use crate::plat::console::ConsoleDevice;
|
||||||
use fdt::node::FdtNode;
|
use fdt::node::FdtNode;
|
||||||
|
use fdt::Fdt;
|
||||||
use uart_16550::MmioSerialPort;
|
use uart_16550::MmioSerialPort;
|
||||||
use utils::addr::PhysAddr;
|
use utils::addr::PhysAddr;
|
||||||
|
|
||||||
@ -17,8 +18,8 @@ impl Driver for Uart16550 {
|
|||||||
&["ns16550", "ns16550a"]
|
&["ns16550", "ns16550a"]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(fdt: FdtNode) -> Self {
|
fn setup(node: FdtNode, _: &Fdt) -> Self {
|
||||||
let addr = fdt.reg().unwrap().next().unwrap().starting_address;
|
let addr = node.reg().unwrap().next().unwrap().starting_address;
|
||||||
let addr = unsafe { mmap_phys_to_virt(PhysAddr::from(addr)) };
|
let addr = unsafe { mmap_phys_to_virt(PhysAddr::from(addr)) };
|
||||||
let mut serial_port = unsafe { MmioSerialPort::new(addr.into()) };
|
let mut serial_port = unsafe { MmioSerialPort::new(addr.into()) };
|
||||||
serial_port.init();
|
serial_port.init();
|
||||||
|
@ -40,6 +40,7 @@ pub fn rust_main() -> ! {
|
|||||||
|
|
||||||
setup_root_server(&fdt);
|
setup_root_server(&fdt);
|
||||||
|
|
||||||
|
info!("Kernel Initialization Completed");
|
||||||
SCHEDULER.schedule();
|
SCHEDULER.schedule();
|
||||||
|
|
||||||
error!("[rust_main] Should not reach here! Maybe scheduler is not working?");
|
error!("[rust_main] Should not reach here! Maybe scheduler is not working?");
|
||||||
@ -48,7 +49,11 @@ pub fn rust_main() -> ! {
|
|||||||
|
|
||||||
fn setup_console(fdt: &Fdt) {
|
fn setup_console(fdt: &Fdt) {
|
||||||
// NOTE: ignore stdin: both stdin and stdout will go through stdout device
|
// NOTE: ignore stdin: both stdin and stdout will go through stdout device
|
||||||
match fdt.chosen().stdout().and_then(|stdout| ConsoleDriver::new(stdout)) {
|
match fdt
|
||||||
|
.chosen()
|
||||||
|
.stdout()
|
||||||
|
.and_then(|stdout| ConsoleDriver::new(stdout.node(), fdt))
|
||||||
|
{
|
||||||
None => warn!("No stdout device found or no compatible drivers found, falling back to platform default"),
|
None => warn!("No stdout device found or no compatible drivers found, falling back to platform default"),
|
||||||
Some(driver) => set_console(driver),
|
Some(driver) => set_console(driver),
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
#![feature(asm_const)]
|
#![feature(asm_const)]
|
||||||
#![feature(cell_update)]
|
#![feature(cell_update)]
|
||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
|
#![feature(iter_array_chunks)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(naked_functions)]
|
#![feature(naked_functions)]
|
||||||
#![feature(panic_info_message)]
|
|
||||||
#![feature(thread_local)]
|
#![feature(thread_local)]
|
||||||
// Test Infrastructure
|
// Test Infrastructure
|
||||||
#![feature(custom_test_frameworks)]
|
#![feature(custom_test_frameworks)]
|
||||||
|
@ -12,6 +12,9 @@ use utils::{
|
|||||||
|
|
||||||
pub static TID_ALLOCATOR: AtomicUsize = AtomicUsize::new(0);
|
pub static TID_ALLOCATOR: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
// one process can run for 10 ticks
|
||||||
|
pub const TIME_TICK: usize = 10;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum ThreadState {
|
pub enum ThreadState {
|
||||||
Inactive,
|
Inactive,
|
||||||
@ -103,8 +106,12 @@ impl TcbObject {
|
|||||||
self.time_tick
|
self.time_tick
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_timetick(&mut self, timeslice: usize) {
|
pub fn refill_timetick(&mut self) {
|
||||||
self.time_tick = timeslice;
|
self.time_tick = if self.tid != 0 { TIME_TICK } else { 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_timetick(&mut self) {
|
||||||
|
self.time_tick = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_tick(&mut self) {
|
pub fn do_tick(&mut self) {
|
||||||
@ -124,7 +131,7 @@ impl TcbObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_syscall(&mut self) {
|
pub fn handle_syscall(&mut self) {
|
||||||
// TODO: don't panic here, return error to user instead
|
// TODO: don't panic here, return error to user instead, create SysRespInfo
|
||||||
handle_syscall(self).unwrap();
|
handle_syscall(self).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::arch::EarlyConsole;
|
use crate::arch::EarlyConsole;
|
||||||
use crate::drivers::serial::{Uart16550, UartSifive};
|
use crate::drivers::serial::{Uart16550, UartSifive};
|
||||||
use crate::drivers::Driver;
|
use crate::drivers::Driver;
|
||||||
use fdt::node::FdtNode;
|
use fdt::{node::FdtNode, Fdt};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
@ -14,15 +14,15 @@ macro_rules! create_console_driver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConsoleDriver {
|
impl ConsoleDriver {
|
||||||
pub fn new(fdt: FdtNode) -> Option<Self> {
|
pub fn new(node: FdtNode, fdt: &Fdt) -> Option<Self> {
|
||||||
if let Some(compatible) = fdt.compatible() {
|
if let Some(compatible) = node.compatible() {
|
||||||
$(
|
$(
|
||||||
if compatible
|
if compatible
|
||||||
.all()
|
.all()
|
||||||
.any(|s| $dynamic_driver::compatible().contains(&s))
|
.any(|s| $dynamic_driver::compatible().contains(&s))
|
||||||
{
|
{
|
||||||
debug!("Console: Using driver: {}", stringify!($dynamic_driver));
|
debug!("Console: Using driver: {}", stringify!($dynamic_driver));
|
||||||
return Some(ConsoleDriver::$dynamic_driver($dynamic_driver::setup(fdt)));
|
return Some(ConsoleDriver::$dynamic_driver($dynamic_driver::setup(node, fdt)));
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
|
25
kernel/src/plat/irq.rs
Normal file
25
kernel/src/plat/irq.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::objects::*;
|
||||||
|
|
||||||
|
const IRQ_NUM: usize = 32;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
pub enum IrqState {
|
||||||
|
Inactive,
|
||||||
|
Signal,
|
||||||
|
Ipi,
|
||||||
|
Reserved,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait IrqController {
|
||||||
|
fn enable(&self, irq: usize);
|
||||||
|
fn disable(&self, irq: usize);
|
||||||
|
fn is_pending(&self, irq: usize) -> bool;
|
||||||
|
fn claim(&self) -> Option<usize>;
|
||||||
|
fn complete(&self, irq: usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IrqManager {
|
||||||
|
handler: [CapEntry; IRQ_NUM],
|
||||||
|
state: [IrqState; IRQ_NUM],
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
pub mod backtrace;
|
pub mod backtrace;
|
||||||
pub mod console;
|
pub mod console;
|
||||||
|
pub mod irq;
|
||||||
pub mod lowlevel;
|
pub mod lowlevel;
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
pub mod trap;
|
pub mod trap;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::objects::*;
|
use crate::objects::*;
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
use log::error;
|
use log::{error, trace};
|
||||||
use spin::lazy::Lazy;
|
use spin::lazy::Lazy;
|
||||||
use utils::{container_of, linked_list::Link};
|
use utils::{container_of, linked_list::Link};
|
||||||
|
|
||||||
@ -16,9 +16,6 @@ pub static SCHEDULER: Scheduler = Scheduler::new();
|
|||||||
|
|
||||||
// TODO: add a shared buffer to transfer TCB between cores
|
// TODO: add a shared buffer to transfer TCB between cores
|
||||||
|
|
||||||
// one process can run for 10 ticks
|
|
||||||
pub const TIME_SLICE: usize = 10;
|
|
||||||
|
|
||||||
pub struct Scheduler {
|
pub struct Scheduler {
|
||||||
head: Link<TcbObject>,
|
head: Link<TcbObject>,
|
||||||
}
|
}
|
||||||
@ -41,9 +38,10 @@ 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() {
|
if next.timetick() > 0 && next.schedulable() {
|
||||||
|
trace!("Scheduling thread {}", next.tid());
|
||||||
next.activate();
|
next.activate();
|
||||||
} else if next.timetick() == 0 {
|
} else if next.timetick() == 0 {
|
||||||
next.set_timetick(TIME_SLICE);
|
next.refill_timetick();
|
||||||
}
|
}
|
||||||
|
|
||||||
// put to the end of the queue
|
// put to the end of the queue
|
||||||
|
@ -9,11 +9,12 @@ pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult {
|
|||||||
let cap_ptr = tcb.trapframe.get_reg(1);
|
let cap_ptr = tcb.trapframe.get_reg(1);
|
||||||
let cap = cspace
|
let cap = cspace
|
||||||
.resolve_address_bits(cap_ptr, usize::BITS as usize)
|
.resolve_address_bits(cap_ptr, usize::BITS as usize)
|
||||||
.map_err(|e| SysError::from(e))?;
|
.map_err(SysError::from)?;
|
||||||
|
|
||||||
trace!("handle_syscall: info={:?} cap={:?}", info, cap);
|
trace!("handle_syscall: info={:?} cap={:?}", info, cap);
|
||||||
|
|
||||||
match info.label() {
|
match info.label() {
|
||||||
|
Syscall::Invalid => Ok(()),
|
||||||
Syscall::DebugPutChar => {
|
Syscall::DebugPutChar => {
|
||||||
if info.length() != 3 {
|
if info.length() != 3 {
|
||||||
return Err(SysError::InvalidArgument);
|
return Err(SysError::InvalidArgument);
|
||||||
@ -22,7 +23,11 @@ pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult {
|
|||||||
let c = tcb.trapframe.get_reg(2) as u8 as char;
|
let c = tcb.trapframe.get_reg(2) as u8 as char;
|
||||||
crate::print!("{}", c);
|
crate::print!("{}", c);
|
||||||
|
|
||||||
return Ok(());
|
Ok(())
|
||||||
|
},
|
||||||
|
Syscall::Yield => {
|
||||||
|
tcb.clear_timetick();
|
||||||
|
Ok(())
|
||||||
},
|
},
|
||||||
_ => unimplemented!("handle_syscall: {:?}, {:?}", info.label(), cap),
|
_ => unimplemented!("handle_syscall: {:?}, {:?}", info.label(), cap),
|
||||||
}
|
}
|
||||||
|
10
root/root.S
10
root/root.S
@ -10,13 +10,17 @@ _start:
|
|||||||
la t0, msg
|
la t0, msg
|
||||||
.loop:
|
.loop:
|
||||||
lb a2, 0(t0)
|
lb a2, 0(t0)
|
||||||
beqz a2, _start
|
beqz a2, .yield
|
||||||
# see uapi/syscall.rs
|
# msg: label = DebugPutChar(1), length = 3
|
||||||
# msg: label = DebugPutChar, length = 3
|
|
||||||
# ptr: self-referential to cspace, just to create a valid cptr
|
# ptr: self-referential to cspace, just to create a valid cptr
|
||||||
syscall (1<<12 | 3), 0x0202020202020202
|
syscall (1<<12 | 3), 0x0202020202020202
|
||||||
addi t0, t0, 1
|
addi t0, t0, 1
|
||||||
j .loop
|
j .loop
|
||||||
|
.yield:
|
||||||
|
# msg: label = Yield(2), length = 2
|
||||||
|
# ptr: self-referential to cspace, just to create a valid cptr
|
||||||
|
syscall (2<<12 | 2), 0x0202020202020202
|
||||||
|
j _start
|
||||||
|
|
||||||
.data
|
.data
|
||||||
msg : .string "Hello, world!\n\0"
|
msg : .string "Hello, world!\n\0"
|
||||||
|
Loading…
Reference in New Issue
Block a user