Browse Source

feature: virtio console support (#1113)

feat(virtio): add virtio console driver support

- Implement virtio console driver with TTY interface
- Add HVC device support for console output
- Update devfs to handle HVC devices
- Fix virtio driver registration and initialization
- Improve virtio net driver interrupt handling
- Clean up block device naming implementation
- Add clippy lint checks to multiple crates
- Fix slab allocator alignment issues
- Update QEMU run script for virtio consoleagonOS.org>

---------

Signed-off-by: longjin <[email protected]>
LoGin 3 days ago
parent
commit
b6db20c072

+ 1 - 0
.gitignore

@@ -19,3 +19,4 @@ cppcheck.xml
 .cache
 compile_commands.json
 /logs/
+*.log

+ 1 - 1
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" }

+ 6 - 0
kernel/crates/bitmap/src/bitmap_core.rs

@@ -7,6 +7,12 @@ pub struct BitMapCore<T: BitOps> {
     phantom: PhantomData<T>,
 }
 
+impl<T: BitOps> Default for BitMapCore<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
 impl<T: BitOps> BitMapCore<T> {
     pub const fn new() -> Self {
         Self {

+ 1 - 0
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)]
 

+ 2 - 1
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;

+ 10 - 7
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(),

+ 1 - 1
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(),

+ 1 - 1
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
+export RUSTDOCFLAGS := -C link-args=-znostart-stop-gc

+ 4 - 67
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<String>,
-    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<H: core::hash::Hasher>(&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;
 

+ 5 - 5
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<BlockDevName, Arc<dyn BlockDevice>>,
+    disks: HashMap<DevName, Arc<dyn BlockDevice>>,
 }
 impl BlockDevManager {
     pub fn new() -> Self {
@@ -207,7 +207,7 @@ impl BlockDevManager {
 }
 
 pub struct BlockDevMeta {
-    pub devname: BlockDevName,
+    pub devname: DevName,
     inner: SpinLock<InnerBlockDevMeta>,
 }
 
@@ -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 {

+ 2 - 0
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)
     }

+ 64 - 1
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<KSet>) {
     DEVICES_VIRTUAL_KSET_INSTANCE = Some(kset);
 }
 
+/// /dev下面的设备的名字
+pub struct DevName {
+    name: Arc<String>,
+    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<H: core::hash::Hasher>(&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 {}
+
 /// 设备应该实现的操作
 ///
 /// ## 注意

+ 11 - 12
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<BlockDevName>; VirtIOBlkManager::MAX_DEVICES],
+    devname: [Option<DevName>; VirtIOBlkManager::MAX_DEVICES],
 }
 
 impl VirtIOBlkManager {
@@ -122,7 +121,7 @@ impl VirtIOBlkManager {
         self.inner.lock()
     }
 
-    pub fn alloc_id(&self) -> Option<BlockDevName> {
+    pub fn alloc_id(&self) -> Option<DevName> {
         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<dyn VirtIODriver>)
-        .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<crate::driver::virtio::VirtioDeviceId> {
+    fn virtio_id_table(&self) -> Vec<crate::driver::virtio::VirtioDeviceId> {
         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);
     }
 }
 

+ 1 - 0
kernel/src/driver/char/mod.rs

@@ -0,0 +1 @@
+pub mod virtio_console;

+ 736 - 0
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<Arc<VirtIOConsoleDriver>> = None;
+static mut TTY_HVC_DRIVER: Option<Arc<TtyDriver>> = None;
+
+#[inline(always)]
+fn tty_hvc_driver() -> &'static Arc<TtyDriver> {
+    unsafe { TTY_HVC_DRIVER.as_ref().unwrap() }
+}
+
+pub fn virtio_console(
+    transport: VirtIOTransport,
+    dev_id: Arc<DeviceId>,
+    dev_parent: Option<Arc<dyn Device>>,
+) {
+    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<dyn VirtIODevice>)
+        .expect("Add virtio console failed");
+}
+
+//
+#[derive(Debug)]
+#[cast_to([sync] VirtIODevice)]
+#[cast_to([sync] Device)]
+pub struct VirtIOConsoleDevice {
+    dev_name: Lazy<DevName>,
+    dev_id: Arc<DeviceId>,
+    _self_ref: Weak<Self>,
+    locked_kobj_state: LockedKObjectState,
+    inner: SpinLock<InnerVirtIOConsoleDevice>,
+}
+unsafe impl Send for VirtIOConsoleDevice {}
+unsafe impl Sync for VirtIOConsoleDevice {}
+
+impl VirtIOConsoleDevice {
+    pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
+        // 设置中断
+        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::<HalImpl, VirtIOTransport>::new(transport);
+        if let Err(e) = device_inner {
+            log::error!("VirtIOConsoleDevice '{dev_id:?}' create failed: {:?}", e);
+            return None;
+        }
+
+        let mut device_inner: VirtIOConsole<HalImpl, VirtIOTransport> = 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<InnerVirtIOConsoleDevice> {
+        self.inner.lock_irqsave()
+    }
+}
+
+struct InnerVirtIOConsoleDevice {
+    device_inner: VirtIOConsole<HalImpl, VirtIOTransport>,
+    virtio_index: Option<VirtIODeviceIndex>,
+    name: Option<String>,
+    device_common: DeviceCommonData,
+    kobject_common: KObjectCommonData,
+    irq: Option<IrqNumber>,
+}
+
+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<Arc<KernFSInode>>) {
+        self.inner().kobject_common.kern_inode = inode;
+    }
+
+    fn inode(&self) -> Option<Arc<KernFSInode>> {
+        self.inner().kobject_common.kern_inode.clone()
+    }
+
+    fn parent(&self) -> Option<Weak<dyn KObject>> {
+        self.inner().kobject_common.parent.clone()
+    }
+
+    fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
+        self.inner().kobject_common.parent = parent;
+    }
+
+    fn kset(&self) -> Option<Arc<KSet>> {
+        self.inner().kobject_common.kset.clone()
+    }
+
+    fn set_kset(&self, kset: Option<Arc<KSet>>) {
+        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<KObjectState> {
+        self.locked_kobj_state.read()
+    }
+
+    fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
+        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<Weak<dyn Bus>> {
+        self.inner().device_common.bus.clone()
+    }
+
+    fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
+        self.inner().device_common.bus = bus;
+    }
+
+    fn class(&self) -> Option<Arc<dyn Class>> {
+        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<Weak<dyn Class>>) {
+        self.inner().device_common.class = class;
+    }
+
+    fn driver(&self) -> Option<Arc<dyn Driver>> {
+        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<Weak<dyn Driver>>) {
+        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<Weak<dyn Device>> {
+        self.inner().device_common.get_parent_weak_or_clear()
+    }
+
+    fn set_dev_parent(&self, parent: Option<Weak<dyn Device>>) {
+        self.inner().device_common.parent = parent;
+    }
+}
+
+impl VirtIODevice for VirtIOConsoleDevice {
+    fn handle_irq(&self, _irq: IrqNumber) -> Result<IrqReturn, SystemError> {
+        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<DeviceId> {
+        &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<VirtIODeviceIndex> {
+        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<IrqNumber> {
+        self.inner().irq
+    }
+}
+
+#[derive(Debug)]
+#[cast_to([sync] VirtIODriver)]
+#[cast_to([sync] Driver)]
+struct VirtIOConsoleDriver {
+    inner: SpinLock<InnerVirtIOConsoleDriver>,
+    devices: RwLock<[Option<Arc<VirtIOConsoleDevice>>; Self::MAX_DEVICES]>,
+    kobj_state: LockedKObjectState,
+}
+
+impl VirtIOConsoleDriver {
+    const MAX_DEVICES: usize = 32;
+
+    pub fn new() -> Arc<Self> {
+        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<InnerVirtIOConsoleDriver> {
+        self.inner.lock()
+    }
+
+    fn do_install(
+        &self,
+        driver: Arc<TtyDriver>,
+        tty: Arc<TtyCore>,
+        vc: Arc<VirtConsole>,
+    ) -> 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<DevName>; VirtIOConsoleDriver::MAX_DEVICES],
+    virtio_driver_common: VirtIODriverCommonData,
+    driver_common: DriverCommonData,
+    kobj_common: KObjectCommonData,
+}
+
+impl InnerVirtIOConsoleDriver {
+    fn alloc_id(&mut self) -> Option<DevName> {
+        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<usize, SystemError> {
+        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<TtyCore>, _cmd: u32, _arg: usize) -> Result<(), SystemError> {
+        Err(SystemError::ENOIOCTLCMD)
+    }
+
+    fn close(&self, _tty: Arc<TtyCore>) -> Result<(), SystemError> {
+        Ok(())
+    }
+
+    fn resize(&self, tty: Arc<TtyCore>, winsize: WindowSize) -> Result<(), SystemError> {
+        *tty.core().window_size_write() = winsize;
+        Ok(())
+    }
+
+    fn install(&self, driver: Arc<TtyDriver>, tty: Arc<TtyCore>) -> 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<dyn ConsoleSwitch>);
+        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<dyn VirtIODevice>) -> Result<(), SystemError> {
+        log::debug!("VirtIOConsoleDriver::probe()");
+        let _dev = device
+            .clone()
+            .arc_any()
+            .downcast::<VirtIOConsoleDevice>()
+            .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<VirtioDeviceId> {
+        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<IdTable> {
+        Some(IdTable::new(VIRTIO_CONSOLE_BASENAME.to_string(), None))
+    }
+
+    // todo: 添加错误时,资源释放的逻辑
+    fn add_device(&self, device: Arc<dyn Device>) {
+        log::debug!("virtio console: add_device");
+        let virtio_con_dev = device.arc_any().downcast::<VirtIOConsoleDevice>().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<dyn Device>);
+
+        // 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<dyn Device>) {
+        let virtio_con_dev = device
+            .clone()
+            .arc_any()
+            .downcast::<VirtIOConsoleDevice>()
+            .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<Arc<dyn Device>> {
+        self.inner().driver_common.devices.clone()
+    }
+
+    fn bus(&self) -> Option<Weak<dyn Bus>> {
+        Some(Arc::downgrade(&virtio_bus()) as Weak<dyn Bus>)
+    }
+
+    fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
+        // do nothing
+    }
+}
+
+impl KObject for VirtIOConsoleDriver {
+    fn as_any_ref(&self) -> &dyn Any {
+        self
+    }
+
+    fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
+        self.inner().kobj_common.kern_inode = inode;
+    }
+
+    fn inode(&self) -> Option<Arc<KernFSInode>> {
+        self.inner().kobj_common.kern_inode.clone()
+    }
+
+    fn parent(&self) -> Option<Weak<dyn KObject>> {
+        self.inner().kobj_common.parent.clone()
+    }
+
+    fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
+        self.inner().kobj_common.parent = parent;
+    }
+
+    fn kset(&self) -> Option<Arc<KSet>> {
+        self.inner().kobj_common.kset.clone()
+    }
+
+    fn set_kset(&self, kset: Option<Arc<KSet>>) {
+        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<KObjectState> {
+        self.kobj_state.read()
+    }
+
+    fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
+        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<dyn VirtIODriver>)
+        .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(());
+}

+ 3 - 5
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
     }
 

