diff --git a/.gitignore b/.gitignore index 53ab248df..88bb38b0b 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ cppcheck.xml .cache compile_commands.json /logs/ +*.log diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 78e8244a4..60f663a74 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -57,7 +57,7 @@ system_error = { path = "crates/system_error" } uefi = { version = "=0.26.0", features = ["alloc"] } uefi-raw = "=0.5.0" unified-init = { path = "crates/unified-init" } -virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers", rev = "f91c807965" } +virtio-drivers = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/virtio-drivers", rev = "415ab38ff9" } wait_queue_macros = { path = "crates/wait_queue_macros" } paste = "=1.0.14" slabmalloc = { path = "crates/rust-slabmalloc" } diff --git a/kernel/crates/bitmap/src/bitmap_core.rs b/kernel/crates/bitmap/src/bitmap_core.rs index 384e32776..7ed57a411 100644 --- a/kernel/crates/bitmap/src/bitmap_core.rs +++ b/kernel/crates/bitmap/src/bitmap_core.rs @@ -7,6 +7,12 @@ pub struct BitMapCore { phantom: PhantomData, } +impl Default for BitMapCore { + fn default() -> Self { + Self::new() + } +} + impl BitMapCore { pub const fn new() -> Self { Self { diff --git a/kernel/crates/bitmap/src/lib.rs b/kernel/crates/bitmap/src/lib.rs index 27436bd86..fac2bff42 100644 --- a/kernel/crates/bitmap/src/lib.rs +++ b/kernel/crates/bitmap/src/lib.rs @@ -2,6 +2,7 @@ #![feature(core_intrinsics)] #![allow(incomplete_features)] // for const generics #![feature(generic_const_exprs)] +#![deny(clippy::all)] #![allow(internal_features)] #![allow(clippy::needless_return)] diff --git a/kernel/crates/rust-slabmalloc/src/lib.rs b/kernel/crates/rust-slabmalloc/src/lib.rs index c1c84cf8b..bde595e36 100644 --- a/kernel/crates/rust-slabmalloc/src/lib.rs +++ b/kernel/crates/rust-slabmalloc/src/lib.rs @@ -23,7 +23,8 @@ #![crate_name = "slabmalloc"] #![crate_type = "lib"] #![feature(maybe_uninit_as_bytes)] - +#![deny(clippy::all)] +#![allow(clippy::needless_return)] extern crate alloc; mod pages; diff --git a/kernel/crates/rust-slabmalloc/src/pages.rs b/kernel/crates/rust-slabmalloc/src/pages.rs index 872d9bf41..67e9ac6da 100644 --- a/kernel/crates/rust-slabmalloc/src/pages.rs +++ b/kernel/crates/rust-slabmalloc/src/pages.rs @@ -33,7 +33,7 @@ impl Bitfield for [AtomicU64] { fn initialize(&mut self, for_size: usize, capacity: usize) { // Set everything to allocated for bitmap in self.iter_mut() { - *bitmap = AtomicU64::new(u64::max_value()); + *bitmap = AtomicU64::new(u64::MAX); } // Mark actual slots as free @@ -56,7 +56,7 @@ impl Bitfield for [AtomicU64] { ) -> Option<(usize, usize)> { for (base_idx, b) in self.iter().enumerate() { let bitval = b.load(Ordering::Relaxed); - if bitval == u64::max_value() { + if bitval == u64::MAX { continue; } else { let negated = !bitval; @@ -117,7 +117,7 @@ impl Bitfield for [AtomicU64] { #[inline(always)] fn is_full(&self) -> bool { self.iter() - .filter(|&x| x.load(Ordering::Relaxed) != u64::max_value()) + .filter(|&x| x.load(Ordering::Relaxed) != u64::MAX) .count() == 0 } @@ -268,10 +268,10 @@ impl<'a> ObjectPage<'a> { } // These needs some more work to be really safe... -unsafe impl<'a> Send for ObjectPage<'a> {} -unsafe impl<'a> Sync for ObjectPage<'a> {} +unsafe impl Send for ObjectPage<'_> {} +unsafe impl Sync for ObjectPage<'_> {} -impl<'a> AllocablePage for ObjectPage<'a> { +impl AllocablePage for ObjectPage<'_> { const SIZE: usize = OBJECT_PAGE_SIZE; fn bitfield(&self) -> &[AtomicU64; 8] { @@ -296,7 +296,7 @@ impl<'a> Default for ObjectPage<'a> { } } -impl<'a> fmt::Debug for ObjectPage<'a> { +impl fmt::Debug for ObjectPage<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ObjectPage") } @@ -401,6 +401,8 @@ impl<'a, T: AllocablePage> PageList<'a, T> { }); self.elements -= 1; + + #[allow(clippy::manual_inspect)] new_head.map(|node| { *node.prev() = Rawlink::none(); *node.next() = Rawlink::none(); @@ -434,6 +436,7 @@ impl<'a, P: AllocablePage + 'a> Iterator for ObjectPageIterMut<'a, P> { #[inline] fn next(&mut self) -> Option<&'a mut P> { unsafe { + #[allow(clippy::manual_inspect)] self.head.resolve_mut().map(|next| { self.head = match next.next().resolve_mut() { None => Rawlink::none(), diff --git a/kernel/crates/rust-slabmalloc/src/sc.rs b/kernel/crates/rust-slabmalloc/src/sc.rs index cdfa98815..0ece66a70 100644 --- a/kernel/crates/rust-slabmalloc/src/sc.rs +++ b/kernel/crates/rust-slabmalloc/src/sc.rs @@ -71,7 +71,7 @@ macro_rules! new_sc_allocator { SCAllocator { size: $size, allocation_count: 0, - obj_per_page: obj_per_page, + obj_per_page, empty_slabs: PageList::new(), slabs: PageList::new(), full_slabs: PageList::new(), diff --git a/kernel/env.mk b/kernel/env.mk index 871f6e7d4..262958817 100644 --- a/kernel/env.mk +++ b/kernel/env.mk @@ -31,4 +31,4 @@ GLOBAL_CFLAGS += -g endif export RUSTFLAGS := -C link-args=-znostart-stop-gc -export RUSTDOCFLAGS := -C link-args=-znostart-stop-gc \ No newline at end of file +export RUSTDOCFLAGS := -C link-args=-znostart-stop-gc diff --git a/kernel/src/driver/base/block/block_device.rs b/kernel/src/driver/base/block/block_device.rs index c02464a0b..4b481b633 100644 --- a/kernel/src/driver/base/block/block_device.rs +++ b/kernel/src/driver/base/block/block_device.rs @@ -3,7 +3,7 @@ use crate::driver::{ base::{ device::{ device_number::{DeviceNumber, Major}, - Device, DeviceError, IdTable, BLOCKDEVS, + DevName, Device, DeviceError, IdTable, BLOCKDEVS, }, map::{ DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, DEV_MAJOR_DYN_EXT_START, @@ -13,8 +13,8 @@ use crate::driver::{ block::cache::{cached_block_device::BlockCache, BlockCacheError, BLOCK_SIZE}, }; -use alloc::{string::String, sync::Arc, vec::Vec}; -use core::{any::Any, fmt::Display, ops::Deref}; +use alloc::{sync::Arc, vec::Vec}; +use core::any::Any; use log::error; use system_error::SystemError; @@ -221,74 +221,11 @@ pub fn __lba_to_bytes(lba_id: usize, blk_size: usize) -> BlockId { return lba_id * blk_size; } -/// 块设备的名字 -pub struct BlockDevName { - name: Arc, - id: usize, -} - -impl BlockDevName { - pub fn new(name: String, id: usize) -> Self { - return BlockDevName { - name: Arc::new(name), - id, - }; - } - - #[inline] - pub fn id(&self) -> usize { - return self.id; - } -} - -impl core::fmt::Debug for BlockDevName { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - return write!(f, "{}", self.name); - } -} - -impl Display for BlockDevName { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - return write!(f, "{}", self.name); - } -} - -impl Clone for BlockDevName { - fn clone(&self) -> Self { - return BlockDevName { - name: self.name.clone(), - id: self.id, - }; - } -} - -impl core::hash::Hash for BlockDevName { - fn hash(&self, state: &mut H) { - self.name.hash(state); - } -} - -impl Deref for BlockDevName { - type Target = String; - - fn deref(&self) -> &Self::Target { - return self.name.as_ref(); - } -} - -impl PartialEq for BlockDevName { - fn eq(&self, other: &Self) -> bool { - return self.name == other.name; - } -} - -impl Eq for BlockDevName {} - /// @brief 块设备应该实现的操作 pub trait BlockDevice: Device { /// # dev_name /// 返回块设备的名字 - fn dev_name(&self) -> &BlockDevName; + fn dev_name(&self) -> &DevName; fn blkdev_meta(&self) -> &BlockDevMeta; diff --git a/kernel/src/driver/base/block/manager.rs b/kernel/src/driver/base/block/manager.rs index 7fe6c2919..0c901178c 100644 --- a/kernel/src/driver/base/block/manager.rs +++ b/kernel/src/driver/base/block/manager.rs @@ -6,14 +6,14 @@ use system_error::SystemError; use unified_init::macros::unified_init; use crate::{ - driver::base::block::gendisk::GenDisk, + driver::base::{block::gendisk::GenDisk, device::DevName}, filesystem::mbr::MbrDiskPartionTable, init::initcall::INITCALL_POSTCORE, libs::spinlock::{SpinLock, SpinLockGuard}, }; use super::{ - block_device::{BlockDevName, BlockDevice, GeneralBlockRange}, + block_device::{BlockDevice, GeneralBlockRange}, gendisk::GenDiskMap, }; @@ -38,7 +38,7 @@ pub struct BlockDevManager { } struct InnerBlockDevManager { - disks: HashMap>, + disks: HashMap>, } impl BlockDevManager { pub fn new() -> Self { @@ -207,7 +207,7 @@ impl BlockDevManager { } pub struct BlockDevMeta { - pub devname: BlockDevName, + pub devname: DevName, inner: SpinLock, } @@ -216,7 +216,7 @@ pub struct InnerBlockDevMeta { } impl BlockDevMeta { - pub fn new(devname: BlockDevName) -> Self { + pub fn new(devname: DevName) -> Self { BlockDevMeta { devname, inner: SpinLock::new(InnerBlockDevMeta { diff --git a/kernel/src/driver/base/device/device_number.rs b/kernel/src/driver/base/device/device_number.rs index 41c19f58c..78c4c3191 100644 --- a/kernel/src/driver/base/device/device_number.rs +++ b/kernel/src/driver/base/device/device_number.rs @@ -24,6 +24,8 @@ impl Major { pub const UNIX98_PTY_SLAVE_MAJOR: Self = Self::new(Self::UNIX98_PTY_MASTER_MAJOR.0 + Self::UNIX98_PTY_MAJOR_COUNT.0); + pub const HVC_MAJOR: Self = Self::new(229); + pub const fn new(x: u32) -> Self { Major(x) } diff --git a/kernel/src/driver/base/device/mod.rs b/kernel/src/driver/base/device/mod.rs index bf42935ea..18199ce03 100644 --- a/kernel/src/driver/base/device/mod.rs +++ b/kernel/src/driver/base/device/mod.rs @@ -26,8 +26,8 @@ use crate::{ }, }; -use core::intrinsics::unlikely; use core::{any::Any, fmt::Debug}; +use core::{fmt::Display, intrinsics::unlikely, ops::Deref}; use system_error::SystemError; use self::{ @@ -124,6 +124,69 @@ unsafe fn set_sys_devices_virtual_kset(kset: Arc) { DEVICES_VIRTUAL_KSET_INSTANCE = Some(kset); } +/// /dev下面的设备的名字 +pub struct DevName { + name: Arc, + id: usize, +} + +impl DevName { + pub fn new(name: String, id: usize) -> Self { + return DevName { + name: Arc::new(name), + id, + }; + } + + #[inline] + pub fn id(&self) -> usize { + return self.id; + } +} + +impl core::fmt::Debug for DevName { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + return write!(f, "{}", self.name); + } +} + +impl Display for DevName { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + return write!(f, "{}", self.name); + } +} + +impl Clone for DevName { + fn clone(&self) -> Self { + return DevName { + name: self.name.clone(), + id: self.id, + }; + } +} + +impl core::hash::Hash for DevName { + fn hash(&self, state: &mut H) { + self.name.hash(state); + } +} + +impl Deref for DevName { + type Target = String; + + fn deref(&self) -> &Self::Target { + return self.name.as_ref(); + } +} + +impl PartialEq for DevName { + fn eq(&self, other: &Self) -> bool { + return self.name == other.name; + } +} + +impl Eq for DevName {} + /// 设备应该实现的操作 /// /// ## 注意 diff --git a/kernel/src/driver/block/virtio_blk.rs b/kernel/src/driver/block/virtio_blk.rs index ce8ac62c1..133ee11d6 100644 --- a/kernel/src/driver/block/virtio_blk.rs +++ b/kernel/src/driver/block/virtio_blk.rs @@ -1,7 +1,6 @@ use core::{any::Any, fmt::Debug}; use alloc::{ - collections::LinkedList, string::{String, ToString}, sync::{Arc, Weak}, vec::Vec, @@ -16,7 +15,7 @@ use crate::{ driver::{ base::{ block::{ - block_device::{BlockDevName, BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE}, + block_device::{BlockDevice, BlockId, GeneralBlockRange, LBA_SIZE}, disk_info::Partition, manager::{block_dev_manager, BlockDevMeta}, }, @@ -24,7 +23,7 @@ use crate::{ device::{ bus::Bus, driver::{Driver, DriverCommonData}, - Device, DeviceCommonData, DeviceId, DeviceType, IdTable, + DevName, Device, DeviceCommonData, DeviceId, DeviceType, IdTable, }, kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, kset::KSet, @@ -103,7 +102,7 @@ pub struct VirtIOBlkManager { struct InnerVirtIOBlkManager { id_bmp: bitmap::StaticBitmap<{ VirtIOBlkManager::MAX_DEVICES }>, - devname: [Option; VirtIOBlkManager::MAX_DEVICES], + devname: [Option; VirtIOBlkManager::MAX_DEVICES], } impl VirtIOBlkManager { @@ -122,7 +121,7 @@ impl VirtIOBlkManager { self.inner.lock() } - pub fn alloc_id(&self) -> Option { + pub fn alloc_id(&self) -> Option { let mut inner = self.inner(); let idx = inner.id_bmp.first_false_index()?; inner.id_bmp.set(idx, true); @@ -132,9 +131,9 @@ impl VirtIOBlkManager { } /// Generate a new block device name like 'vda', 'vdb', etc. - fn format_name(id: usize) -> BlockDevName { + fn format_name(id: usize) -> DevName { let x = (b'a' + id as u8) as char; - BlockDevName::new(format!("vd{}", x), id) + DevName::new(format!("vd{}", x), id) } #[allow(dead_code)] @@ -204,7 +203,7 @@ impl VirtIOBlkDevice { } impl BlockDevice for VirtIOBlkDevice { - fn dev_name(&self) -> &BlockDevName { + fn dev_name(&self) -> &DevName { &self.blkdev_meta.devname } @@ -349,7 +348,7 @@ impl VirtIODevice for VirtIOBlkDevice { impl Device for VirtIOBlkDevice { fn dev_type(&self) -> DeviceType { - DeviceType::Net + DeviceType::Block } fn id_table(&self) -> IdTable { @@ -479,7 +478,7 @@ fn virtio_blk_driver_init() -> Result<(), SystemError> { let driver = VirtIOBlkDriver::new(); virtio_driver_manager() .register(driver.clone() as Arc) - .expect("Add virtio net driver failed"); + .expect("Add virtio blk driver failed"); unsafe { VIRTIO_BLK_DRIVER = Some(driver); } @@ -546,12 +545,12 @@ impl VirtIODriver for VirtIOBlkDriver { return Ok(()); } - fn virtio_id_table(&self) -> LinkedList { + fn virtio_id_table(&self) -> Vec { self.inner().virtio_driver_common.id_table.clone() } fn add_virtio_id(&self, id: VirtioDeviceId) { - self.inner().virtio_driver_common.id_table.push_back(id); + self.inner().virtio_driver_common.id_table.push(id); } } diff --git a/kernel/src/driver/char/mod.rs b/kernel/src/driver/char/mod.rs new file mode 100644 index 000000000..35d092218 --- /dev/null +++ b/kernel/src/driver/char/mod.rs @@ -0,0 +1 @@ +pub mod virtio_console; diff --git a/kernel/src/driver/char/virtio_console.rs b/kernel/src/driver/char/virtio_console.rs new file mode 100644 index 000000000..463622888 --- /dev/null +++ b/kernel/src/driver/char/virtio_console.rs @@ -0,0 +1,736 @@ +use crate::{ + driver::{ + base::{ + class::Class, + device::{ + bus::Bus, + device_number::Major, + driver::{Driver, DriverCommonData}, + DevName, Device, DeviceCommonData, DeviceId, DeviceType, IdTable, + }, + kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, + kset::KSet, + }, + tty::{ + console::ConsoleSwitch, + kthread::send_to_tty_refresh_thread, + termios::{WindowSize, TTY_STD_TERMIOS}, + tty_core::{TtyCore, TtyCoreData}, + tty_driver::{TtyDriver, TtyDriverManager, TtyDriverType, TtyOperation}, + virtual_terminal::{vc_manager, virtual_console::VirtualConsoleData, VirtConsole}, + }, + video::console::dummycon::dummy_console, + virtio::{ + sysfs::{virtio_bus, virtio_device_manager, virtio_driver_manager}, + transport::VirtIOTransport, + virtio_drivers_error_to_system_error, + virtio_impl::HalImpl, + VirtIODevice, VirtIODeviceIndex, VirtIODriver, VirtIODriverCommonData, VirtioDeviceId, + VIRTIO_VENDOR_ID, + }, + }, + exception::{irqdesc::IrqReturn, IrqNumber}, + filesystem::kernfs::KernFSInode, + init::initcall::INITCALL_POSTCORE, + libs::{ + lazy_init::Lazy, + rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, + spinlock::{SpinLock, SpinLockGuard}, + }, +}; +use alloc::string::String; +use alloc::string::ToString; +use alloc::sync::{Arc, Weak}; +use alloc::vec::Vec; +use bitmap::traits::BitMapOps; +use core::fmt::Debug; +use core::fmt::Formatter; +use core::{ + any::Any, + sync::atomic::{compiler_fence, Ordering}, +}; +use system_error::SystemError; +use unified_init::macros::unified_init; +use virtio_drivers::device::console::VirtIOConsole; + +const VIRTIO_CONSOLE_BASENAME: &str = "virtio_console"; +const HVC_MINOR: u32 = 0; + +static mut VIRTIO_CONSOLE_DRIVER: Option> = None; +static mut TTY_HVC_DRIVER: Option> = None; + +#[inline(always)] +fn tty_hvc_driver() -> &'static Arc { + unsafe { TTY_HVC_DRIVER.as_ref().unwrap() } +} + +pub fn virtio_console( + transport: VirtIOTransport, + dev_id: Arc, + dev_parent: Option>, +) { + log::debug!( + "virtio_console: dev_id: {:?}, parent: {:?}", + dev_id, + dev_parent + ); + let device = VirtIOConsoleDevice::new(transport, dev_id.clone()); + if device.is_none() { + return; + } + + let device = device.unwrap(); + + if let Some(dev_parent) = dev_parent { + device.set_dev_parent(Some(Arc::downgrade(&dev_parent))); + } + virtio_device_manager() + .device_add(device.clone() as Arc) + .expect("Add virtio console failed"); +} + +// +#[derive(Debug)] +#[cast_to([sync] VirtIODevice)] +#[cast_to([sync] Device)] +pub struct VirtIOConsoleDevice { + dev_name: Lazy, + dev_id: Arc, + _self_ref: Weak, + locked_kobj_state: LockedKObjectState, + inner: SpinLock, +} +unsafe impl Send for VirtIOConsoleDevice {} +unsafe impl Sync for VirtIOConsoleDevice {} + +impl VirtIOConsoleDevice { + pub fn new(transport: VirtIOTransport, dev_id: Arc) -> Option> { + // 设置中断 + if let Err(err) = transport.setup_irq(dev_id.clone()) { + log::error!( + "VirtIOConsoleDevice '{dev_id:?}' setup_irq failed: {:?}", + err + ); + return None; + } + + let irq = Some(transport.irq()); + let device_inner = VirtIOConsole::::new(transport); + if let Err(e) = device_inner { + log::error!("VirtIOConsoleDevice '{dev_id:?}' create failed: {:?}", e); + return None; + } + + let mut device_inner: VirtIOConsole = device_inner.unwrap(); + device_inner.enable_interrupts(); + + let dev = Arc::new_cyclic(|self_ref| Self { + dev_id, + dev_name: Lazy::new(), + _self_ref: self_ref.clone(), + locked_kobj_state: LockedKObjectState::default(), + inner: SpinLock::new(InnerVirtIOConsoleDevice { + device_inner, + name: None, + virtio_index: None, + device_common: DeviceCommonData::default(), + kobject_common: KObjectCommonData::default(), + irq, + }), + }); + + Some(dev) + } + + fn inner(&self) -> SpinLockGuard { + self.inner.lock_irqsave() + } +} + +struct InnerVirtIOConsoleDevice { + device_inner: VirtIOConsole, + virtio_index: Option, + name: Option, + device_common: DeviceCommonData, + kobject_common: KObjectCommonData, + irq: Option, +} + +impl Debug for InnerVirtIOConsoleDevice { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + f.debug_struct("InnerVirtIOConsoleDevice") + .field("virtio_index", &self.virtio_index) + .field("name", &self.name) + .field("device_common", &self.device_common) + .field("kobject_common", &self.kobject_common) + .field("irq", &self.irq) + .finish() + } +} + +impl KObject for VirtIOConsoleDevice { + fn as_any_ref(&self) -> &dyn Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner().kobject_common.kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner().kobject_common.kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner().kobject_common.parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner().kobject_common.parent = parent; + } + + fn kset(&self) -> Option> { + self.inner().kobject_common.kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner().kobject_common.kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner().kobject_common.kobj_type + } + + fn name(&self) -> String { + self.device_name() + } + + fn set_name(&self, _name: String) { + // do nothing + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.locked_kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.locked_kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.locked_kobj_state.write() = state; + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner().kobject_common.kobj_type = ktype; + } +} + +impl Device for VirtIOConsoleDevice { + fn dev_type(&self) -> DeviceType { + DeviceType::Char + } + + fn id_table(&self) -> IdTable { + IdTable::new(VIRTIO_CONSOLE_BASENAME.to_string(), None) + } + + fn bus(&self) -> Option> { + self.inner().device_common.bus.clone() + } + + fn set_bus(&self, bus: Option>) { + self.inner().device_common.bus = bus; + } + + fn class(&self) -> Option> { + let mut guard = self.inner(); + let r = guard.device_common.class.clone()?.upgrade(); + if r.is_none() { + guard.device_common.class = None; + } + + return r; + } + + fn set_class(&self, class: Option>) { + self.inner().device_common.class = class; + } + + fn driver(&self) -> Option> { + let r = self.inner().device_common.driver.clone()?.upgrade(); + if r.is_none() { + self.inner().device_common.driver = None; + } + + return r; + } + + fn set_driver(&self, driver: Option>) { + self.inner().device_common.driver = driver; + } + + fn is_dead(&self) -> bool { + false + } + + fn can_match(&self) -> bool { + self.inner().device_common.can_match + } + + fn set_can_match(&self, can_match: bool) { + self.inner().device_common.can_match = can_match; + } + + fn state_synced(&self) -> bool { + true + } + + fn dev_parent(&self) -> Option> { + self.inner().device_common.get_parent_weak_or_clear() + } + + fn set_dev_parent(&self, parent: Option>) { + self.inner().device_common.parent = parent; + } +} + +impl VirtIODevice for VirtIOConsoleDevice { + fn handle_irq(&self, _irq: IrqNumber) -> Result { + let mut buf = [0u8; 8]; + let mut index = 0; + // Read up to the size of the buffer + while index < buf.len() { + if let Ok(Some(c)) = self.inner().device_inner.recv(true) { + buf[index] = c; + index += 1; + } else { + break; // No more bytes to read + } + } + + send_to_tty_refresh_thread(&buf[0..index]); + Ok(IrqReturn::Handled) + } + + fn dev_id(&self) -> &Arc { + &self.dev_id + } + + fn set_device_name(&self, name: String) { + self.inner().name = Some(name); + } + + fn device_name(&self) -> String { + self.inner() + .name + .clone() + .unwrap_or_else(|| VIRTIO_CONSOLE_BASENAME.to_string()) + } + + fn set_virtio_device_index(&self, index: VirtIODeviceIndex) { + self.inner().virtio_index = Some(index); + } + + fn virtio_device_index(&self) -> Option { + self.inner().virtio_index + } + + fn device_type_id(&self) -> u32 { + virtio_drivers::transport::DeviceType::Console as u32 + } + + fn vendor(&self) -> u32 { + VIRTIO_VENDOR_ID.into() + } + + fn irq(&self) -> Option { + self.inner().irq + } +} + +#[derive(Debug)] +#[cast_to([sync] VirtIODriver)] +#[cast_to([sync] Driver)] +struct VirtIOConsoleDriver { + inner: SpinLock, + devices: RwLock<[Option>; Self::MAX_DEVICES]>, + kobj_state: LockedKObjectState, +} + +impl VirtIOConsoleDriver { + const MAX_DEVICES: usize = 32; + + pub fn new() -> Arc { + let inner = InnerVirtIOConsoleDriver { + virtio_driver_common: VirtIODriverCommonData::default(), + driver_common: DriverCommonData::default(), + kobj_common: KObjectCommonData::default(), + id_bmp: bitmap::StaticBitmap::new(), + devname: [const { None }; Self::MAX_DEVICES], + }; + + let id_table = VirtioDeviceId::new( + virtio_drivers::transport::DeviceType::Console as u32, + VIRTIO_VENDOR_ID.into(), + ); + + let result = VirtIOConsoleDriver { + inner: SpinLock::new(inner), + kobj_state: LockedKObjectState::default(), + devices: RwLock::new([const { None }; Self::MAX_DEVICES]), + }; + + result.add_virtio_id(id_table); + Arc::new(result) + } + + fn inner(&self) -> SpinLockGuard { + self.inner.lock() + } + + fn do_install( + &self, + driver: Arc, + tty: Arc, + vc: Arc, + ) -> Result<(), SystemError> { + driver.standard_install(tty.clone())?; + vc.port().setup_internal_tty(Arc::downgrade(&tty)); + tty.set_port(vc.port()); + vc.devfs_setup()?; + + Ok(()) + } +} + +#[derive(Debug)] +struct InnerVirtIOConsoleDriver { + id_bmp: bitmap::StaticBitmap<{ VirtIOConsoleDriver::MAX_DEVICES }>, + devname: [Option; VirtIOConsoleDriver::MAX_DEVICES], + virtio_driver_common: VirtIODriverCommonData, + driver_common: DriverCommonData, + kobj_common: KObjectCommonData, +} + +impl InnerVirtIOConsoleDriver { + fn alloc_id(&mut self) -> Option { + let idx = self.id_bmp.first_false_index()?; + self.id_bmp.set(idx, true); + let name = Self::format_name(idx); + self.devname[idx] = Some(name.clone()); + Some(name) + } + + fn format_name(id: usize) -> DevName { + DevName::new(format!("vport{}", id), id) + } + + fn free_id(&mut self, id: usize) { + if id >= VirtIOConsoleDriver::MAX_DEVICES { + return; + } + self.id_bmp.set(id, false); + self.devname[id] = None; + } +} + +impl TtyOperation for VirtIOConsoleDriver { + fn open(&self, _tty: &TtyCoreData) -> Result<(), SystemError> { + Ok(()) + } + + fn write(&self, tty: &TtyCoreData, buf: &[u8], nr: usize) -> Result { + if nr > buf.len() { + return Err(SystemError::EINVAL); + } + let index = tty.index(); + if index >= VirtIOConsoleDriver::MAX_DEVICES { + return Err(SystemError::ENODEV); + } + + let dev = self.devices.read()[index] + .clone() + .ok_or(SystemError::ENODEV)?; + let mut cnt = 0; + let mut inner = dev.inner(); + for c in buf[0..nr].iter() { + if let Err(e) = inner.device_inner.send(*c) { + if cnt > 0 { + return Ok(cnt); + } + return Err(virtio_drivers_error_to_system_error(e)); + } else { + cnt += 1; + } + } + + Ok(cnt) + } + + fn flush_chars(&self, _tty: &TtyCoreData) { + // do nothing + } + + fn ioctl(&self, _tty: Arc, _cmd: u32, _arg: usize) -> Result<(), SystemError> { + Err(SystemError::ENOIOCTLCMD) + } + + fn close(&self, _tty: Arc) -> Result<(), SystemError> { + Ok(()) + } + + fn resize(&self, tty: Arc, winsize: WindowSize) -> Result<(), SystemError> { + *tty.core().window_size_write() = winsize; + Ok(()) + } + + fn install(&self, driver: Arc, tty: Arc) -> Result<(), SystemError> { + if tty.core().index() >= VirtIOConsoleDriver::MAX_DEVICES { + return Err(SystemError::ENODEV); + } + + let dev = self.devices.read()[tty.core().index()] + .clone() + .ok_or(SystemError::ENODEV)?; + let info = dev.inner().device_inner.info(); + let winsize = WindowSize::new(info.rows, info.columns, 1, 1); + + *tty.core().window_size_write() = winsize; + let vc_data = Arc::new(SpinLock::new(VirtualConsoleData::new(usize::MAX))); + let mut vc_data_guard = vc_data.lock_irqsave(); + vc_data_guard.set_driver_funcs(Arc::downgrade(&dummy_console()) as Weak); + vc_data_guard.init( + Some(tty.core().window_size().row.into()), + Some(tty.core().window_size().col.into()), + true, + ); + drop(vc_data_guard); + + let vc = VirtConsole::new(Some(vc_data)); + let vc_index = vc_manager().alloc(vc.clone()).ok_or(SystemError::EBUSY)?; + self.do_install(driver, tty, vc.clone()).inspect_err(|_| { + vc_manager().free(vc_index); + })?; + + Ok(()) + } +} + +impl VirtIODriver for VirtIOConsoleDriver { + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + log::debug!("VirtIOConsoleDriver::probe()"); + let _dev = device + .clone() + .arc_any() + .downcast::() + .map_err(|_| { + log::error!( + "VirtIOConsoleDriver::probe() failed: device is not a VirtIO console device. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + log::debug!("VirtIOConsoleDriver::probe() succeeded"); + Ok(()) + } + + fn virtio_id_table(&self) -> Vec { + self.inner().virtio_driver_common.id_table.clone() + } + + fn add_virtio_id(&self, id: VirtioDeviceId) { + self.inner().virtio_driver_common.id_table.push(id); + } +} + +impl Driver for VirtIOConsoleDriver { + fn id_table(&self) -> Option { + Some(IdTable::new(VIRTIO_CONSOLE_BASENAME.to_string(), None)) + } + + // todo: 添加错误时,资源释放的逻辑 + fn add_device(&self, device: Arc) { + log::debug!("virtio console: add_device"); + let virtio_con_dev = device.arc_any().downcast::().expect( + "VirtIOConsoleDriver::add_device() failed: device is not a VirtIOConsoleDevice", + ); + if virtio_con_dev.dev_name.initialized() { + panic!("VirtIOConsoleDriver::add_device() failed: dev_name has already initialized for device: '{:?}'", + virtio_con_dev.dev_id(), + ); + } + log::debug!("virtio console: add_device: to lock inner"); + let mut inner = self.inner(); + log::debug!("virtio console: add_device: inner.locked"); + let dev_name = inner.alloc_id(); + if dev_name.is_none() { + panic!("Failed to allocate ID for VirtIO console device: '{:?}', virtio console device limit exceeded.", virtio_con_dev.dev_id()) + } + + let dev_name = dev_name.unwrap(); + + virtio_con_dev.dev_name.init(dev_name); + + inner + .driver_common + .devices + .push(virtio_con_dev.clone() as Arc); + + // avoid deadlock in `init_tty_device` + drop(inner); + + let mut devices_fast_guard = self.devices.write(); + let index = virtio_con_dev.dev_name.get().id(); + if devices_fast_guard[index].is_none() { + devices_fast_guard[index] = Some(virtio_con_dev.clone()); + } else { + panic!("VirtIOConsoleDriver::add_device() failed: device slot already occupied at index: {}", index); + } + // avoid deadlock in `init_tty_device` + drop(devices_fast_guard); + + log::debug!("virtio console: add_device: to init tty device"); + let r = tty_hvc_driver().init_tty_device(Some(index)); + log::debug!( + "virtio console: add_device: init tty device done, index: {}, dev_name: {:?}", + index, + virtio_con_dev.dev_name.get(), + ); + if let Err(e) = r { + log::error!( + "Failed to init tty device for virtio console device, index: {}, dev_name: {:?}, err: {:?}", + index, + virtio_con_dev.dev_name.get(), + e, + ); + return; + } + } + + fn delete_device(&self, device: &Arc) { + let virtio_con_dev = device + .clone() + .arc_any() + .downcast::() + .expect( + "VirtIOConsoleDriver::delete_device() failed: device is not a VirtIOConsoleDevice", + ); + + let mut guard = self.inner(); + let mut devices_fast_guard = self.devices.write(); + let index = guard + .driver_common + .devices + .iter() + .position(|dev| Arc::ptr_eq(device, dev)) + .expect("VirtIOConsoleDriver::delete_device() failed: device not found"); + + guard.driver_common.devices.remove(index); + guard.free_id(virtio_con_dev.dev_name.get().id()); + + devices_fast_guard[index] = None; + } + + fn devices(&self) -> Vec> { + self.inner().driver_common.devices.clone() + } + + fn bus(&self) -> Option> { + Some(Arc::downgrade(&virtio_bus()) as Weak) + } + + fn set_bus(&self, _bus: Option>) { + // do nothing + } +} + +impl KObject for VirtIOConsoleDriver { + fn as_any_ref(&self) -> &dyn Any { + self + } + + fn set_inode(&self, inode: Option>) { + self.inner().kobj_common.kern_inode = inode; + } + + fn inode(&self) -> Option> { + self.inner().kobj_common.kern_inode.clone() + } + + fn parent(&self) -> Option> { + self.inner().kobj_common.parent.clone() + } + + fn set_parent(&self, parent: Option>) { + self.inner().kobj_common.parent = parent; + } + + fn kset(&self) -> Option> { + self.inner().kobj_common.kset.clone() + } + + fn set_kset(&self, kset: Option>) { + self.inner().kobj_common.kset = kset; + } + + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner().kobj_common.kobj_type + } + + fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) { + self.inner().kobj_common.kobj_type = ktype; + } + + fn name(&self) -> String { + VIRTIO_CONSOLE_BASENAME.to_string() + } + + fn set_name(&self, _name: String) { + // do nothing + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.kobj_state.write() + } + + fn set_kobj_state(&self, state: KObjectState) { + *self.kobj_state.write() = state; + } +} + +#[unified_init(INITCALL_POSTCORE)] +fn virtio_console_driver_init() -> Result<(), SystemError> { + let driver = VirtIOConsoleDriver::new(); + virtio_driver_manager() + .register(driver.clone() as Arc) + .expect("Add virtio console driver failed"); + unsafe { + VIRTIO_CONSOLE_DRIVER = Some(driver.clone()); + } + let hvc_tty_driver = TtyDriver::new( + VirtIOConsoleDriver::MAX_DEVICES.try_into().unwrap(), + "hvc", + 0, + Major::HVC_MAJOR, + HVC_MINOR, + TtyDriverType::System, + *TTY_STD_TERMIOS, + driver.clone(), + None, + ); + + let hvc_tty_driver = TtyDriverManager::tty_register_driver(hvc_tty_driver)?; + compiler_fence(Ordering::SeqCst); + unsafe { + TTY_HVC_DRIVER = Some(hvc_tty_driver); + } + + compiler_fence(Ordering::SeqCst); + + return Ok(()); +} diff --git a/kernel/src/driver/disk/ahci/ahcidisk.rs b/kernel/src/driver/disk/ahci/ahcidisk.rs index 76bc05b33..b3c16ad93 100644 --- a/kernel/src/driver/disk/ahci/ahcidisk.rs +++ b/kernel/src/driver/disk/ahci/ahcidisk.rs @@ -1,15 +1,13 @@ use super::{_port, hba::HbaCmdTable}; use crate::arch::MMArch; -use crate::driver::base::block::block_device::{ - BlockDevName, BlockDevice, BlockId, GeneralBlockRange, -}; +use crate::driver::base::block::block_device::{BlockDevice, BlockId, GeneralBlockRange}; use crate::driver::base::block::disk_info::Partition; use crate::driver::base::block::manager::BlockDevMeta; use crate::driver::base::class::Class; use crate::driver::base::device::bus::Bus; use crate::driver::base::device::driver::Driver; -use crate::driver::base::device::{Device, DeviceType, IdTable}; +use crate::driver::base::device::{DevName, Device, DeviceType, IdTable}; use crate::driver::base::kobject::{KObjType, KObject, KObjectState}; use crate::driver::base::kset::KSet; use crate::driver::disk::ahci::HBA_PxIS_TFES; @@ -520,7 +518,7 @@ impl Device for LockedAhciDisk { } impl BlockDevice for LockedAhciDisk { - fn dev_name(&self) -> &BlockDevName { + fn dev_name(&self) -> &DevName { &self.blkdev_meta.devname } diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index 3b723b780..8fae3da2f 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,6 +1,7 @@ pub mod acpi; pub mod base; pub mod block; +pub mod char; pub mod clocksource; pub mod disk; pub mod firmware; diff --git a/kernel/src/driver/net/e1000e/e1000e.rs b/kernel/src/driver/net/e1000e/e1000e.rs index 0383c8ac9..cb08a6113 100644 --- a/kernel/src/driver/net/e1000e/e1000e.rs +++ b/kernel/src/driver/net/e1000e/e1000e.rs @@ -587,11 +587,13 @@ impl Drop for E1000EDevice { pub fn e1000e_init() { match e1000e_probe() { - Ok(_code) => { - info!("Successfully init e1000e device!"); + Ok(code) => { + if code == 1 { + info!("Successfully init e1000e device!"); + } } - Err(_error) => { - info!("Error occurred!"); + Err(error) => { + info!("Failed to init e1000e device: {error:?}"); } } } @@ -602,6 +604,7 @@ pub fn e1000e_probe() -> Result { if result.is_empty() { return Ok(0); } + let mut initialized = false; for device in result { let standard_device = device.as_standard_device().unwrap(); if standard_device.common_header.vendor_id == 0x8086 { @@ -625,11 +628,16 @@ pub fn e1000e_probe() -> Result { .unwrap(), )?; e1000e_driver_init(e1000e); + initialized = true; } } } - return Ok(1); + if initialized { + Ok(1) + } else { + Ok(0) + } } // 用到的e1000e寄存器结构体 @@ -787,6 +795,7 @@ const E1000E_TXD_CMD_RS: u8 = 1 << 3; /// E1000E驱动初始化过程中可能的错误 #[allow(dead_code)] +#[derive(Debug)] pub enum E1000EPciError { // 获取到错误类型的BAR(IO BAR) // An IO BAR was provided rather than a memory BAR. diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 35190e2b9..32e7ddad1 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -6,7 +6,6 @@ use core::{ }; use alloc::{ - collections::LinkedList, string::{String, ToString}, sync::{Arc, Weak}, vec::Vec, @@ -108,7 +107,7 @@ impl VirtIONetDevice { let mac = wire::EthernetAddress::from_bytes(&driver_net.mac_address()); debug!("VirtIONetDevice mac: {:?}", mac); let device_inner = VirtIONicDeviceInner::new(driver_net); - + device_inner.inner.lock_irqsave().enable_interrupts(); let dev = Arc::new(Self { dev_id, inner: SpinLock::new(InnerVirtIONetDevice { @@ -259,7 +258,9 @@ impl Device for VirtIONetDevice { impl VirtIODevice for VirtIONetDevice { fn handle_irq(&self, _irq: IrqNumber) -> Result { - poll_ifaces_try_lock_onetime().ok(); + if poll_ifaces_try_lock_onetime().is_err() { + log::error!("virtio_net: try lock failed"); + } return Ok(IrqReturn::Handled); } @@ -865,12 +866,12 @@ impl VirtIODriver for VirtIONetDriver { return Ok(()); } - fn virtio_id_table(&self) -> LinkedList { + fn virtio_id_table(&self) -> Vec { self.inner().virtio_driver_common.id_table.clone() } fn add_virtio_id(&self, id: VirtioDeviceId) { - self.inner().virtio_driver_common.id_table.push_back(id); + self.inner().virtio_driver_common.id_table.push(id); } } diff --git a/kernel/src/driver/scsi/mod.rs b/kernel/src/driver/scsi/mod.rs index 21a42cc85..3a01f1ff9 100644 --- a/kernel/src/driver/scsi/mod.rs +++ b/kernel/src/driver/scsi/mod.rs @@ -7,7 +7,7 @@ use crate::{ libs::spinlock::{SpinLock, SpinLockGuard}, }; -use super::base::block::block_device::BlockDevName; +use super::base::device::DevName; static mut SCSI_MANAGER: Option = None; @@ -30,7 +30,7 @@ pub struct ScsiManager { struct InnerScsiManager { id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>, - devname: [Option; ScsiManager::MAX_DEVICES], + devname: [Option; ScsiManager::MAX_DEVICES], } impl ScsiManager { @@ -49,7 +49,7 @@ impl ScsiManager { self.inner.lock() } - pub fn alloc_id(&self) -> Option { + pub fn alloc_id(&self) -> Option { let mut inner = self.inner(); let idx = inner.id_bmp.first_false_index()?; inner.id_bmp.set(idx, true); @@ -59,9 +59,9 @@ impl ScsiManager { } /// Generate a new block device name like 'sda', 'sdb', etc. - fn format_name(id: usize) -> BlockDevName { + fn format_name(id: usize) -> DevName { let x = (b'a' + id as u8) as char; - BlockDevName::new(format!("sd{}", x), id) + DevName::new(format!("sd{}", x), id) } #[allow(dead_code)] diff --git a/kernel/src/driver/tty/tty_core.rs b/kernel/src/driver/tty/tty_core.rs index 93f0e9c4e..112289ba5 100644 --- a/kernel/src/driver/tty/tty_core.rs +++ b/kernel/src/driver/tty/tty_core.rs @@ -50,6 +50,7 @@ impl Drop for TtyCore { } impl TtyCore { + #[inline(never)] pub fn new(driver: Arc, index: usize) -> Arc { let name = driver.tty_line_name(index); let device_number = driver @@ -76,7 +77,6 @@ impl TtyCore { device_number, privete_fields: SpinLock::new(None), }; - return Arc::new(Self { core, line_discipline: Arc::new(NTtyLinediscipline { diff --git a/kernel/src/driver/tty/tty_driver.rs b/kernel/src/driver/tty/tty_driver.rs index a586599f9..6c0ffcf1d 100644 --- a/kernel/src/driver/tty/tty_driver.rs +++ b/kernel/src/driver/tty/tty_driver.rs @@ -309,10 +309,16 @@ impl TtyDriver { } else { idx = self.ida.lock().alloc().ok_or(SystemError::EBUSY)?; } - + log::debug!("init_tty_device: create TtyCore"); let tty = TtyCore::new(self.self_ref(), idx); + log::debug!("init_tty_device: to driver_install_tty"); self.driver_install_tty(tty.clone())?; + log::debug!( + "init_tty_device: driver_install_tty done, index: {}, dev_name: {:?}", + idx, + tty.core().name(), + ); let core = tty.core(); @@ -321,18 +327,20 @@ impl TtyDriver { ports[core.index()].setup_internal_tty(Arc::downgrade(&tty)); tty.set_port(ports[core.index()].clone()); } - + log::debug!("init_tty_device: to ldisc_setup"); TtyLdiscManager::ldisc_setup(tty.clone(), tty.core().link())?; // 在devfs创建对应的文件 + log::debug!("init_tty_device: to new tty device"); let device = TtyDevice::new( core.name().clone(), IdTable::new(self.tty_line_name(idx), Some(*core.device_number())), super::tty_device::TtyType::Tty, ); - + log::debug!("init_tty_device: to devfs_register"); devfs_register(device.name_ref(), device.clone())?; + log::debug!("init_tty_device: to device_register"); device_register(device)?; Ok(tty) } @@ -473,8 +481,8 @@ pub trait TtyOperation: Sync + Send + Debug { fn flush_chars(&self, tty: &TtyCoreData); - fn put_char(&self, _tty: &TtyCoreData, _ch: u8) -> Result<(), SystemError> { - Err(SystemError::ENOSYS) + fn put_char(&self, tty: &TtyCoreData, ch: u8) -> Result<(), SystemError> { + self.write(tty, &[ch], 1).map(|_| ()) } fn start(&self, _tty: &TtyCoreData) -> Result<(), SystemError> { diff --git a/kernel/src/driver/tty/virtual_terminal/mod.rs b/kernel/src/driver/tty/virtual_terminal/mod.rs index 31abbfb62..5ec8d28e1 100644 --- a/kernel/src/driver/tty/virtual_terminal/mod.rs +++ b/kernel/src/driver/tty/virtual_terminal/mod.rs @@ -58,6 +58,8 @@ lazy_static! { static ref VC_MANAGER: VirtConsoleManager = VirtConsoleManager::new(); } +kernel_cmdline_param_kv!(CONSOLE_PARAM, console, ""); + /// 获取虚拟终端管理器 #[inline] pub fn vc_manager() -> &'static VirtConsoleManager { @@ -228,12 +230,29 @@ impl VirtConsoleManager { } pub fn setup_default_vc(&self) { - // todo: 从内核启动参数中获取 - for name in Self::DEFAULT_VC_NAMES.iter() { - if let Some(vc) = self.lookup_vc_by_tty_name(name) { - log::info!("Set default vc with tty device: {}", name); + let mut console_value_str = CONSOLE_PARAM.value_str().unwrap_or("").trim(); + if !console_value_str.is_empty() { + // 删除前缀/dev/ + console_value_str = console_value_str + .strip_prefix("/dev/") + .unwrap_or(console_value_str); + if let Some(vc) = self.lookup_vc_by_tty_name(console_value_str) { + log::info!("Set vc by cmdline: {}", console_value_str); self.set_current_vc(vc); return; + } else { + panic!( + "virt console: set vc by cmdline failed, name: {}", + console_value_str + ); + } + } else { + for name in Self::DEFAULT_VC_NAMES.iter() { + if let Some(vc) = self.lookup_vc_by_tty_name(name) { + log::info!("Set default vc with tty device: {}", name); + self.set_current_vc(vc); + return; + } } } diff --git a/kernel/src/driver/virtio/mod.rs b/kernel/src/driver/virtio/mod.rs index d0a1db91c..fca5212ba 100644 --- a/kernel/src/driver/virtio/mod.rs +++ b/kernel/src/driver/virtio/mod.rs @@ -1,4 +1,4 @@ -use alloc::{collections::LinkedList, string::String, sync::Arc}; +use alloc::{string::String, sync::Arc, vec::Vec}; use system_error::SystemError; use crate::exception::{irqdesc::IrqReturn, IrqNumber}; @@ -51,7 +51,7 @@ pub trait VirtIODevice: Device { pub trait VirtIODriver: Driver { fn probe(&self, device: &Arc) -> Result<(), SystemError>; - fn virtio_id_table(&self) -> LinkedList; + fn virtio_id_table(&self) -> Vec; fn add_virtio_id(&self, id: VirtioDeviceId); } @@ -60,7 +60,7 @@ int_like!(VirtIODeviceIndex, usize); #[derive(Debug, Default)] pub struct VirtIODriverCommonData { - pub id_table: LinkedList, + pub id_table: Vec, } /// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/include/linux/mod_devicetable.h#449 @@ -75,3 +75,19 @@ impl VirtioDeviceId { Self { device, vendor } } } + +pub fn virtio_drivers_error_to_system_error(error: virtio_drivers::Error) -> SystemError { + match error { + virtio_drivers::Error::QueueFull => SystemError::ENOBUFS, + virtio_drivers::Error::NotReady => SystemError::EAGAIN_OR_EWOULDBLOCK, + virtio_drivers::Error::WrongToken => SystemError::EINVAL, + virtio_drivers::Error::AlreadyUsed => SystemError::EBUSY, + virtio_drivers::Error::InvalidParam => SystemError::EINVAL, + virtio_drivers::Error::DmaError => SystemError::ENOMEM, + virtio_drivers::Error::IoError => SystemError::EIO, + virtio_drivers::Error::Unsupported => SystemError::ENOSYS, + virtio_drivers::Error::ConfigSpaceTooSmall => SystemError::EINVAL, + virtio_drivers::Error::ConfigSpaceMissing => SystemError::EINVAL, + virtio_drivers::Error::SocketDeviceError(_) => SystemError::EIO, + } +} diff --git a/kernel/src/driver/virtio/sysfs.rs b/kernel/src/driver/virtio/sysfs.rs index b528d5c0c..c51f3d114 100644 --- a/kernel/src/driver/virtio/sysfs.rs +++ b/kernel/src/driver/virtio/sysfs.rs @@ -196,11 +196,14 @@ impl VirtIODeviceManager { dev.set_virtio_device_index(virtio_index); dev.set_device_name(format!("virtio{}", virtio_index.data())); + log::debug!("virtio_device_add: dev: {:?}", dev); + // 添加设备到设备管理器 device_manager().add_device(dev.clone() as Arc)?; let r = device_manager() .add_groups(&(dev.clone() as Arc), &[&VirtIODeviceAttrGroup]); - + log::debug!("virtio_device_add: to setup irq"); self.setup_irq(&dev).ok(); + log::debug!("virtio_device_add: setup irq done"); return r; } diff --git a/kernel/src/driver/virtio/virtio.rs b/kernel/src/driver/virtio/virtio.rs index 4864f01bb..414d11e25 100644 --- a/kernel/src/driver/virtio/virtio.rs +++ b/kernel/src/driver/virtio/virtio.rs @@ -4,6 +4,7 @@ use super::virtio_impl::HalImpl; use crate::driver::base::device::bus::Bus; use crate::driver::base::device::{Device, DeviceId}; use crate::driver::block::virtio_blk::virtio_blk; +use crate::driver::char::virtio_console::virtio_console; use crate::driver::net::virtio_net::virtio_net; use crate::driver::pci::pci::{ get_pci_device_structures_mut_by_vendor_id, PciDeviceStructureGeneralDevice, @@ -11,18 +12,24 @@ use crate::driver::pci::pci::{ }; use crate::driver::pci::subsys::pci_bus; use crate::driver::virtio::transport::VirtIOTransport; +use crate::init::initcall::INITCALL_DEVICE; use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; use log::{debug, error, warn}; +use system_error::SystemError; +use unified_init::macros::unified_init; use virtio_drivers::transport::{DeviceType, Transport}; ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加) -pub fn virtio_probe() { +#[unified_init(INITCALL_DEVICE)] +fn virtio_probe() -> Result<(), SystemError> { #[cfg(not(target_arch = "riscv64"))] virtio_probe_pci(); virtio_probe_mmio(); + + Ok(()) } #[allow(dead_code)] @@ -63,6 +70,7 @@ pub(super) fn virtio_device_init( DeviceType::GPU => { warn!("Not support virtio_gpu device for now"); } + DeviceType::Console => virtio_console(transport, dev_id, dev_parent), DeviceType::Input => { warn!("Not support virtio_input device for now"); } diff --git a/kernel/src/filesystem/devfs/mod.rs b/kernel/src/filesystem/devfs/mod.rs index 92f602a22..51cafc7db 100644 --- a/kernel/src/filesystem/devfs/mod.rs +++ b/kernel/src/filesystem/devfs/mod.rs @@ -141,16 +141,21 @@ impl DevFS { .as_any_ref() .downcast_ref::() .unwrap(); - // 在 /dev/char 下创建设备节点 - dev_char_inode.add_dev(name, device.clone())?; // 特殊处理 tty 设备,挂载在 /dev 下 if name.starts_with("tty") && name.len() > 3 { dev_root_inode.add_dev(name, device.clone())?; - } - // ptmx设备 - if name == "ptmx" { + } else if name.starts_with("hvc") && name.len() > 3 { + // 特殊处理 hvc 设备,挂载在 /dev 下 dev_root_inode.add_dev(name, device.clone())?; + } else if name == "console" { + dev_root_inode.add_dev(name, device.clone())?; + } else if name == "ptmx" { + // ptmx设备 + dev_root_inode.add_dev(name, device.clone())?; + } else { + // 在 /dev/char 下创建设备节点 + dev_char_inode.add_dev(name, device.clone())?; } device.set_fs(dev_char_inode.0.lock().fs.clone()); } diff --git a/kernel/src/init/initial_kthread.rs b/kernel/src/init/initial_kthread.rs index a79c59da9..d3ed834f4 100644 --- a/kernel/src/init/initial_kthread.rs +++ b/kernel/src/init/initial_kthread.rs @@ -8,7 +8,7 @@ use system_error::SystemError; use crate::{ arch::{interrupt::TrapFrame, process::arch_switch_to_user}, - driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe}, + driver::net::e1000e::e1000e::e1000e_init, filesystem::vfs::core::mount_root_fs, namespaces::NsProxy, net::net_core::net_init, @@ -45,7 +45,7 @@ fn kernel_init() -> Result<(), SystemError> { crate::driver::disk::ahci::ahci_init() .inspect_err(|e| log::error!("ahci_init failed: {:?}", e)) .ok(); - virtio_probe(); + mount_root_fs().expect("Failed to mount root fs"); e1000e_init(); net_init().unwrap_or_else(|err| { diff --git a/kernel/src/mm/allocator/slab.rs b/kernel/src/mm/allocator/slab.rs index 4ac38a316..b48306e9f 100644 --- a/kernel/src/mm/allocator/slab.rs +++ b/kernel/src/mm/allocator/slab.rs @@ -35,6 +35,10 @@ impl SlabAllocator { Ok(nptr) => nptr.as_ptr(), Err(AllocationError::OutOfMemory) => { let boxed_page = ObjectPage::new(); + assert_eq!( + (boxed_page.as_ref() as *const ObjectPage as usize) & (MMArch::PAGE_SIZE - 1), + 0 + ); let leaked_page = Box::leak(boxed_page); self.zone .refill(layout, leaked_page) diff --git a/kernel/src/namespaces/mnt_namespace.rs b/kernel/src/namespaces/mnt_namespace.rs index e5312d82c..15d3efda1 100644 --- a/kernel/src/namespaces/mnt_namespace.rs +++ b/kernel/src/namespaces/mnt_namespace.rs @@ -92,7 +92,8 @@ impl FsStruct { impl Namespace for MntNamespace { fn ns_common_to_ns(ns_common: Arc) -> Arc { let ns_common_ptr = Arc::as_ptr(&ns_common); - container_of!(ns_common_ptr, MntNamespace, ns_common) + // container_of!(ns_common_ptr, MntNamespace, ns_common) + panic!("not implemented") } } diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh index 7b48644c0..a82067e41 100644 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -82,11 +82,14 @@ QEMU_SERIAL_LOG_FILE="../serial_opt.txt" QEMU_SERIAL="-serial file:${QEMU_SERIAL_LOG_FILE}" QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none" QEMU_ACCELARATE="" -QEMU_ARGUMENT="" +QEMU_ARGUMENT=" -no-reboot " QEMU_DEVICES="" + +KERNEL_CMDLINE="" + BIOS_TYPE="" #这个变量为true则使用virtio磁盘 -VIRTIO_BLK_DEVICE=false +VIRTIO_BLK_DEVICE=true # 如果qemu_accel不为空 if [ -n "${qemu_accel}" ]; then QEMU_ACCELARATE=" -machine accel=${qemu_accel} " @@ -139,9 +142,13 @@ while true;do ;; nographic) QEMU_SERIAL=" -serial chardev:mux -monitor chardev:mux -chardev stdio,id=mux,mux=on,signal=off,logfile=${QEMU_SERIAL_LOG_FILE} " + # 添加 virtio console 设备 + QEMU_DEVICES+=" -device virtio-serial -device virtconsole,chardev=mux " + KERNEL_CMDLINE+=" console=/dev/hvc0 " QEMU_MONITOR="" QEMU_ARGUMENT+=" --nographic " QEMU_ARGUMENT+=" -kernel ../bin/kernel/kernel.elf " + QEMU_ARGUMENT+="-append ${KERNEL_CMDLINE}" ;; esac;shift 2;; @@ -156,12 +163,15 @@ QEMU_DEVICES+="${QEMU_DEVICES_DISK} " QEMU_DEVICES+=" -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 " # E1000E # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -net nic,model=e1000e,netdev=hostnet0,id=net0 -netdev user,id=hostnet1,hostfwd=tcp::12581-:12581 -device virtio-net-pci,vectors=5,netdev=hostnet1,id=net1 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 " + + QEMU_ARGUMENT+="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d ${QEMU_MONITOR} -d ${qemu_trace_std} " QEMU_ARGUMENT+="-s ${QEMU_MACHINE} ${QEMU_CPU_FEATURES} ${QEMU_RTC_CLOCK} ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES} " QEMU_ARGUMENT+=" ${QEMU_SHM_OBJECT} " QEMU_ARGUMENT+=" ${QEMU_ACCELARATE} " +QEMU_ARGUMENT+=" -D ../qemu.log " # 安装riscv64的uboot