drivers: implement EventListener

This commit is contained in:
Yuekai Jia 2021-09-18 16:33:32 +08:00
parent 994f8b80f2
commit 022d7f0e96
37 changed files with 227 additions and 165 deletions

View File

@ -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 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
mock = [] mock = ["async-std"]
virtio = ["virtio-drivers"] virtio = ["virtio-drivers"]
[dependencies] [dependencies]
@ -16,4 +16,6 @@ log = "0.4"
spin = "0.9" spin = "0.9"
cfg-if = "1.0" cfg-if = "1.0"
bitflags = "1.3" bitflags = "1.3"
lazy_static = "1.4"
virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2b3c6cf", optional = true } virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers", rev = "2b3c6cf", optional = true }
async-std = { version = "1.10", optional = true }

View File

@ -29,4 +29,4 @@ pub enum DeviceError {
pub type DeviceResult<T = ()> = core::result::Result<T, DeviceError>; pub type DeviceResult<T = ()> = core::result::Result<T, DeviceError>;
pub type IrqHandler = alloc::boxed::Box<dyn Fn() + Send + Sync>; pub type IrqHandler = alloc::boxed::Box<dyn Fn(u32) + Send + Sync>;

View File

@ -1,28 +1,43 @@
use std::io::{self, Read}; use std::collections::VecDeque;
use std::sync::mpsc::{self, Receiver};
use std::sync::Mutex; use std::sync::Mutex;
use async_std::{io, io::prelude::*, task};
use crate::scheme::{Scheme, UartScheme}; use crate::scheme::{Scheme, UartScheme};
use crate::DeviceResult; use crate::DeviceResult;
pub struct MockUart { const UART_BUF_LEN: usize = 256;
stdin_channel: Mutex<Receiver<u8>>,
lazy_static::lazy_static! {
static ref UART_BUF: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::with_capacity(UART_BUF_LEN));
} }
pub struct MockUart;
impl MockUart { impl MockUart {
pub fn new() -> Self { pub fn new() -> Self {
let (tx, rx) = mpsc::channel(); Self
std::thread::spawn(move || loop { }
let mut buf = [0];
io::stdin().read_exact(&mut buf).unwrap(); pub fn start_irq_serve(irq_handler: impl Fn() + Send + Sync + 'static) {
if tx.send(buf[0]).is_err() { task::spawn(async move {
break; 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 { impl UartScheme for MockUart {
fn try_recv(&self) -> DeviceResult<Option<u8>> { fn try_recv(&self) -> DeviceResult<Option<u8>> {
match self.stdin_channel.lock().unwrap().try_recv() { if let Some(c) = UART_BUF.lock().unwrap().pop_front() {
Ok(ch) => Ok(Some(ch)), Ok(Some(c))
_ => Ok(None), } else {
Ok(None)
} }
} }
@ -56,10 +72,14 @@ impl UartScheme for MockUart {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use std::sync::Arc;
#[test] #[test]
fn test_mock_uart() { 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("Hello, World!\n").unwrap();
uart.write_str(format!("{} + {} = {}\n", 1, 2, 1 + 2).as_str()) uart.write_str(format!("{} + {} = {}\n", 1, 2, 1 + 2).as_str())
.unwrap(); .unwrap();

View File

@ -0,0 +1,46 @@
use alloc::vec::Vec;
use spin::Mutex;
use super::{Scheme, UartScheme};
use crate::{DeviceResult, IrqHandler};
pub struct EventListener<T: Scheme> {
inner: T,
events: Mutex<Vec<(IrqHandler, bool)>>,
}
impl<T: Scheme> EventListener<T> {
pub fn new(inner: T) -> Self {
Self {
inner,
events: Mutex::new(Vec::new()),
}
}
}
impl<T: Scheme> Scheme for EventListener<T> {
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<T: UartScheme> UartScheme for EventListener<T> {
fn try_recv(&self) -> DeviceResult<Option<u8>> {
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)
}
}

View File

@ -1,15 +1,20 @@
mod block; mod block;
mod display; mod display;
mod event;
mod input; mod input;
mod net; mod net;
mod uart; mod uart;
pub use block::BlockScheme; pub use block::BlockScheme;
pub use display::DisplayScheme; pub use display::DisplayScheme;
pub use event::EventListener;
pub use input::InputScheme; pub use input::InputScheme;
pub use net::NetScheme; pub use net::NetScheme;
pub use uart::UartScheme; pub use uart::UartScheme;
pub trait Scheme: Send + Sync { pub trait Scheme: Send + Sync {
fn handle_irq(&self, _irq_num: u32) {} fn handle_irq(&self, _irq_num: u32) {}
fn subscribe(&self, _handler: crate::IrqHandler, _once: bool) {
unimplemented!("please call `subscribe()` with the `EventListener` wrapper")
}
} }

View File

@ -102,11 +102,6 @@ where
fn write_str(&mut self, s: &str) -> DeviceResult { fn write_str(&mut self, s: &str) -> DeviceResult {
for b in s.bytes() { for b in s.bytes() {
match b { match b {
8 | 0x7F => {
self.send(8)?;
self.send(b' ')?;
self.send(8)?;
}
b'\n' => { b'\n' => {
self.send(b'\r')?; self.send(b'\r')?;
self.send(b'\n')?; self.send(b'\n')?;

View File

@ -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> { impl<'a> BlockScheme for VirtIoBlk<'a> {
fn read_block(&self, block_id: usize, buf: &mut [u8]) -> DeviceResult { fn read_block(&self, block_id: usize, buf: &mut [u8]) -> DeviceResult {

View File

@ -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> { impl<'a> UartScheme for VirtIoConsole<'a> {
fn try_recv(&self) -> DeviceResult<Option<u8>> { fn try_recv(&self) -> DeviceResult<Option<u8>> {

View File

@ -28,7 +28,7 @@ zcore-drivers = { path = "../drivers" }
libc = "0.2" libc = "0.2"
tempfile = "3" tempfile = "3"
lazy_static = "1.4" lazy_static = "1.4"
async-std = { version = "1.9", optional = true } async-std = { version = "1.10", optional = true }
# Bare-metal mode # Bare-metal mode
[target.'cfg(target_os = "none")'.dependencies] [target.'cfg(target_os = "none")'.dependencies]

View File

@ -1,11 +1,12 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use zcore_drivers::scheme::EventListener;
use zcore_drivers::uart::Uart16550Mmio; use zcore_drivers::uart::Uart16550Mmio;
use crate::{drivers::UART, mem::phys_to_virt}; use crate::{drivers::UART, mem::phys_to_virt};
pub(super) fn init() { pub(super) fn init() {
UART.init_by(Box::new(unsafe { UART.init_by(Box::new(EventListener::new(unsafe {
Uart16550Mmio::<u8>::new(phys_to_virt(super::consts::UART_BASE)) Uart16550Mmio::<u8>::new(phys_to_virt(super::consts::UART_BASE))
})); })));
} }

View File

@ -11,7 +11,7 @@ const U_PLIC: u32 = 8;
const S_PLIC: u32 = 9; const S_PLIC: u32 = 9;
const M_PLIC: u32 = 11; const M_PLIC: u32 = 11;
lazy_static::lazy_static! { lazy_static! {
static ref IRQ_MANAGER: Mutex<IrqManager> = Mutex::new(IrqManager::new(1, 15)); static ref IRQ_MANAGER: Mutex<IrqManager> = Mutex::new(IrqManager::new(1, 15));
} }

View File

@ -17,9 +17,9 @@ pub mod vm;
pub fn init() { pub fn init() {
vm::remap_the_kernel().unwrap(); vm::remap_the_kernel().unwrap();
drivers::init();
interrupt::init(); interrupt::init();
timer::init(); timer::init();
drivers::init();
#[cfg(feature = "board_qemu")] #[cfg(feature = "board_qemu")]
{ {

View File

@ -88,7 +88,7 @@ pub(super) fn handle_interrupt() {
} }
UART0_INT_NUM => { UART0_INT_NUM => {
//UART中断ID是10 //UART中断ID是10
crate::serial::handle_irq(); crate::drivers::UART.handle_irq(UART0_INT_NUM);
//换用sbi的方式获取字符 //换用sbi的方式获取字符
//interrupt::try_process_serial(); //interrupt::try_process_serial();

View File

@ -13,7 +13,7 @@ pub struct AcpiTable {
inner: Acpi, inner: Acpi,
} }
lazy_static::lazy_static! { lazy_static! {
static ref ACPI_TABLE: Mutex<Option<AcpiTable>> = Mutex::default(); static ref ACPI_TABLE: Mutex<Option<AcpiTable>> = Mutex::default();
} }

View File

@ -1,4 +1,4 @@
lazy_static::lazy_static! { lazy_static! {
static ref TSC_FREQUENCY: u16 = { static ref TSC_FREQUENCY: u16 = {
const DEFAULT: u16 = 2600; const DEFAULT: u16 = 2600;
if let Some(info) = raw_cpuid::CpuId::new().get_processor_frequency_info() { if let Some(info) = raw_cpuid::CpuId::new().get_processor_frequency_info() {

View File

@ -1,9 +1,10 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use zcore_drivers::scheme::EventListener;
use zcore_drivers::uart::Uart16550Pio; use zcore_drivers::uart::Uart16550Pio;
use crate::drivers::UART; use crate::drivers::UART;
pub(super) fn init() { pub(super) fn init() {
UART.init_by(Box::new(Uart16550Pio::new(0x3F8))); UART.init_by(Box::new(EventListener::new(Uart16550Pio::new(0x3F8))));
} }

View File

@ -28,7 +28,7 @@ const Spurious: u32 = 31;
const IO_APIC_NUM_REDIRECTIONS: u8 = 120; const IO_APIC_NUM_REDIRECTIONS: u8 = 120;
lazy_static::lazy_static! { lazy_static! {
static ref IRQ_MANAGER: Mutex<IrqManager> = Mutex::new(IrqManager::new(0x20, 0xff)); static ref IRQ_MANAGER: Mutex<IrqManager> = Mutex::new(IrqManager::new(0x20, 0xff));
static ref MAX_INSTR_TABLE: Mutex<Vec<(usize, u8)>> = Mutex::default(); static ref MAX_INSTR_TABLE: Mutex<Vec<(usize, u8)>> = Mutex::default();
} }
@ -239,10 +239,6 @@ fn timer() {
crate::timer::timer_tick(); crate::timer::timer_tick();
} }
fn com1() {
crate::serial::handle_irq();
}
/* /*
fn keyboard() { fn keyboard() {
use pc_keyboard::{DecodedKey, KeyCode}; use pc_keyboard::{DecodedKey, KeyCode};
@ -285,7 +281,11 @@ pub(super) fn init() {
.ok(); .ok();
// im.register_handler(Keyboard + IRQ_MIN_ID, Box::new(keyboard)); // im.register_handler(Keyboard + IRQ_MIN_ID, Box::new(keyboard));
// im.register_handler(Mouse + IRQ_MIN_ID, Box::new(mouse)); // 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(); im.register_handler(57u32, Box::new(irq57test)).ok();
// register_handler(Keyboard, Keyboard + IRQ_MIN_ID); // register_handler(Keyboard, Keyboard + IRQ_MIN_ID);
// register_handler(Mouse, Mouse + IRQ_MIN_ID); // register_handler(Mouse, Mouse + IRQ_MIN_ID);

View File

@ -4,7 +4,7 @@ use core::time::Duration;
use naive_timer::Timer; use naive_timer::Timer;
use spin::Mutex; use spin::Mutex;
lazy_static::lazy_static! { lazy_static! {
pub static ref NAIVE_TIMER: Mutex<Timer> = Mutex::new(Timer::default()); pub static ref NAIVE_TIMER: Mutex<Timer> = Mutex::new(Timer::default());
} }

View File

@ -1,17 +1,11 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use core::time::Duration; use core::time::Duration;
use core::{future::Future, pin::Pin};
/// Yields execution back to the async runtime.
pub fn yield_now() -> impl Future<Output = ()> {
YieldFuture::default()
}
#[must_use = "yield_now does nothing unless polled/`await`-ed"] #[must_use = "yield_now does nothing unless polled/`await`-ed"]
#[derive(Default)] #[derive(Default)]
struct YieldFuture { pub(super) struct YieldFuture {
flag: bool, flag: bool,
} }
@ -29,14 +23,15 @@ impl Future for YieldFuture {
} }
} }
/// Sleeps until the specified of time. #[must_use = "sleep does nothing unless polled/`await`-ed"]
pub fn sleep_until(deadline: Duration) -> impl Future { pub(super) struct SleepFuture {
SleepFuture { deadline } deadline: Duration,
} }
#[must_use = "sleep does nothing unless polled/`await`-ed"] impl SleepFuture {
pub struct SleepFuture { pub fn new(deadline: Duration) -> Self {
deadline: Duration, Self { deadline }
}
} }
impl Future for SleepFuture { impl Future for SleepFuture {
@ -54,29 +49,37 @@ impl Future for SleepFuture {
} }
} }
/// Get a char from serial. #[must_use = "serial_getchar does nothing unless polled/`await`-ed"]
pub fn serial_getchar() -> impl Future<Output = u8> { pub(super) struct SerialFuture<'a> {
SerialFuture buf: &'a mut [u8],
} }
#[must_use = "serial_getchar does nothing unless polled/`await`-ed"] impl<'a> SerialFuture<'a> {
pub struct SerialFuture; pub fn new(buf: &'a mut [u8]) -> Self {
Self { buf }
}
}
impl Future for SerialFuture { impl Future for SerialFuture<'_> {
type Output = u8; type Output = usize;
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let mut buf = [0u8]; use crate::drivers::UART;
if crate::serial::serial_read(&mut buf) != 0 { let buf = &mut self.get_mut().buf;
return Poll::Ready(buf[0]); 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(); let waker = cx.waker().clone();
crate::serial::serial_set_callback(Box::new({ UART.subscribe(Box::new(move |_| waker.wake_by_ref()), true);
move || {
waker.wake_by_ref();
true
}
}));
Poll::Pending Poll::Pending
} }
} }

View File

@ -72,7 +72,7 @@ impl Drop for PhysFrame {
} }
} }
lazy_static::lazy_static! { lazy_static! {
/// The global physical frame contains all zeros. /// The global physical frame contains all zeros.
pub static ref ZERO_FRAME: PhysFrame = PhysFrame::new_zero().expect("failed to alloc zero frame"); pub static ref ZERO_FRAME: PhysFrame = PhysFrame::new_zero().expect("failed to alloc zero frame");
} }

View File

@ -1,12 +1,14 @@
mod future;
pub(super) mod defs; pub(super) mod defs;
pub(super) mod fb; pub(super) mod fb;
pub mod addr; pub mod addr;
pub mod context; pub mod context;
pub mod drivers; pub mod drivers;
pub mod future;
pub mod mem; pub mod mem;
pub mod serial; pub mod serial;
pub mod thread;
pub mod user; pub mod user;
pub mod vdso; pub mod vdso;
pub mod vm; pub mod vm;

View File

@ -1,16 +1,7 @@
use alloc::{boxed::Box, collections::VecDeque, vec::Vec};
use core::fmt::{Arguments, Result, Write}; use core::fmt::{Arguments, Result, Write};
use spin::Mutex;
use crate::drivers::UART; use crate::drivers::UART;
lazy_static::lazy_static! {
static ref STDIN: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> bool + Send + Sync>>> =
Mutex::new(Vec::new());
}
struct SerialWriter; struct SerialWriter;
impl Write for 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<dyn Fn() -> 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. /// Print format string and its arguments to serial.
pub fn serial_write_fmt(fmt: Arguments) { pub fn serial_write_fmt(fmt: Arguments) {
SerialWriter.write_fmt(fmt).unwrap(); SerialWriter.write_fmt(fmt).unwrap();
@ -56,3 +22,8 @@ pub fn serial_write_fmt(fmt: Arguments) {
pub fn serial_write(s: &str) { pub fn serial_write(s: &str) {
serial_write_fmt(format_args!("{}", s)); 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
}

View File

@ -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
}

View File

@ -33,12 +33,12 @@ hal_fn_def! {
} }
pub mod vm: common::vm { 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`. /// Activate this page table by given `vmtoken`.
pub(crate) fn activate_paging(vmtoken: PhysAddr); 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`). /// Flush TLB by the associated `vaddr`, or flush the entire TLB. (`vaddr` is `None`).
pub(crate) fn flush_tlb(vaddr: Option<VirtAddr>); pub(crate) fn flush_tlb(vaddr: Option<VirtAddr>);
@ -103,7 +103,7 @@ hal_fn_def! {
pub fn fetch_page_fault_info(info_reg: usize) -> (VirtAddr, MMUFlags); pub fn fetch_page_fault_info(info_reg: usize) -> (VirtAddr, MMUFlags);
} }
pub mod thread { pub mod thread: common::thread {
/// Spawn a new thread. /// Spawn a new thread.
pub fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, vmtoken: usize); pub fn spawn(future: Pin<Box<dyn Future<Output = ()> + Send + 'static>>, vmtoken: usize);

View File

@ -5,12 +5,12 @@
#![deny(warnings)] #![deny(warnings)]
extern crate alloc; extern crate alloc;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
#[macro_use] #[macro_use]
extern crate cfg_if; extern crate cfg_if;
#[macro_use]
extern crate lazy_static;
#[macro_use] #[macro_use]
mod macros; 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 config::*;
pub use imp::*; pub use imp::*;
pub use kernel_handler::*; pub use kernel_handler::*;

View File

@ -20,7 +20,7 @@ struct InputEvent {
value: i32, value: i32,
} }
lazy_static::lazy_static! { lazy_static! {
static ref MOUSE_CALLBACK: Mutex<Vec<Box<MouseCallbackFn>>> = Mutex::new(Vec::new()); static ref MOUSE_CALLBACK: Mutex<Vec<Box<MouseCallbackFn>>> = Mutex::new(Vec::new());
static ref KBD_CALLBACK: Mutex<Vec<Box<KBDCallbackFn>>> = Mutex::new(Vec::new()); static ref KBD_CALLBACK: Mutex<Vec<Box<KBDCallbackFn>>> = Mutex::new(Vec::new());
} }

View File

@ -1,9 +1,11 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use zcore_drivers::mock::MockUart; use zcore_drivers::mock::MockUart;
use zcore_drivers::scheme::EventListener;
use crate::drivers::UART; use crate::drivers::UART;
pub(super) fn init() { 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));
} }

View File

@ -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_BASE: VirtAddr = 0x8_0000_0000;
pub(super) const PMEM_SIZE: usize = 0x4000_0000; // 1GiB 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 FRAME_FILE: File = create_pmem_file();
pub(super) static ref AVAILABLE_FRAMES: Mutex<VecDeque<usize>> = pub(super) static ref AVAILABLE_FRAMES: Mutex<VecDeque<usize>> =
Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect()); Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect());

View File

@ -38,10 +38,4 @@ pub fn init() {
unsafe { unsafe {
register_sigsegv_handler(); register_sigsegv_handler();
} }
// spawn a thread to read stdin
// TODO: raw mode
std::thread::spawn(|| loop {
crate::serial::handle_irq();
core::hint::spin_loop();
});
} }

View File

@ -56,8 +56,7 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
let path = args[0].clone(); let path = args[0].clone();
debug!("Linux process: {:?}", path); debug!("Linux process: {:?}", path);
use kernel_hal::vm::{GenericPageTable, PageTable}; let pg_token = kernel_hal::vm::current_vmtoken();
let pg_token = PageTable::from_current().table_phys();
debug!("current pgt = {:#x}", pg_token); debug!("current pgt = {:#x}", pg_token);
//调用zircon-object/src/task/thread.start设置好要执行的thread //调用zircon-object/src/task/thread.start设置好要执行的thread
let (entry, sp) = loader.load(&proc.vmar(), &data, args, envs, path).unwrap(); let (entry, sp) = loader.load(&proc.vmar(), &data, args, envs, path).unwrap();
@ -96,7 +95,7 @@ async fn new_thread(thread: CurrentThread) {
0x20..=0x3f => { 0x20..=0x3f => {
kernel_hal::interrupt::handle_irq(cx.trap_num as u32); kernel_hal::interrupt::handle_irq(cx.trap_num as u32);
if cx.trap_num == 0x20 { if cx.trap_num == 0x20 {
kernel_hal::future::yield_now().await; kernel_hal::thread::yield_now().await;
} }
} }
0xe => { 0xe => {
@ -133,7 +132,7 @@ async fn new_thread(thread: CurrentThread) {
if trap_num == 4 || trap_num == 5 { if trap_num == 4 || trap_num == 5 {
debug!("Timer interrupt: {}", trap_num); 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); //kernel_hal::interrupt::handle_irq(trap_num as u32);

View File

@ -21,16 +21,18 @@ async fn main() {
kernel_hal::dev::fb::init(); kernel_hal::dev::fb::init();
kernel_hal::dev::input::init(); kernel_hal::dev::input::init();
} }
kernel_hal::serial::serial_set_callback(Box::new({
move || { use kernel_hal::drivers::UART;
let mut buffer = [0; 255]; UART.subscribe(
let len = kernel_hal::serial::serial_read(&mut buffer); Box::new(|_| {
for c in &buffer[..len] { while let Some(c) = UART.try_recv().unwrap() {
STDIN.push((*c).into()); let c = if c == b'\r' { b'\n' } else { c };
STDIN.push(c as char);
} }
false }),
} false,
})); );
// run first process // run first process
let args: Vec<_> = std::env::args().skip(1).collect(); 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()]; let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/x86_64-alpine-linux-musl/bin".into()];

View File

@ -297,7 +297,7 @@ impl Syscall<'_> {
pub async fn sys_nanosleep(&self, req: UserInPtr<TimeSpec>) -> SysResult { pub async fn sys_nanosleep(&self, req: UserInPtr<TimeSpec>) -> SysResult {
info!("nanosleep: deadline={:?}", req); info!("nanosleep: deadline={:?}", req);
let req = req.read()?; let req = req.read()?;
kernel_hal::future::sleep_until(req.into()).await; kernel_hal::thread::sleep_until(req.into()).await;
Ok(0) Ok(0)
} }

View File

@ -167,19 +167,18 @@ fn get_rootproc(cmdline: &str) -> Vec<String> {
#[cfg(feature = "linux")] #[cfg(feature = "linux")]
fn main(ramfs_data: &'static mut [u8], cmdline: &str) -> ! { fn main(ramfs_data: &'static mut [u8], cmdline: &str) -> ! {
use kernel_hal::drivers::UART;
use linux_object::fs::STDIN; use linux_object::fs::STDIN;
kernel_hal::serial::serial_set_callback(Box::new({ UART.subscribe(
move || { Box::new(|_| {
let mut buffer = [0; 255]; while let Some(c) = UART.try_recv().unwrap() {
let len = kernel_hal::serial::serial_read(&mut buffer); let c = if c == b'\r' { b'\n' } else { c };
for c in &buffer[..len] { STDIN.push(c as char);
STDIN.push((*c).into());
// kernel_hal::serial::serial_write(alloc::format!("{}", *c as char).as_str());
} }
false }),
} false,
})); );
//let args: Vec<String> = vec!["/bin/busybox".into(), "sh".into()]; //let args: Vec<String> = vec!["/bin/busybox".into(), "sh".into()];
let args: Vec<String> = get_rootproc(cmdline); let args: Vec<String> = get_rootproc(cmdline);
@ -234,6 +233,9 @@ impl KernelHandler for ZcoreKernelHandler {
} }
fn handle_page_fault(&self, fault_vaddr: usize, access_flags: MMUFlags) { 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
);
} }
} }

View File

@ -220,7 +220,7 @@ async fn new_thread(thread: CurrentThread) {
kernel_hal::interrupt::handle_irq(trap_num as u32); kernel_hal::interrupt::handle_irq(trap_num as u32);
if trap_num == 0x20 { if trap_num == 0x20 {
EXCEPTIONS_TIMER.add(1); EXCEPTIONS_TIMER.add(1);
kernel_hal::future::yield_now().await; kernel_hal::thread::yield_now().await;
} }
} }
0xe => { 0xe => {

View File

@ -15,7 +15,6 @@ use {
}, },
futures::{channel::oneshot::*, future::FutureExt, pin_mut, select_biased}, futures::{channel::oneshot::*, future::FutureExt, pin_mut, select_biased},
kernel_hal::context::{GeneralRegs, UserContext}, kernel_hal::context::{GeneralRegs, UserContext},
// kernel_hal::future::sleep_until,
spin::Mutex, spin::Mutex,
}; };
@ -603,14 +602,14 @@ impl CurrentThread {
select_biased! { select_biased! {
ret = future.fuse() => ret.into_result(), ret = future.fuse() => ret.into_result(),
_ = killed.fuse() => Err(ZxError::STOP), _ = 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), _ = cancel_token.fuse() => Err(ZxError::CANCELED),
} }
} else { } else {
select_biased! { select_biased! {
ret = future.fuse() => ret.into_result(), ret = future.fuse() => ret.into_result(),
_ = killed.fuse() => Err(ZxError::STOP), _ = 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(); let mut inner = self.inner.lock();

View File

@ -25,15 +25,10 @@ impl Syscall<'_> {
let proc = self.thread.proc(); let proc = self.thread.proc();
proc.get_object::<Resource>(handle)? proc.get_object::<Resource>(handle)?
.validate(ResourceKind::ROOT)?; .validate(ResourceKind::ROOT)?;
// FIXME: To make 'console' work, now debug_read is a blocking call. let mut vec = vec![0u8; buf_size as usize];
// But it should be non-blocking. let len = kernel_hal::serial::serial_read(&mut vec).await;
// let mut vec = vec![0u8; buf_size as usize]; buf.write_array(&vec[..len])?;
// let len = kernel_hal::serial_read(&mut vec); actual.write(len as u32)?;
// 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)?;
Ok(()) Ok(())
} }
} }

View File

@ -94,11 +94,13 @@ impl Syscall<'_> {
pub async fn sys_nanosleep(&self, deadline: Deadline) -> ZxResult { pub async fn sys_nanosleep(&self, deadline: Deadline) -> ZxResult {
info!("nanosleep: deadline={:?}", deadline); info!("nanosleep: deadline={:?}", deadline);
if deadline.0 <= 0 { if deadline.0 <= 0 {
kernel_hal::future::yield_now().await; kernel_hal::thread::yield_now().await;
} else { } else {
let future = kernel_hal::thread::sleep_until(deadline.into());
pin_mut!(future);
self.thread self.thread
.blocking_run( .blocking_run(
kernel_hal::future::sleep_until(deadline.into()), future,
ThreadState::BlockedSleeping, ThreadState::BlockedSleeping,
Deadline::forever().into(), Deadline::forever().into(),
None, None,