+ 1 - 0
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;

+ 14 - 5
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<u64, E1000EPciError> {
     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<u64, E1000EPciError> {
                     .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.

+ 6 - 5
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<IrqReturn, SystemError> {
-        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<VirtioDeviceId> {
+    fn virtio_id_table(&self) -> Vec<VirtioDeviceId> {
         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);
     }
 }
 

+ 5 - 5
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<ScsiManager> = None;
 
@@ -30,7 +30,7 @@ pub struct ScsiManager {
 
 struct InnerScsiManager {
     id_bmp: bitmap::StaticBitmap<{ ScsiManager::MAX_DEVICES }>,
-    devname: [Option<BlockDevName>; ScsiManager::MAX_DEVICES],
+    devname: [Option<DevName>; ScsiManager::MAX_DEVICES],
 }
 
 impl ScsiManager {
@@ -49,7 +49,7 @@ impl ScsiManager {
         self.inner.lock()
     }
 
-    pub fn alloc_id(&self) -> Option<BlockDevName> {
+    pub fn alloc_id(&self) -> Option<DevName> {
         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)]

+ 1 - 1
kernel/src/driver/tty/tty_core.rs

@@ -50,6 +50,7 @@ impl Drop for TtyCore {
 }
 
 impl TtyCore {
+    #[inline(never)]
     pub fn new(driver: Arc<TtyDriver>, index: usize) -> Arc<Self> {
         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 {

+ 13 - 5
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> {

+ 23 - 4
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;
+                }
             }
         }
 

+ 19 - 3
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<dyn VirtIODevice>) -> Result<(), SystemError>;
 
-    fn virtio_id_table(&self) -> LinkedList<VirtioDeviceId>;
+    fn virtio_id_table(&self) -> Vec<VirtioDeviceId>;
 
     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<VirtioDeviceId>,
+    pub id_table: Vec<VirtioDeviceId>,
 }
 
 /// 参考: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,
+    }
+}

+ 4 - 1
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<dyn Device>)?;
         let r = device_manager()
             .add_groups(&(dev.clone() as Arc<dyn Device>), &[&VirtIODeviceAttrGroup]);
-
+        log::debug!("virtio_device_add: to setup irq");
         self.setup_irq(&dev).ok();
+        log::debug!("virtio_device_add: setup irq done");
 
         return r;
     }

+ 9 - 1
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");
         }

+ 10 - 5
kernel/src/filesystem/devfs/mod.rs

@@ -141,16 +141,21 @@ impl DevFS {
                     .as_any_ref()
                     .downcast_ref::<LockedDevFSInode>()
                     .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());
             }

+ 2 - 2
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| {

+ 4 - 0
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)

+ 2 - 1
kernel/src/namespaces/mnt_namespace.rs

@@ -92,7 +92,8 @@ impl FsStruct {
 impl Namespace for MntNamespace {
     fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self> {
         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")
     }
 }
 

+ 12 - 2
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