From 022d7f0e96b0b1a45846aed0df3f0beade9c4aaf Mon Sep 17 00:00:00 2001 From: Yuekai Jia Date: Sat, 18 Sep 2021 16:33:32 +0800 Subject: [PATCH] drivers: implement EventListener --- drivers/Cargo.toml | 4 +- drivers/src/lib.rs | 2 +- drivers/src/mock/uart.rs | 56 +++++++++++------ drivers/src/scheme/event.rs | 46 ++++++++++++++ drivers/src/scheme/mod.rs | 5 ++ drivers/src/uart/uart_16550.rs | 5 -- drivers/src/virtio/blk.rs | 6 +- drivers/src/virtio/console.rs | 6 +- kernel-hal/Cargo.toml | 2 +- kernel-hal/src/bare/arch/riscv/drivers.rs | 5 +- kernel-hal/src/bare/arch/riscv/interrupt.rs | 2 +- kernel-hal/src/bare/arch/riscv/mod.rs | 2 +- kernel-hal/src/bare/arch/riscv/plic.rs | 2 +- kernel-hal/src/bare/arch/x86_64/acpi_table.rs | 2 +- kernel-hal/src/bare/arch/x86_64/cpu.rs | 2 +- kernel-hal/src/bare/arch/x86_64/drivers.rs | 3 +- kernel-hal/src/bare/arch/x86_64/interrupt.rs | 12 ++-- kernel-hal/src/bare/timer.rs | 2 +- kernel-hal/src/common/future.rs | 63 ++++++++++--------- kernel-hal/src/common/mem.rs | 2 +- kernel-hal/src/common/mod.rs | 4 +- kernel-hal/src/common/serial.rs | 39 ++---------- kernel-hal/src/common/thread.rs | 13 ++++ kernel-hal/src/hal_fn.rs | 8 +-- kernel-hal/src/lib.rs | 6 +- kernel-hal/src/libos/dev/input.rs | 2 +- kernel-hal/src/libos/drivers.rs | 4 +- kernel-hal/src/libos/mem_common.rs | 2 +- kernel-hal/src/libos/mod.rs | 6 -- linux-loader/src/lib.rs | 7 +-- linux-loader/src/main.rs | 20 +++--- linux-syscall/src/task.rs | 2 +- zCore/src/main.rs | 24 +++---- zircon-loader/src/lib.rs | 2 +- zircon-object/src/task/thread.rs | 5 +- zircon-syscall/src/debug.rs | 13 ++-- zircon-syscall/src/time.rs | 6 +- 37 files changed, 227 insertions(+), 165 deletions(-) create mode 100644 drivers/src/scheme/event.rs create mode 100644 kernel-hal/src/common/thread.rs diff --git a/drivers/Cargo.toml b/drivers/Cargo.toml index bccac758..c4cedc14 100644 --- a/drivers/Cargo.toml +++ b/drivers/Cargo.toml @@ -8,7 +8,7 @@ description = "Device drivers of zCore" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -mock = [] +mock = ["async-std"] virtio = ["virtio-drivers"] [dependencies] @@ -16,4 +16,6 @@ log = "0.4" spin = "0.9" cfg-if = "1.0" bitflags = "1.3" +lazy_static = "1.4" virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2b3c6cf", optional = true } +async-std = { version = "1.10", optional = true } diff --git a/drivers/src/lib.rs b/drivers/src/lib.rs index b4383e92..624b140b 100644 --- a/drivers/src/lib.rs +++ b/drivers/src/lib.rs @@ -29,4 +29,4 @@ pub enum DeviceError { pub type DeviceResult = core::result::Result; -pub type IrqHandler = alloc::boxed::Box; +pub type IrqHandler = alloc::boxed::Box; diff --git a/drivers/src/mock/uart.rs b/drivers/src/mock/uart.rs index f8b94b34..09890cff 100644 --- a/drivers/src/mock/uart.rs +++ b/drivers/src/mock/uart.rs @@ -1,28 +1,43 @@ -use std::io::{self, Read}; -use std::sync::mpsc::{self, Receiver}; +use std::collections::VecDeque; use std::sync::Mutex; +use async_std::{io, io::prelude::*, task}; + use crate::scheme::{Scheme, UartScheme}; use crate::DeviceResult; -pub struct MockUart { - stdin_channel: Mutex>, +const UART_BUF_LEN: usize = 256; + +lazy_static::lazy_static! { + static ref UART_BUF: Mutex> = Mutex::new(VecDeque::with_capacity(UART_BUF_LEN)); } +pub struct MockUart; + impl MockUart { pub fn new() -> Self { - let (tx, rx) = mpsc::channel(); - std::thread::spawn(move || loop { - let mut buf = [0]; - io::stdin().read_exact(&mut buf).unwrap(); - if tx.send(buf[0]).is_err() { - break; + Self + } + + pub fn start_irq_serve(irq_handler: impl Fn() + Send + Sync + 'static) { + task::spawn(async move { + loop { + let mut buf = [0; UART_BUF_LEN]; + let remains = UART_BUF_LEN - UART_BUF.lock().unwrap().len(); + if remains > 0 { + if let Ok(n) = io::stdin().read(&mut buf[..remains]).await { + { + let mut uart_buf = UART_BUF.lock().unwrap(); + for c in &buf[..n] { + uart_buf.push_back(*c); + } + } + irq_handler(); + } + } + task::yield_now().await; } - core::hint::spin_loop(); }); - Self { - stdin_channel: Mutex::new(rx), - } } } @@ -36,9 +51,10 @@ impl Scheme for MockUart {} impl UartScheme for MockUart { fn try_recv(&self) -> DeviceResult> { - match self.stdin_channel.lock().unwrap().try_recv() { - Ok(ch) => Ok(Some(ch)), - _ => Ok(None), + if let Some(c) = UART_BUF.lock().unwrap().pop_front() { + Ok(Some(c)) + } else { + Ok(None) } } @@ -56,10 +72,14 @@ impl UartScheme for MockUart { #[cfg(test)] mod test { use super::*; + use std::sync::Arc; #[test] fn test_mock_uart() { - let uart = MockUart::new(); + let uart = Arc::new(MockUart::new()); + let u = uart.clone(); + MockUart::start_irq_serve(move || u.handle_irq(0)); + uart.write_str("Hello, World!\n").unwrap(); uart.write_str(format!("{} + {} = {}\n", 1, 2, 1 + 2).as_str()) .unwrap(); diff --git a/drivers/src/scheme/event.rs b/drivers/src/scheme/event.rs new file mode 100644 index 00000000..027a9b77 --- /dev/null +++ b/drivers/src/scheme/event.rs @@ -0,0 +1,46 @@ +use alloc::vec::Vec; + +use spin::Mutex; + +use super::{Scheme, UartScheme}; +use crate::{DeviceResult, IrqHandler}; + +pub struct EventListener { + inner: T, + events: Mutex>, +} + +impl EventListener { + pub fn new(inner: T) -> Self { + Self { + inner, + events: Mutex::new(Vec::new()), + } + } +} + +impl Scheme for EventListener { + fn handle_irq(&self, irq_num: u32) { + self.inner.handle_irq(irq_num); + self.events.lock().retain(|(f, once)| { + f(irq_num); + !once + }); + } + + fn subscribe(&self, handler: IrqHandler, once: bool) { + self.events.lock().push((handler, once)); + } +} + +impl UartScheme for EventListener { + fn try_recv(&self) -> DeviceResult> { + self.inner.try_recv() + } + fn send(&self, ch: u8) -> DeviceResult { + self.inner.send(ch) + } + fn write_str(&self, s: &str) -> DeviceResult { + self.inner.write_str(s) + } +} diff --git a/drivers/src/scheme/mod.rs b/drivers/src/scheme/mod.rs index d30b7ec7..c9557dc2 100644 --- a/drivers/src/scheme/mod.rs +++ b/drivers/src/scheme/mod.rs @@ -1,15 +1,20 @@ mod block; mod display; +mod event; mod input; mod net; mod uart; pub use block::BlockScheme; pub use display::DisplayScheme; +pub use event::EventListener; pub use input::InputScheme; pub use net::NetScheme; pub use uart::UartScheme; pub trait Scheme: Send + Sync { fn handle_irq(&self, _irq_num: u32) {} + fn subscribe(&self, _handler: crate::IrqHandler, _once: bool) { + unimplemented!("please call `subscribe()` with the `EventListener` wrapper") + } } diff --git a/drivers/src/uart/uart_16550.rs b/drivers/src/uart/uart_16550.rs index e2d96cdf..b668c51b 100644 --- a/drivers/src/uart/uart_16550.rs +++ b/drivers/src/uart/uart_16550.rs @@ -102,11 +102,6 @@ where fn write_str(&mut self, s: &str) -> DeviceResult { for b in s.bytes() { match b { - 8 | 0x7F => { - self.send(8)?; - self.send(b' ')?; - self.send(8)?; - } b'\n' => { self.send(b'\r')?; self.send(b'\n')?; diff --git a/drivers/src/virtio/blk.rs b/drivers/src/virtio/blk.rs index 6795dd93..c27e8f4c 100644 --- a/drivers/src/virtio/blk.rs +++ b/drivers/src/virtio/blk.rs @@ -16,7 +16,11 @@ impl<'a> VirtIoBlk<'a> { } } -impl<'a> Scheme for VirtIoBlk<'a> {} +impl<'a> Scheme for VirtIoBlk<'a> { + fn handle_irq(&self, _irq_num: u32) { + self.inner.lock().ack_interrupt(); + } +} impl<'a> BlockScheme for VirtIoBlk<'a> { fn read_block(&self, block_id: usize, buf: &mut [u8]) -> DeviceResult { diff --git a/drivers/src/virtio/console.rs b/drivers/src/virtio/console.rs index 6d634e7a..c512d7c7 100644 --- a/drivers/src/virtio/console.rs +++ b/drivers/src/virtio/console.rs @@ -18,7 +18,11 @@ impl<'a> VirtIoConsole<'a> { } } -impl<'a> Scheme for VirtIoConsole<'a> {} +impl<'a> Scheme for VirtIoConsole<'a> { + fn handle_irq(&self, _irq_num: u32) { + self.inner.lock().ack_interrupt().unwrap(); + } +} impl<'a> UartScheme for VirtIoConsole<'a> { fn try_recv(&self) -> DeviceResult> { diff --git a/kernel-hal/Cargo.toml b/kernel-hal/Cargo.toml index 86274dc6..2a522103 100644 --- a/kernel-hal/Cargo.toml +++ b/kernel-hal/Cargo.toml @@ -28,7 +28,7 @@ zcore-drivers = { path = "../drivers" } libc = "0.2" tempfile = "3" lazy_static = "1.4" -async-std = { version = "1.9", optional = true } +async-std = { version = "1.10", optional = true } # Bare-metal mode [target.'cfg(target_os = "none")'.dependencies] diff --git a/kernel-hal/src/bare/arch/riscv/drivers.rs b/kernel-hal/src/bare/arch/riscv/drivers.rs index 1d920f5f..67a6d383 100644 --- a/kernel-hal/src/bare/arch/riscv/drivers.rs +++ b/kernel-hal/src/bare/arch/riscv/drivers.rs @@ -1,11 +1,12 @@ use alloc::boxed::Box; +use zcore_drivers::scheme::EventListener; use zcore_drivers::uart::Uart16550Mmio; use crate::{drivers::UART, mem::phys_to_virt}; pub(super) fn init() { - UART.init_by(Box::new(unsafe { + UART.init_by(Box::new(EventListener::new(unsafe { Uart16550Mmio::::new(phys_to_virt(super::consts::UART_BASE)) - })); + }))); } diff --git a/kernel-hal/src/bare/arch/riscv/interrupt.rs b/kernel-hal/src/bare/arch/riscv/interrupt.rs index b2e65f12..b15321b5 100644 --- a/kernel-hal/src/bare/arch/riscv/interrupt.rs +++ b/kernel-hal/src/bare/arch/riscv/interrupt.rs @@ -11,7 +11,7 @@ const U_PLIC: u32 = 8; const S_PLIC: u32 = 9; const M_PLIC: u32 = 11; -lazy_static::lazy_static! { +lazy_static! { static ref IRQ_MANAGER: Mutex = Mutex::new(IrqManager::new(1, 15)); } diff --git a/kernel-hal/src/bare/arch/riscv/mod.rs b/kernel-hal/src/bare/arch/riscv/mod.rs index 04df6f68..a2801404 100644 --- a/kernel-hal/src/bare/arch/riscv/mod.rs +++ b/kernel-hal/src/bare/arch/riscv/mod.rs @@ -17,9 +17,9 @@ pub mod vm; pub fn init() { vm::remap_the_kernel().unwrap(); + drivers::init(); interrupt::init(); timer::init(); - drivers::init(); #[cfg(feature = "board_qemu")] { diff --git a/kernel-hal/src/bare/arch/riscv/plic.rs b/kernel-hal/src/bare/arch/riscv/plic.rs index 2acefd62..5a73e433 100644 --- a/kernel-hal/src/bare/arch/riscv/plic.rs +++ b/kernel-hal/src/bare/arch/riscv/plic.rs @@ -88,7 +88,7 @@ pub(super) fn handle_interrupt() { } UART0_INT_NUM => { //UART中断ID是10 - crate::serial::handle_irq(); + crate::drivers::UART.handle_irq(UART0_INT_NUM); //换用sbi的方式获取字符 //interrupt::try_process_serial(); diff --git a/kernel-hal/src/bare/arch/x86_64/acpi_table.rs b/kernel-hal/src/bare/arch/x86_64/acpi_table.rs index c9facb2d..97957d2e 100644 --- a/kernel-hal/src/bare/arch/x86_64/acpi_table.rs +++ b/kernel-hal/src/bare/arch/x86_64/acpi_table.rs @@ -13,7 +13,7 @@ pub struct AcpiTable { inner: Acpi, } -lazy_static::lazy_static! { +lazy_static! { static ref ACPI_TABLE: Mutex> = Mutex::default(); } diff --git a/kernel-hal/src/bare/arch/x86_64/cpu.rs b/kernel-hal/src/bare/arch/x86_64/cpu.rs index cc911c22..b9cf8b2c 100644 --- a/kernel-hal/src/bare/arch/x86_64/cpu.rs +++ b/kernel-hal/src/bare/arch/x86_64/cpu.rs @@ -1,4 +1,4 @@ -lazy_static::lazy_static! { +lazy_static! { static ref TSC_FREQUENCY: u16 = { const DEFAULT: u16 = 2600; if let Some(info) = raw_cpuid::CpuId::new().get_processor_frequency_info() { diff --git a/kernel-hal/src/bare/arch/x86_64/drivers.rs b/kernel-hal/src/bare/arch/x86_64/drivers.rs index 915c1a8b..3480a15f 100644 --- a/kernel-hal/src/bare/arch/x86_64/drivers.rs +++ b/kernel-hal/src/bare/arch/x86_64/drivers.rs @@ -1,9 +1,10 @@ use alloc::boxed::Box; +use zcore_drivers::scheme::EventListener; use zcore_drivers::uart::Uart16550Pio; use crate::drivers::UART; pub(super) fn init() { - UART.init_by(Box::new(Uart16550Pio::new(0x3F8))); + UART.init_by(Box::new(EventListener::new(Uart16550Pio::new(0x3F8)))); } diff --git a/kernel-hal/src/bare/arch/x86_64/interrupt.rs b/kernel-hal/src/bare/arch/x86_64/interrupt.rs index d23083ff..5676a31a 100644 --- a/kernel-hal/src/bare/arch/x86_64/interrupt.rs +++ b/kernel-hal/src/bare/arch/x86_64/interrupt.rs @@ -28,7 +28,7 @@ const Spurious: u32 = 31; const IO_APIC_NUM_REDIRECTIONS: u8 = 120; -lazy_static::lazy_static! { +lazy_static! { static ref IRQ_MANAGER: Mutex = Mutex::new(IrqManager::new(0x20, 0xff)); static ref MAX_INSTR_TABLE: Mutex> = Mutex::default(); } @@ -239,10 +239,6 @@ fn timer() { crate::timer::timer_tick(); } -fn com1() { - crate::serial::handle_irq(); -} - /* fn keyboard() { use pc_keyboard::{DecodedKey, KeyCode}; @@ -285,7 +281,11 @@ pub(super) fn init() { .ok(); // im.register_handler(Keyboard + IRQ_MIN_ID, Box::new(keyboard)); // im.register_handler(Mouse + IRQ_MIN_ID, Box::new(mouse)); - im.register_handler(COM1 + IRQ_MIN_ID, Box::new(com1)).ok(); + im.register_handler( + COM1 + IRQ_MIN_ID, + Box::new(|| crate::drivers::UART.handle_irq(COM1)), + ) + .ok(); im.register_handler(57u32, Box::new(irq57test)).ok(); // register_handler(Keyboard, Keyboard + IRQ_MIN_ID); // register_handler(Mouse, Mouse + IRQ_MIN_ID); diff --git a/kernel-hal/src/bare/timer.rs b/kernel-hal/src/bare/timer.rs index 4f5cf0f5..755b2904 100644 --- a/kernel-hal/src/bare/timer.rs +++ b/kernel-hal/src/bare/timer.rs @@ -4,7 +4,7 @@ use core::time::Duration; use naive_timer::Timer; use spin::Mutex; -lazy_static::lazy_static! { +lazy_static! { pub static ref NAIVE_TIMER: Mutex = Mutex::new(Timer::default()); } diff --git a/kernel-hal/src/common/future.rs b/kernel-hal/src/common/future.rs index 41c5ea18..bc3783f1 100644 --- a/kernel-hal/src/common/future.rs +++ b/kernel-hal/src/common/future.rs @@ -1,17 +1,11 @@ use alloc::boxed::Box; -use core::future::Future; -use core::pin::Pin; use core::task::{Context, Poll}; use core::time::Duration; - -/// Yields execution back to the async runtime. -pub fn yield_now() -> impl Future { - YieldFuture::default() -} +use core::{future::Future, pin::Pin}; #[must_use = "yield_now does nothing unless polled/`await`-ed"] #[derive(Default)] -struct YieldFuture { +pub(super) struct YieldFuture { flag: bool, } @@ -29,14 +23,15 @@ impl Future for YieldFuture { } } -/// Sleeps until the specified of time. -pub fn sleep_until(deadline: Duration) -> impl Future { - SleepFuture { deadline } +#[must_use = "sleep does nothing unless polled/`await`-ed"] +pub(super) struct SleepFuture { + deadline: Duration, } -#[must_use = "sleep does nothing unless polled/`await`-ed"] -pub struct SleepFuture { - deadline: Duration, +impl SleepFuture { + pub fn new(deadline: Duration) -> Self { + Self { deadline } + } } impl Future for SleepFuture { @@ -54,29 +49,37 @@ impl Future for SleepFuture { } } -/// Get a char from serial. -pub fn serial_getchar() -> impl Future { - SerialFuture +#[must_use = "serial_getchar does nothing unless polled/`await`-ed"] +pub(super) struct SerialFuture<'a> { + buf: &'a mut [u8], } -#[must_use = "serial_getchar does nothing unless polled/`await`-ed"] -pub struct SerialFuture; +impl<'a> SerialFuture<'a> { + pub fn new(buf: &'a mut [u8]) -> Self { + Self { buf } + } +} -impl Future for SerialFuture { - type Output = u8; +impl Future for SerialFuture<'_> { + type Output = usize; fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { - let mut buf = [0u8]; - if crate::serial::serial_read(&mut buf) != 0 { - return Poll::Ready(buf[0]); + use crate::drivers::UART; + let buf = &mut self.get_mut().buf; + let mut n = 0; + for i in 0..buf.len() { + if let Some(c) = UART.try_recv().unwrap() { + buf[i] = if c == b'\r' { b'\n' } else { c }; + n += 1; + } else { + break; + } + } + if n > 0 { + return Poll::Ready(n); } let waker = cx.waker().clone(); - crate::serial::serial_set_callback(Box::new({ - move || { - waker.wake_by_ref(); - true - } - })); + UART.subscribe(Box::new(move |_| waker.wake_by_ref()), true); Poll::Pending } } diff --git a/kernel-hal/src/common/mem.rs b/kernel-hal/src/common/mem.rs index 361a92d4..b0e6522c 100644 --- a/kernel-hal/src/common/mem.rs +++ b/kernel-hal/src/common/mem.rs @@ -72,7 +72,7 @@ impl Drop for PhysFrame { } } -lazy_static::lazy_static! { +lazy_static! { /// The global physical frame contains all zeros. pub static ref ZERO_FRAME: PhysFrame = PhysFrame::new_zero().expect("failed to alloc zero frame"); } diff --git a/kernel-hal/src/common/mod.rs b/kernel-hal/src/common/mod.rs index 21189b63..49b1ed3f 100644 --- a/kernel-hal/src/common/mod.rs +++ b/kernel-hal/src/common/mod.rs @@ -1,12 +1,14 @@ +mod future; + pub(super) mod defs; pub(super) mod fb; pub mod addr; pub mod context; pub mod drivers; -pub mod future; pub mod mem; pub mod serial; +pub mod thread; pub mod user; pub mod vdso; pub mod vm; diff --git a/kernel-hal/src/common/serial.rs b/kernel-hal/src/common/serial.rs index a1b0e85d..20939ebe 100644 --- a/kernel-hal/src/common/serial.rs +++ b/kernel-hal/src/common/serial.rs @@ -1,16 +1,7 @@ -use alloc::{boxed::Box, collections::VecDeque, vec::Vec}; use core::fmt::{Arguments, Result, Write}; -use spin::Mutex; - use crate::drivers::UART; -lazy_static::lazy_static! { - static ref STDIN: Mutex> = Mutex::new(VecDeque::new()); - static ref STDIN_CALLBACK: Mutex bool + Send + Sync>>> = - Mutex::new(Vec::new()); -} - struct SerialWriter; impl Write for SerialWriter { @@ -22,31 +13,6 @@ impl Write for SerialWriter { } } -pub(crate) fn handle_irq() { - if let Some(uart) = UART.try_get() { - if let Some(c) = uart.try_recv().unwrap() { - let c = if c == b'\r' { b'\n' } else { c }; - STDIN.lock().push_back(c); - STDIN_CALLBACK.lock().retain(|f| !f()); - } - } -} - -/// Register a callback of serial readable event. -pub fn serial_set_callback(callback: Box bool + Send + Sync>) { - STDIN_CALLBACK.lock().push(callback); -} - -/// Read a string from serial buffer. -pub fn serial_read(buf: &mut [u8]) -> usize { - let mut stdin = STDIN.lock(); - let len = stdin.len().min(buf.len()); - for c in &mut buf[..len] { - *c = stdin.pop_front().unwrap(); - } - len -} - /// Print format string and its arguments to serial. pub fn serial_write_fmt(fmt: Arguments) { SerialWriter.write_fmt(fmt).unwrap(); @@ -56,3 +22,8 @@ pub fn serial_write_fmt(fmt: Arguments) { pub fn serial_write(s: &str) { serial_write_fmt(format_args!("{}", s)); } + +/// Get a char from serial. +pub async fn serial_read(buf: &mut [u8]) -> usize { + super::future::SerialFuture::new(buf).await +} diff --git a/kernel-hal/src/common/thread.rs b/kernel-hal/src/common/thread.rs new file mode 100644 index 00000000..aa7938b8 --- /dev/null +++ b/kernel-hal/src/common/thread.rs @@ -0,0 +1,13 @@ +use core::time::Duration; + +use super::future::{SleepFuture, YieldFuture}; + +/// Sleeps until the specified of time. +pub async fn sleep_until(deadline: Duration) { + SleepFuture::new(deadline).await +} + +/// Yields execution back to the async runtime. +pub async fn yield_now() { + YieldFuture::default().await +} diff --git a/kernel-hal/src/hal_fn.rs b/kernel-hal/src/hal_fn.rs index 4a9724c2..18157562 100644 --- a/kernel-hal/src/hal_fn.rs +++ b/kernel-hal/src/hal_fn.rs @@ -33,12 +33,12 @@ hal_fn_def! { } pub mod vm: common::vm { + /// Read current VM token. (e.g. CR3, SATP, ...) + pub fn current_vmtoken() -> PhysAddr; + /// Activate this page table by given `vmtoken`. pub(crate) fn activate_paging(vmtoken: PhysAddr); - /// Read current VM token. (e.g. CR3, SATP, ...) - pub(crate) fn current_vmtoken() -> PhysAddr; - /// Flush TLB by the associated `vaddr`, or flush the entire TLB. (`vaddr` is `None`). pub(crate) fn flush_tlb(vaddr: Option); @@ -103,7 +103,7 @@ hal_fn_def! { pub fn fetch_page_fault_info(info_reg: usize) -> (VirtAddr, MMUFlags); } - pub mod thread { + pub mod thread: common::thread { /// Spawn a new thread. pub fn spawn(future: Pin + Send + 'static>>, vmtoken: usize); diff --git a/kernel-hal/src/lib.rs b/kernel-hal/src/lib.rs index b83335c2..2570cb01 100644 --- a/kernel-hal/src/lib.rs +++ b/kernel-hal/src/lib.rs @@ -5,12 +5,12 @@ #![deny(warnings)] extern crate alloc; - #[macro_use] extern crate log; - #[macro_use] extern crate cfg_if; +#[macro_use] +extern crate lazy_static; #[macro_use] mod macros; @@ -31,7 +31,7 @@ cfg_if! { } } -pub use common::{addr, defs::*, drivers, future, serial, user}; +pub use common::{addr, defs::*, drivers, serial, user}; pub use config::*; pub use imp::*; pub use kernel_handler::*; diff --git a/kernel-hal/src/libos/dev/input.rs b/kernel-hal/src/libos/dev/input.rs index a21e7918..589effa0 100644 --- a/kernel-hal/src/libos/dev/input.rs +++ b/kernel-hal/src/libos/dev/input.rs @@ -20,7 +20,7 @@ struct InputEvent { value: i32, } -lazy_static::lazy_static! { +lazy_static! { static ref MOUSE_CALLBACK: Mutex>> = Mutex::new(Vec::new()); static ref KBD_CALLBACK: Mutex>> = Mutex::new(Vec::new()); } diff --git a/kernel-hal/src/libos/drivers.rs b/kernel-hal/src/libos/drivers.rs index 437b503a..90f62945 100644 --- a/kernel-hal/src/libos/drivers.rs +++ b/kernel-hal/src/libos/drivers.rs @@ -1,9 +1,11 @@ use alloc::boxed::Box; use zcore_drivers::mock::MockUart; +use zcore_drivers::scheme::EventListener; use crate::drivers::UART; pub(super) fn init() { - UART.init_by(Box::new(MockUart::new())); + UART.init_by(Box::new(EventListener::new(MockUart::new()))); + MockUart::start_irq_serve(|| UART.handle_irq(0)); } diff --git a/kernel-hal/src/libos/mem_common.rs b/kernel-hal/src/libos/mem_common.rs index f1c1a7ab..752ea3e2 100644 --- a/kernel-hal/src/libos/mem_common.rs +++ b/kernel-hal/src/libos/mem_common.rs @@ -10,7 +10,7 @@ use crate::{mem::phys_to_virt, VirtAddr, PAGE_SIZE}; pub(super) const PMEM_BASE: VirtAddr = 0x8_0000_0000; pub(super) const PMEM_SIZE: usize = 0x4000_0000; // 1GiB -lazy_static::lazy_static! { +lazy_static! { pub(super) static ref FRAME_FILE: File = create_pmem_file(); pub(super) static ref AVAILABLE_FRAMES: Mutex> = Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect()); diff --git a/kernel-hal/src/libos/mod.rs b/kernel-hal/src/libos/mod.rs index cb6ffd02..edf2d144 100644 --- a/kernel-hal/src/libos/mod.rs +++ b/kernel-hal/src/libos/mod.rs @@ -38,10 +38,4 @@ pub fn init() { unsafe { register_sigsegv_handler(); } - // spawn a thread to read stdin - // TODO: raw mode - std::thread::spawn(|| loop { - crate::serial::handle_irq(); - core::hint::spin_loop(); - }); } diff --git a/linux-loader/src/lib.rs b/linux-loader/src/lib.rs index ab8ec836..c75a729e 100644 --- a/linux-loader/src/lib.rs +++ b/linux-loader/src/lib.rs @@ -56,8 +56,7 @@ pub fn run(args: Vec, envs: Vec, rootfs: Arc) -> let path = args[0].clone(); debug!("Linux process: {:?}", path); - use kernel_hal::vm::{GenericPageTable, PageTable}; - let pg_token = PageTable::from_current().table_phys(); + let pg_token = kernel_hal::vm::current_vmtoken(); debug!("current pgt = {:#x}", pg_token); //调用zircon-object/src/task/thread.start设置好要执行的thread let (entry, sp) = loader.load(&proc.vmar(), &data, args, envs, path).unwrap(); @@ -96,7 +95,7 @@ async fn new_thread(thread: CurrentThread) { 0x20..=0x3f => { kernel_hal::interrupt::handle_irq(cx.trap_num as u32); if cx.trap_num == 0x20 { - kernel_hal::future::yield_now().await; + kernel_hal::thread::yield_now().await; } } 0xe => { @@ -133,7 +132,7 @@ async fn new_thread(thread: CurrentThread) { if trap_num == 4 || trap_num == 5 { debug!("Timer interrupt: {}", trap_num); - kernel_hal::future::yield_now().await; + kernel_hal::thread::yield_now().await; } //kernel_hal::interrupt::handle_irq(trap_num as u32); diff --git a/linux-loader/src/main.rs b/linux-loader/src/main.rs index 5e380260..9e2a6a82 100644 --- a/linux-loader/src/main.rs +++ b/linux-loader/src/main.rs @@ -21,16 +21,18 @@ async fn main() { kernel_hal::dev::fb::init(); kernel_hal::dev::input::init(); } - kernel_hal::serial::serial_set_callback(Box::new({ - move || { - let mut buffer = [0; 255]; - let len = kernel_hal::serial::serial_read(&mut buffer); - for c in &buffer[..len] { - STDIN.push((*c).into()); + + use kernel_hal::drivers::UART; + UART.subscribe( + Box::new(|_| { + while let Some(c) = UART.try_recv().unwrap() { + let c = if c == b'\r' { b'\n' } else { c }; + STDIN.push(c as char); } - false - } - })); + }), + false, + ); + // run first process let args: Vec<_> = std::env::args().skip(1).collect(); let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()]; diff --git a/linux-syscall/src/task.rs b/linux-syscall/src/task.rs index 0fd79f5a..f99296d3 100644 --- a/linux-syscall/src/task.rs +++ b/linux-syscall/src/task.rs @@ -297,7 +297,7 @@ impl Syscall<'_> { pub async fn sys_nanosleep(&self, req: UserInPtr) -> SysResult { info!("nanosleep: deadline={:?}", req); let req = req.read()?; - kernel_hal::future::sleep_until(req.into()).await; + kernel_hal::thread::sleep_until(req.into()).await; Ok(0) } diff --git a/zCore/src/main.rs b/zCore/src/main.rs index 6662c989..4d8baea1 100644 --- a/zCore/src/main.rs +++ b/zCore/src/main.rs @@ -167,19 +167,18 @@ fn get_rootproc(cmdline: &str) -> Vec { #[cfg(feature = "linux")] fn main(ramfs_data: &'static mut [u8], cmdline: &str) -> ! { + use kernel_hal::drivers::UART; use linux_object::fs::STDIN; - kernel_hal::serial::serial_set_callback(Box::new({ - move || { - let mut buffer = [0; 255]; - let len = kernel_hal::serial::serial_read(&mut buffer); - for c in &buffer[..len] { - STDIN.push((*c).into()); - // kernel_hal::serial::serial_write(alloc::format!("{}", *c as char).as_str()); + UART.subscribe( + Box::new(|_| { + while let Some(c) = UART.try_recv().unwrap() { + let c = if c == b'\r' { b'\n' } else { c }; + STDIN.push(c as char); } - false - } - })); + }), + false, + ); //let args: Vec = vec!["/bin/busybox".into(), "sh".into()]; let args: Vec = get_rootproc(cmdline); @@ -234,6 +233,9 @@ impl KernelHandler for ZcoreKernelHandler { } fn handle_page_fault(&self, fault_vaddr: usize, access_flags: MMUFlags) { - panic!("page fault from kernel mode @ {:#x}({:?})", fault_vaddr, access_flags); + panic!( + "page fault from kernel mode @ {:#x}({:?})", + fault_vaddr, access_flags + ); } } diff --git a/zircon-loader/src/lib.rs b/zircon-loader/src/lib.rs index f1adea71..05d0b416 100644 --- a/zircon-loader/src/lib.rs +++ b/zircon-loader/src/lib.rs @@ -220,7 +220,7 @@ async fn new_thread(thread: CurrentThread) { kernel_hal::interrupt::handle_irq(trap_num as u32); if trap_num == 0x20 { EXCEPTIONS_TIMER.add(1); - kernel_hal::future::yield_now().await; + kernel_hal::thread::yield_now().await; } } 0xe => { diff --git a/zircon-object/src/task/thread.rs b/zircon-object/src/task/thread.rs index 1d6ecf90..73c6e454 100644 --- a/zircon-object/src/task/thread.rs +++ b/zircon-object/src/task/thread.rs @@ -15,7 +15,6 @@ use { }, futures::{channel::oneshot::*, future::FutureExt, pin_mut, select_biased}, kernel_hal::context::{GeneralRegs, UserContext}, - // kernel_hal::future::sleep_until, spin::Mutex, }; @@ -603,14 +602,14 @@ impl CurrentThread { select_biased! { ret = future.fuse() => ret.into_result(), _ = killed.fuse() => Err(ZxError::STOP), - _ = kernel_hal::future::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), + _ = kernel_hal::thread::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), _ = cancel_token.fuse() => Err(ZxError::CANCELED), } } else { select_biased! { ret = future.fuse() => ret.into_result(), _ = killed.fuse() => Err(ZxError::STOP), - _ = kernel_hal::future::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), + _ = kernel_hal::thread::sleep_until(deadline).fuse() => Err(ZxError::TIMED_OUT), } }; let mut inner = self.inner.lock(); diff --git a/zircon-syscall/src/debug.rs b/zircon-syscall/src/debug.rs index 941d81c0..83d588ef 100644 --- a/zircon-syscall/src/debug.rs +++ b/zircon-syscall/src/debug.rs @@ -25,15 +25,10 @@ impl Syscall<'_> { let proc = self.thread.proc(); proc.get_object::(handle)? .validate(ResourceKind::ROOT)?; - // FIXME: To make 'console' work, now debug_read is a blocking call. - // But it should be non-blocking. - // let mut vec = vec![0u8; buf_size as usize]; - // let len = kernel_hal::serial_read(&mut vec); - // buf.write_array(&vec[..len])?; - // actual.write(len as u32)?; - let c = kernel_hal::future::serial_getchar().await; - buf.write_array(&[c])?; - actual.write(1)?; + let mut vec = vec![0u8; buf_size as usize]; + let len = kernel_hal::serial::serial_read(&mut vec).await; + buf.write_array(&vec[..len])?; + actual.write(len as u32)?; Ok(()) } } diff --git a/zircon-syscall/src/time.rs b/zircon-syscall/src/time.rs index 5ae43ef0..1d6e01c2 100644 --- a/zircon-syscall/src/time.rs +++ b/zircon-syscall/src/time.rs @@ -94,11 +94,13 @@ impl Syscall<'_> { pub async fn sys_nanosleep(&self, deadline: Deadline) -> ZxResult { info!("nanosleep: deadline={:?}", deadline); if deadline.0 <= 0 { - kernel_hal::future::yield_now().await; + kernel_hal::thread::yield_now().await; } else { + let future = kernel_hal::thread::sleep_until(deadline.into()); + pin_mut!(future); self.thread .blocking_run( - kernel_hal::future::sleep_until(deadline.into()), + future, ThreadState::BlockedSleeping, Deadline::forever().into(), None,