forked from rcore-os/zCore
drivers: implement EventListener
This commit is contained in:
parent
994f8b80f2
commit
022d7f0e96
|
@ -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 }
|
||||
|
|
|
@ -29,4 +29,4 @@ pub enum 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>;
|
||||
|
|
|
@ -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<Receiver<u8>>,
|
||||
const UART_BUF_LEN: usize = 256;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref UART_BUF: Mutex<VecDeque<u8>> = 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<Option<u8>> {
|
||||
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();
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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')?;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<Option<u8>> {
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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::<u8>::new(phys_to_virt(super::consts::UART_BASE))
|
||||
}));
|
||||
})));
|
||||
}
|
||||
|
|
|
@ -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<IrqManager> = Mutex::new(IrqManager::new(1, 15));
|
||||
}
|
||||
|
||||
|
|
|
@ -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")]
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -13,7 +13,7 @@ pub struct AcpiTable {
|
|||
inner: Acpi,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
lazy_static! {
|
||||
static ref ACPI_TABLE: Mutex<Option<AcpiTable>> = Mutex::default();
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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))));
|
||||
}
|
||||
|
|
|
@ -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<IrqManager> = Mutex::new(IrqManager::new(0x20, 0xff));
|
||||
static ref MAX_INSTR_TABLE: Mutex<Vec<(usize, u8)>> = 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);
|
||||
|
|
|
@ -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<Timer> = Mutex::new(Timer::default());
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Output = ()> {
|
||||
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<Output = u8> {
|
||||
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<Self::Output> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<VecDeque<u8>> = Mutex::new(VecDeque::new());
|
||||
static ref STDIN_CALLBACK: Mutex<Vec<Box<dyn Fn() -> 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<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.
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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<VirtAddr>);
|
||||
|
||||
|
@ -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<Box<dyn Future<Output = ()> + Send + 'static>>, vmtoken: usize);
|
||||
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -20,7 +20,7 @@ struct InputEvent {
|
|||
value: i32,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
lazy_static! {
|
||||
static ref MOUSE_CALLBACK: Mutex<Vec<Box<MouseCallbackFn>>> = Mutex::new(Vec::new());
|
||||
static ref KBD_CALLBACK: Mutex<Vec<Box<KBDCallbackFn>>> = Mutex::new(Vec::new());
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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<VecDeque<usize>> =
|
||||
Mutex::new((PAGE_SIZE..PMEM_SIZE).step_by(PAGE_SIZE).collect());
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -56,8 +56,7 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
|
|||
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);
|
||||
|
|
|
@ -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()];
|
||||
|
|
|
@ -297,7 +297,7 @@ impl Syscall<'_> {
|
|||
pub async fn sys_nanosleep(&self, req: UserInPtr<TimeSpec>) -> 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)
|
||||
}
|
||||
|
||||
|
|
|
@ -167,19 +167,18 @@ fn get_rootproc(cmdline: &str) -> Vec<String> {
|
|||
|
||||
#[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<String> = vec!["/bin/busybox".into(), "sh".into()];
|
||||
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) {
|
||||
panic!("page fault from kernel mode @ {:#x}({:?})", fault_vaddr, access_flags);
|
||||
panic!(
|
||||
"page fault from kernel mode @ {:#x}({:?})",
|
||||
fault_vaddr, access_flags
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -25,15 +25,10 @@ impl Syscall<'_> {
|
|||
let proc = self.thread.proc();
|
||||
proc.get_object::<Resource>(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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue