diff --git a/kernel/src/arch/x86_64/driver/apic/x2apic.rs b/kernel/src/arch/x86_64/driver/apic/x2apic.rs index 3f01d2e59..7718cb45d 100644 --- a/kernel/src/arch/x86_64/driver/apic/x2apic.rs +++ b/kernel/src/arch/x86_64/driver/apic/x2apic.rs @@ -5,7 +5,7 @@ use x86::msr::{ IA32_X2APIC_VERSION, }; -use crate::{kdebug, kinfo}; +use crate::kinfo; use super::{hw_irq::ApicId, LVTRegister, LocalAPIC, LVT}; @@ -55,9 +55,9 @@ impl LocalAPIC for X2Apic { kinfo!("x2APIC EOI broadcast suppression enabled."); } } - kdebug!("x2apic: to mask all lvt"); + // kdebug!("x2apic: to mask all lvt"); self.mask_all_lvt(); - kdebug!("x2apic: all lvt masked"); + // kdebug!("x2apic: all lvt masked"); } true } diff --git a/kernel/src/driver/base/device/bus.rs b/kernel/src/driver/base/device/bus.rs index 3287aa9bb..a94b1fae3 100644 --- a/kernel/src/driver/base/device/bus.rs +++ b/kernel/src/driver/base/device/bus.rs @@ -147,12 +147,12 @@ pub trait Bus: Debug + Send + Sync { fn resume(&self, device: &Arc) -> Result<(), SystemError>; - /// match platform device to platform driver. + /// match device to driver. /// /// ## 参数 /// - /// * `device` - platform device - /// * `driver` - platform driver + /// * `device` - device + /// * `driver` - driver /// /// ## 返回 /// diff --git a/kernel/src/driver/base/device/dd.rs b/kernel/src/driver/base/device/dd.rs index 96ddb3404..e560cb654 100644 --- a/kernel/src/driver/base/device/dd.rs +++ b/kernel/src/driver/base/device/dd.rs @@ -180,7 +180,7 @@ impl DeviceManager { /// /// 如果传递的设备已成功完成对驱动程序的探测,则返回true,否则返回false。 pub fn device_is_bound(&self, dev: &Arc) -> bool { - return dev.driver().is_some(); + return driver_manager().driver_is_bound(dev); } /// 把一个驱动绑定到设备上 @@ -199,6 +199,11 @@ impl DeviceManager { pub fn device_bind_driver(&self, dev: &Arc) -> Result<(), SystemError> { let r = driver_manager().driver_sysfs_add(dev); if let Err(e) = r { + kerror!( + "device_bind_driver: driver_sysfs_add failed, dev: '{}', err: {:?}", + dev.name(), + e + ); self.device_links_force_bind(dev); driver_manager().driver_bound(dev); return Err(e); @@ -606,7 +611,7 @@ impl Attribute for DeviceAttrStateSynced { } #[derive(Debug)] -struct DeviceAttrCoredump; +pub(super) struct DeviceAttrCoredump; impl Attribute for DeviceAttrCoredump { fn name(&self) -> &str { diff --git a/kernel/src/driver/base/device/driver.rs b/kernel/src/driver/base/device/driver.rs index bedee6fba..0df615e12 100644 --- a/kernel/src/driver/base/device/driver.rs +++ b/kernel/src/driver/base/device/driver.rs @@ -3,10 +3,14 @@ use super::{ Device, DeviceMatchName, DeviceMatcher, IdTable, }; use crate::{ - driver::base::kobject::KObject, + driver::base::{ + device::{bus::BusNotifyEvent, dd::DeviceAttrCoredump, device_manager}, + kobject::KObject, + }, filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup}, }; use alloc::{ + string::ToString, sync::{Arc, Weak}, vec::Vec, }; @@ -226,8 +230,38 @@ impl DriverManager { } /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#434 - pub fn driver_sysfs_add(&self, _dev: &Arc) -> Result<(), SystemError> { - todo!("DriverManager::driver_sysfs_add()"); + pub fn driver_sysfs_add(&self, dev: &Arc) -> Result<(), SystemError> { + if let Some(bus) = dev.bus().and_then(|bus| bus.upgrade()) { + bus.subsystem() + .bus_notifier() + .call_chain(BusNotifyEvent::BindDriver, Some(dev), None); + } + let driver_kobj = dev.driver().unwrap() as Arc; + let device_kobj = dev.clone() as Arc; + + let err_remove_device = |e| { + sysfs_instance().remove_link(&driver_kobj, dev.name()); + Err(e) + }; + + let err_remove_driver = |e| { + sysfs_instance().remove_link(&device_kobj, "driver".to_string()); + err_remove_device(e) + }; + + sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device_kobj.name())?; + + if let Err(e) = + sysfs_instance().create_link(Some(&device_kobj), &driver_kobj, "driver".to_string()) + { + return err_remove_device(e); + } + + if let Err(e) = device_manager().create_file(dev, &DeviceAttrCoredump) { + return err_remove_driver(e); + } + + return Ok(()); } pub fn add_groups( diff --git a/kernel/src/driver/base/subsys.rs b/kernel/src/driver/base/subsys.rs index 34d587f4e..d36989292 100644 --- a/kernel/src/driver/base/subsys.rs +++ b/kernel/src/driver/base/subsys.rs @@ -22,6 +22,7 @@ use super::{ driver::Driver, Device, }, + kobject::KObject, kset::KSet, }; @@ -82,6 +83,10 @@ impl SubSysPrivate { }; } + pub fn name(&self) -> String { + return self.subsys.name(); + } + pub fn subsys(&self) -> Arc { return self.subsys.clone(); } diff --git a/kernel/src/driver/net/e1000e/e1000e_driver.rs b/kernel/src/driver/net/e1000e/e1000e_driver.rs index 9bb816249..92ff60c45 100644 --- a/kernel/src/driver/net/e1000e/e1000e_driver.rs +++ b/kernel/src/driver/net/e1000e/e1000e_driver.rs @@ -4,14 +4,15 @@ use crate::{ arch::rand::rand, driver::{ base::{ - device::{bus::Bus, driver::Driver, Device, IdTable}, + class::Class, + device::{bus::Bus, driver::Driver, Device, DeviceType, IdTable}, kobject::{KObjType, KObject, KObjectState}, }, - net::NetDriver, + net::NetDevice, }, kinfo, libs::spinlock::SpinLock, - net::{generate_iface_id, NET_DRIVERS}, + net::{generate_iface_id, NET_DEVICES}, time::Instant, }; use alloc::{ @@ -205,33 +206,49 @@ impl Debug for E1000EInterface { } } -impl Driver for E1000EInterface { - fn id_table(&self) -> Option { +impl Device for E1000EInterface { + fn dev_type(&self) -> DeviceType { todo!() } - fn add_device(&self, _device: Arc) { + fn id_table(&self) -> IdTable { todo!() } - fn delete_device(&self, _device: &Arc) { + fn set_bus(&self, _bus: Option>) { todo!() } - fn devices(&self) -> alloc::vec::Vec> { + fn set_class(&self, _class: Option>) { todo!() } - fn bus(&self) -> Option> { + fn driver(&self) -> Option> { todo!() } - fn set_bus(&self, _bus: Option>) { + fn set_driver(&self, _driver: Option>) { + todo!() + } + + fn is_dead(&self) -> bool { + todo!() + } + + fn can_match(&self) -> bool { + todo!() + } + + fn set_can_match(&self, _can_match: bool) { + todo!() + } + + fn state_synced(&self) -> bool { todo!() } } -impl NetDriver for E1000EInterface { +impl NetDevice for E1000EInterface { fn mac(&self) -> smoltcp::wire::EthernetAddress { let mac = self.driver.inner.lock().mac_address(); return smoltcp::wire::EthernetAddress::from_bytes(&mac); @@ -347,7 +364,7 @@ pub fn e1000e_driver_init(device: E1000EDevice) { let driver = E1000EDriver::new(device); let iface = E1000EInterface::new(driver); // 将网卡的接口信息注册到全局的网卡接口信息表中 - NET_DRIVERS + NET_DEVICES .write_irqsave() .insert(iface.nic_id(), iface.clone()); kinfo!("e1000e driver init successfully!\tMAC: [{}]", mac); diff --git a/kernel/src/driver/net/mod.rs b/kernel/src/driver/net/mod.rs index e01fa7896..ce1a149ba 100644 --- a/kernel/src/driver/net/mod.rs +++ b/kernel/src/driver/net/mod.rs @@ -4,7 +4,7 @@ use smoltcp::{ wire::{self, EthernetAddress}, }; -use super::base::device::driver::Driver; +use super::base::device::Device; use crate::libs::spinlock::SpinLock; use system_error::SystemError; @@ -13,7 +13,7 @@ pub mod e1000e; pub mod irq_handle; pub mod virtio_net; -pub trait NetDriver: Driver { +pub trait NetDevice: Device { /// @brief 获取网卡的MAC地址 fn mac(&self) -> EthernetAddress; diff --git a/kernel/src/driver/net/virtio_net.rs b/kernel/src/driver/net/virtio_net.rs index 0ff11fbdd..c3e61da48 100644 --- a/kernel/src/driver/net/virtio_net.rs +++ b/kernel/src/driver/net/virtio_net.rs @@ -1,123 +1,206 @@ use core::{ + any::Any, cell::UnsafeCell, fmt::Debug, ops::{Deref, DerefMut}, }; use alloc::{ - string::String, + string::{String, ToString}, sync::{Arc, Weak}, + vec::Vec, }; use smoltcp::{iface, phy, wire}; -use virtio_drivers::{device::net::VirtIONet, transport::Transport}; +use unified_init::macros::unified_init; +use virtio_drivers::device::net::VirtIONet; -use super::NetDriver; +use super::NetDevice; use crate::{ arch::rand::rand, driver::{ base::{ - device::{bus::Bus, driver::Driver, Device, DeviceId, IdTable}, - kobject::{KObjType, KObject, KObjectState}, + class::Class, + device::{ + bus::Bus, + driver::{Driver, DriverCommonData}, + Device, DeviceCommonData, DeviceId, DeviceType, IdTable, + }, + kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState}, + kset::KSet, + }, + virtio::{ + irq::virtio_irq_manager, + sysfs::{virtio_bus, virtio_device_manager, virtio_driver_manager}, + transport::VirtIOTransport, + virtio_impl::HalImpl, + VirtIODevice, VirtIODeviceIndex, VirtIODriver, VIRTIO_VENDOR_ID, }, - virtio::{irq::virtio_irq_manager, virtio_impl::HalImpl, VirtIODevice}, }, exception::{irqdesc::IrqReturn, IrqNumber}, - kerror, kinfo, - libs::spinlock::SpinLock, - net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DRIVERS}, + filesystem::kernfs::KernFSInode, + init::initcall::INITCALL_POSTCORE, + kerror, + libs::{ + rwlock::{RwLockReadGuard, RwLockWriteGuard}, + spinlock::{SpinLock, SpinLockGuard}, + }, + net::{generate_iface_id, net_core::poll_ifaces_try_lock_onetime, NET_DEVICES}, time::Instant, }; use system_error::SystemError; -/// @brief Virtio网络设备驱动(加锁) -pub struct VirtioNICDriver { - pub inner: Arc>>, +static mut VIRTIO_NET_DRIVER: Option> = None; + +const DEVICE_NAME: &str = "virtio_net"; + +#[inline(always)] +fn virtio_net_driver() -> Arc { + unsafe { VIRTIO_NET_DRIVER.as_ref().unwrap().clone() } } -impl Clone for VirtioNICDriver { - fn clone(&self) -> Self { - return VirtioNICDriver { - inner: self.inner.clone(), - }; +pub struct VirtIoNetImpl { + inner: VirtIONet, +} + +impl VirtIoNetImpl { + const fn new(inner: VirtIONet) -> Self { + Self { inner } + } +} + +impl Deref for VirtIoNetImpl { + type Target = VirtIONet; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for VirtIoNetImpl { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner } } -/// 网卡驱动的包裹器,这是为了获取网卡驱动的可变引用而设计的。 -/// -/// 由于smoltcp的设计,导致需要在poll的时候获取网卡驱动的可变引用, -/// 同时需要在token的consume里面获取可变引用。为了避免双重加锁,所以需要这个包裹器。 -struct VirtioNICDriverWrapper(UnsafeCell>); -unsafe impl Send for VirtioNICDriverWrapper {} -unsafe impl Sync for VirtioNICDriverWrapper {} +unsafe impl Send for VirtIoNetImpl {} +unsafe impl Sync for VirtIoNetImpl {} + +#[derive(Debug)] +struct VirtIONicDeviceInnerWrapper(UnsafeCell); +unsafe impl Send for VirtIONicDeviceInnerWrapper {} +unsafe impl Sync for VirtIONicDeviceInnerWrapper {} -impl Deref for VirtioNICDriverWrapper { - type Target = VirtioNICDriver; +impl Deref for VirtIONicDeviceInnerWrapper { + type Target = VirtIONicDeviceInner; fn deref(&self) -> &Self::Target { unsafe { &*self.0.get() } } } -impl DerefMut for VirtioNICDriverWrapper { +impl DerefMut for VirtIONicDeviceInnerWrapper { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *self.0.get() } } } #[allow(clippy::mut_from_ref)] -impl VirtioNICDriverWrapper { - fn force_get_mut(&self) -> &mut VirtioNICDriver { +impl VirtIONicDeviceInnerWrapper { + fn force_get_mut(&self) -> &mut ::Target { unsafe { &mut *self.0.get() } } } -impl Debug for VirtioNICDriver { +/// Virtio网络设备驱动(加锁) +pub struct VirtIONicDeviceInner { + pub inner: Arc>, +} + +impl Clone for VirtIONicDeviceInner { + fn clone(&self) -> Self { + return VirtIONicDeviceInner { + inner: self.inner.clone(), + }; + } +} + +impl Debug for VirtIONicDeviceInner { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("VirtioNICDriver").finish() + f.debug_struct("VirtIONicDriver").finish() } } -pub struct VirtioInterface { - driver: VirtioNICDriverWrapper, +#[cast_to([sync] VirtIODevice)] +pub struct VirtioInterface { + device_inner: VirtIONicDeviceInnerWrapper, iface_id: usize, - iface: SpinLock, - name: String, + iface_name: String, dev_id: Arc, + iface: SpinLock, + inner: SpinLock, + locked_kobj_state: LockedKObjectState, +} + +#[derive(Debug)] +struct InnerVirtIOInterface { + name: Option, + virtio_index: Option, + device_common: DeviceCommonData, + kobj_common: KObjectCommonData, } -impl Debug for VirtioInterface { +impl core::fmt::Debug for VirtioInterface { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("VirtioInterface") - .field("driver", self.driver.deref()) .field("iface_id", &self.iface_id) - .field("iface", &"smoltcp::iface::Interface") - .field("name", &self.name) + .field("iface_name", &self.iface_name) + .field("dev_id", &self.dev_id) + .field("inner", &self.inner) + .field("locked_kobj_state", &self.locked_kobj_state) .finish() } } -impl VirtioInterface { - pub fn new(mut driver: VirtioNICDriver, dev_id: Arc) -> Arc { +impl VirtioInterface { + pub fn new(mut device_inner: VirtIONicDeviceInner, dev_id: Arc) -> Arc { let iface_id = generate_iface_id(); let mut iface_config = iface::Config::new(wire::HardwareAddress::Ethernet( - wire::EthernetAddress(driver.inner.lock().mac_address()), + wire::EthernetAddress(device_inner.inner.lock().mac_address()), )); iface_config.random_seed = rand() as u64; - let iface = iface::Interface::new(iface_config, &mut driver, Instant::now().into()); + let iface = iface::Interface::new(iface_config, &mut device_inner, Instant::now().into()); - let driver: VirtioNICDriverWrapper = VirtioNICDriverWrapper(UnsafeCell::new(driver)); let result = Arc::new(VirtioInterface { - driver, + device_inner: VirtIONicDeviceInnerWrapper(UnsafeCell::new(device_inner)), iface_id, + locked_kobj_state: LockedKObjectState::default(), iface: SpinLock::new(iface), - name: format!("eth{}", iface_id), + iface_name: format!("eth{}", iface_id), dev_id, + inner: SpinLock::new(InnerVirtIOInterface { + name: None, + virtio_index: None, + device_common: DeviceCommonData::default(), + kobj_common: KObjectCommonData::default(), + }), }); + result.inner().device_common.driver = + Some(Arc::downgrade(&virtio_net_driver()) as Weak); + return result; } + + fn inner(&self) -> SpinLockGuard { + return self.inner.lock(); + } + + /// 获取网卡接口的名称 + #[allow(dead_code)] + pub fn iface_name(&self) -> String { + self.iface_name.clone() + } } -impl VirtIODevice for VirtioInterface { +impl VirtIODevice for VirtioInterface { fn handle_irq(&self, _irq: IrqNumber) -> Result { poll_ifaces_try_lock_onetime().ok(); return Ok(IrqReturn::Handled); @@ -126,46 +209,133 @@ impl VirtIODevice for VirtioInterface { fn dev_id(&self) -> &Arc { return &self.dev_id; } + fn set_virtio_device_index(&self, index: VirtIODeviceIndex) { + self.inner().virtio_index = Some(index); + } + + fn virtio_device_index(&self) -> Option { + return self.inner().virtio_index; + } + + 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_net".to_string()) + } + + fn device_type_id(&self) -> u32 { + virtio_drivers::transport::DeviceType::Network as u32 + } + + fn vendor(&self) -> u32 { + VIRTIO_VENDOR_ID.into() + } } -impl Drop for VirtioInterface { +impl Drop for VirtioInterface { fn drop(&mut self) { // 从全局的网卡接口信息表中删除这个网卡的接口信息 - NET_DRIVERS.write_irqsave().remove(&self.iface_id); + NET_DEVICES.write_irqsave().remove(&self.iface_id); + } +} + +impl Device for VirtioInterface { + fn dev_type(&self) -> DeviceType { + DeviceType::Net + } + + fn id_table(&self) -> IdTable { + IdTable::new(DEVICE_NAME.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 { + true + } + + fn set_can_match(&self, can_match: bool) { + self.inner().device_common.can_match = can_match; + } + + fn state_synced(&self) -> bool { + true } } -impl VirtioNICDriver { - pub fn new(driver_net: VirtIONet) -> Self { +impl VirtIONicDeviceInner { + pub fn new(driver_net: VirtIONet) -> Self { let mut iface_config = iface::Config::new(wire::HardwareAddress::Ethernet( wire::EthernetAddress(driver_net.mac_address()), )); iface_config.random_seed = rand() as u64; - let inner: Arc>> = Arc::new(SpinLock::new(driver_net)); - let result = VirtioNICDriver { inner }; + let inner = Arc::new(SpinLock::new(VirtIoNetImpl::new(driver_net))); + let result = VirtIONicDeviceInner { inner }; return result; } } -pub struct VirtioNetToken { - driver: VirtioNICDriver, +pub struct VirtioNetToken { + driver: VirtIONicDeviceInner, rx_buffer: Option, } -impl VirtioNetToken { +impl VirtioNetToken { pub fn new( - driver: VirtioNICDriver, + driver: VirtIONicDeviceInner, rx_buffer: Option, ) -> Self { return Self { driver, rx_buffer }; } } -impl phy::Device for VirtioNICDriver { - type RxToken<'a> = VirtioNetToken where Self: 'a; - type TxToken<'a> = VirtioNetToken where Self: 'a; +impl phy::Device for VirtIONicDeviceInner { + type RxToken<'a> = VirtioNetToken where Self: 'a; + type TxToken<'a> = VirtioNetToken where Self: 'a; fn receive( &mut self, @@ -206,13 +376,12 @@ impl phy::Device for VirtioNICDriver { } } -impl phy::TxToken for VirtioNetToken { +impl phy::TxToken for VirtioNetToken { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { // // 为了线程安全,这里需要对VirtioNet进行加【写锁】,以保证对设备的互斥访问。 - let mut driver_net = self.driver.inner.lock(); let mut tx_buf = driver_net.new_tx_buffer(len); let result = f(tx_buf.packet_mut()); @@ -221,7 +390,7 @@ impl phy::TxToken for VirtioNetToken { } } -impl phy::RxToken for VirtioNetToken { +impl phy::RxToken for VirtioNetToken { fn consume(self, f: F) -> R where F: FnOnce(&mut [u8]) -> R, @@ -239,9 +408,9 @@ impl phy::RxToken for VirtioNetToken { } /// @brief virtio-net 驱动的初始化与测试 -pub fn virtio_net(transport: T, dev_id: Arc) { - let driver_net: VirtIONet = - match VirtIONet::::new(transport, 4096) { +pub fn virtio_net(transport: VirtIOTransport, dev_id: Arc) { + let driver_net: VirtIONet = + match VirtIONet::::new(transport, 4096) { Ok(net) => net, Err(_) => { kerror!("VirtIONet init failed"); @@ -249,53 +418,17 @@ pub fn virtio_net(transport: T, dev_id: Arc) { } }; let mac = wire::EthernetAddress::from_bytes(&driver_net.mac_address()); - let driver: VirtioNICDriver = VirtioNICDriver::new(driver_net); - let iface = VirtioInterface::new(driver, dev_id); - let name = iface.name.clone(); - // 将网卡的接口信息注册到全局的网卡接口信息表中 - NET_DRIVERS - .write_irqsave() - .insert(iface.nic_id(), iface.clone()); - - virtio_irq_manager() - .register_device(iface.clone()) - .expect("Register virtio net failed"); - kinfo!( - "Virtio-net driver init successfully!\tNetDevID: [{}], MAC: [{}]", - name, - mac - ); -} - -impl Driver for VirtioInterface { - fn id_table(&self) -> Option { - todo!() - } - - fn add_device(&self, _device: Arc) { - todo!() - } - - fn delete_device(&self, _device: &Arc) { - todo!() - } - - fn devices(&self) -> alloc::vec::Vec> { - todo!() - } - - fn bus(&self) -> Option> { - todo!() - } - - fn set_bus(&self, _bus: Option>) { - todo!() - } + let dev_inner = VirtIONicDeviceInner::new(driver_net); + let iface = VirtioInterface::new(dev_inner, dev_id); + kdebug!("To add virtio net: {}, mac: {}", iface.device_name(), mac); + virtio_device_manager() + .device_add(iface.clone() as Arc) + .expect("Add virtio net failed"); } -impl NetDriver for VirtioInterface { +impl NetDevice for VirtioInterface { fn mac(&self) -> wire::EthernetAddress { - let mac: [u8; 6] = self.driver.inner.lock().mac_address(); + let mac: [u8; 6] = self.device_inner.inner.lock().mac_address(); return wire::EthernetAddress::from_bytes(&mac); } @@ -306,7 +439,7 @@ impl NetDriver for VirtioInterface { #[inline] fn name(&self) -> String { - return self.name.clone(); + return self.iface_name.clone(); } fn update_ip_addrs(&self, ip_addrs: &[wire::IpCidr]) -> Result<(), SystemError> { @@ -331,7 +464,7 @@ impl NetDriver for VirtioInterface { fn poll(&self, sockets: &mut iface::SocketSet) -> Result<(), SystemError> { let timestamp: smoltcp::time::Instant = Instant::now().into(); let mut guard = self.iface.lock(); - let poll_res = guard.poll(timestamp, self.driver.force_get_mut(), sockets); + let poll_res = guard.poll(timestamp, self.device_inner.force_get_mut(), sockets); // todo: notify!!! // kdebug!("Virtio Interface poll:{poll_res}"); if poll_res { @@ -349,71 +482,235 @@ impl NetDriver for VirtioInterface { // } } -impl KObject for VirtioInterface { +impl KObject for VirtioInterface { fn as_any_ref(&self) -> &dyn core::any::Any { self } - fn set_inode(&self, _inode: Option>) { - todo!() + fn set_inode(&self, inode: Option>) { + self.inner().kobj_common.kern_inode = inode; } - fn inode(&self) -> Option> { - todo!() + fn inode(&self) -> Option> { + self.inner().kobj_common.kern_inode.clone() } - fn parent(&self) -> Option> { - todo!() + fn parent(&self) -> Option> { + self.inner().kobj_common.parent.clone() } - fn set_parent(&self, _parent: Option>) { - todo!() + fn set_parent(&self, parent: Option>) { + self.inner().kobj_common.parent = parent; } - fn kset(&self) -> Option> { - todo!() + fn kset(&self) -> Option> { + self.inner().kobj_common.kset.clone() } - fn set_kset(&self, _kset: Option>) { - todo!() + fn set_kset(&self, kset: Option>) { + self.inner().kobj_common.kset = kset; } - fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> { - todo!() + fn kobj_type(&self) -> Option<&'static dyn KObjType> { + self.inner().kobj_common.kobj_type } fn name(&self) -> String { - self.name.clone() + self.device_name() } fn set_name(&self, _name: String) { - todo!() + // do nothing + } + + fn kobj_state(&self) -> RwLockReadGuard { + self.locked_kobj_state.read() + } + + fn kobj_state_mut(&self) -> RwLockWriteGuard { + self.locked_kobj_state.write() } - fn kobj_state( - &self, - ) -> crate::libs::rwlock::RwLockReadGuard { - todo!() + 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().kobj_common.kobj_type = ktype; + } +} + +#[unified_init(INITCALL_POSTCORE)] +fn virtio_net_driver_init() -> Result<(), SystemError> { + let driver = VirtIONetDriver::new(); + virtio_driver_manager() + .register(driver.clone() as Arc) + .expect("Add virtio net driver failed"); + unsafe { + VIRTIO_NET_DRIVER = Some(driver); } - fn kobj_state_mut( - &self, - ) -> crate::libs::rwlock::RwLockWriteGuard { - todo!() + return Ok(()); +} +#[derive(Debug)] +#[cast_to([sync] VirtIODriver)] +struct VirtIONetDriver { + inner: SpinLock, + kobj_state: LockedKObjectState, +} + +impl VirtIONetDriver { + pub fn new() -> Arc { + let inner = InnerVirtIODriver { + driver_common: DriverCommonData::default(), + kobj_common: KObjectCommonData::default(), + }; + Arc::new(VirtIONetDriver { + inner: SpinLock::new(inner), + kobj_state: LockedKObjectState::default(), + }) } - fn set_kobj_state(&self, _state: KObjectState) { - todo!() + fn inner(&self) -> SpinLockGuard { + return self.inner.lock(); } +} - fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) { - todo!() +#[derive(Debug)] +struct InnerVirtIODriver { + driver_common: DriverCommonData, + kobj_common: KObjectCommonData, +} + +impl VirtIODriver for VirtIONetDriver { + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + let iface = device + .clone() + .arc_any() + .downcast::() + .map_err(|_| { + kerror!( + "VirtIONetDriver::probe() failed: device is not a VirtioInterface. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + + // 将网卡的接口信息注册到全局的网卡接口信息表中 + NET_DEVICES + .write_irqsave() + .insert(iface.nic_id(), iface.clone()); + + virtio_irq_manager() + .register_device(iface.clone()) + .expect("Register virtio net failed"); + + return Ok(()); } } -// 向编译器保证,VirtioNICDriver在线程之间是安全的. -// 由于smoltcp只会在token内真正操作网卡设备,并且在VirtioNetToken的consume -// 方法内,会对VirtioNet进行加【写锁】,因此,能够保证对设备操作的的互斥访问, -// 因此VirtioNICDriver在线程之间是安全的。 -// unsafe impl Sync for VirtioNICDriver {} -// unsafe impl Send for VirtioNICDriver {} +impl Driver for VirtIONetDriver { + fn id_table(&self) -> Option { + Some(IdTable::new(DEVICE_NAME.to_string(), None)) + } + + fn add_device(&self, device: Arc) { + let iface = device + .arc_any() + .downcast::() + .expect("VirtIONetDriver::add_device() failed: device is not a VirtioInterface"); + + self.inner() + .driver_common + .devices + .push(iface as Arc); + } + + fn delete_device(&self, device: &Arc) { + let _iface = device + .clone() + .arc_any() + .downcast::() + .expect("VirtIONetDriver::delete_device() failed: device is not a VirtioInterface"); + + let mut guard = self.inner(); + let index = guard + .driver_common + .devices + .iter() + .position(|dev| Arc::ptr_eq(device, dev)) + .expect("VirtIONetDriver::delete_device() failed: device not found"); + + guard.driver_common.devices.remove(index); + } + + 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 VirtIONetDriver { + 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 { + DEVICE_NAME.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; + } +} diff --git a/kernel/src/driver/pci/pci.rs b/kernel/src/driver/pci/pci.rs index 2e6cb53c3..6e1cdef1a 100644 --- a/kernel/src/driver/pci/pci.rs +++ b/kernel/src/driver/pci/pci.rs @@ -95,11 +95,45 @@ impl PciDeviceLinkedList { } } -/// @brief 在链表中寻找满足条件的PCI设备结构体并返回其可变引用 -/// @param list 链表的写锁守卫 -/// @param class_code 寄存器值 -/// @param subclass 寄存器值,与class_code一起确定设备类型 -/// @return Vec<&'a mut Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的可变引用的容器 +/// # 获取具有特定供应商ID的PCI设备结构的引用 +/// +/// 这个函数通过供应商ID搜索PCI设备结构列表,并返回匹配该ID的所有设备结构的引用。 +/// +/// ## 参数 +/// +/// - list: 一个可变的PCI设备结构链表,类型为`&'a mut RwLockWriteGuard<'_, LinkedList>>`。 +/// - vendor_id: 要查找的PCI供应商ID,类型为`u16`。 +/// +/// ## 返回值 +/// +/// - 返回匹配的供应商ID的PCI设备结构的引用。 +pub fn get_pci_device_structures_mut_by_vendor_id<'a>( + list: &'a mut RwLockWriteGuard<'_, LinkedList>>, + vendor_id: u16, +) -> Vec<&'a mut Box<(dyn PciDeviceStructure)>> { + let mut result = Vec::new(); + for box_pci_device_structure in list.iter_mut() { + let common_header = (*box_pci_device_structure).common_header(); + if common_header.vendor_id == vendor_id { + result.push(box_pci_device_structure); + } + } + result +} + +/// # get_pci_device_structure_mut - 在链表中寻找满足条件的PCI设备结构体并返回其可变引用 +/// +/// 该函数遍历给定的PCI设备链表,寻找其common_header中class_code和subclass字段与给定值匹配的设备结构体。 +/// 对于每一个匹配的设备结构体,函数返回一个可变引用。 +/// +/// ## 参数 +/// +/// - list: &'a mut RwLockWriteGuard<'_, LinkedList>> — 链表的写锁守卫,用于访问和遍历PCI设备链表。 +/// - class_code: u8 — PCI设备class code寄存器值,用于分类设备的功能。 +/// - subclass: u8 — PCI设备subclass寄存器值,与class_code一起确定设备的子类型。 +/// +/// ## 返回值 +/// - 包含链表中所有满足条件的PCI结构体的可变引用的容器。 pub fn get_pci_device_structure_mut<'a>( list: &'a mut RwLockWriteGuard<'_, LinkedList>>, class_code: u8, @@ -114,11 +148,20 @@ pub fn get_pci_device_structure_mut<'a>( } result } -/// @brief 在链表中寻找满足条件的PCI设备结构体并返回其不可变引用 -/// @param list 链表的读锁守卫 -/// @param class_code 寄存器值 -/// @param subclass 寄存器值,与class_code一起确定设备类型 -/// @return Vec<&'a Box<(dyn PciDeviceStructure) 包含链表中所有满足条件的PCI结构体的不可变引用的容器 + +/// # get_pci_device_structure - 在链表中寻找满足条件的PCI设备结构体并返回其不可变引用 +/// +/// 该函数遍历给定的PCI设备链表,寻找其common_header中class_code和subclass字段与给定值匹配的设备结构体。 +/// 对于每一个匹配的设备结构体,函数返回一个可变引用。 +/// +/// ## 参数 +/// +/// - list: &'a mut RwLockWriteGuard<'_, LinkedList>> — 链表的写锁守卫,用于访问和遍历PCI设备链表。 +/// - class_code: u8 — PCI设备class code寄存器值,用于分类设备的功能。 +/// - subclass: u8 — PCI设备subclass寄存器值,与class_code一起确定设备的子类型。 +/// +/// ## 返回值 +/// - 包含链表中所有满足条件的PCI结构体的不可变引用的容器。 #[allow(clippy::borrowed_box)] pub fn get_pci_device_structure<'a>( list: &'a mut RwLockReadGuard<'_, LinkedList>>, diff --git a/kernel/src/driver/serial/serial8250/mod.rs b/kernel/src/driver/serial/serial8250/mod.rs index ac31c1da7..48c82c07f 100644 --- a/kernel/src/driver/serial/serial8250/mod.rs +++ b/kernel/src/driver/serial/serial8250/mod.rs @@ -94,6 +94,10 @@ impl Serial8250Manager { // todo: 把驱动注册到uart层、tty层 uart_manager().register_driver(&(serial8250_isa_driver.clone() as Arc))?; + // 把驱动注册到platform总线 + platform_driver_manager() + .register(serial8250_isa_driver.clone() as Arc)?; + // 注册isa设备到platform总线 platform_device_manager() .device_add(serial8250_isa_dev.clone() as Arc) @@ -104,10 +108,6 @@ impl Serial8250Manager { return e; })?; - // 把驱动注册到platform总线 - platform_driver_manager() - .register(serial8250_isa_driver.clone() as Arc)?; - unsafe { INITIALIZED = true; } diff --git a/kernel/src/driver/virtio/mmio.rs b/kernel/src/driver/virtio/mmio.rs new file mode 100644 index 000000000..e7fa507e4 --- /dev/null +++ b/kernel/src/driver/virtio/mmio.rs @@ -0,0 +1,3 @@ +pub(super) fn virtio_probe_mmio() { + // todo: implement virtio_probe_mmio +} diff --git a/kernel/src/driver/virtio/mod.rs b/kernel/src/driver/virtio/mod.rs index 2aaa406eb..b069be82e 100644 --- a/kernel/src/driver/virtio/mod.rs +++ b/kernel/src/driver/virtio/mod.rs @@ -1,20 +1,44 @@ -use core::any::Any; - -use alloc::sync::Arc; +use alloc::{string::String, sync::Arc}; use system_error::SystemError; use crate::exception::{irqdesc::IrqReturn, IrqNumber}; -use super::base::device::DeviceId; +use super::base::device::{driver::Driver, Device, DeviceId}; pub(super) mod irq; +pub mod mmio; +pub mod sysfs; +pub mod transport; pub mod transport_pci; #[allow(clippy::module_inception)] pub mod virtio; pub mod virtio_impl; -pub trait VirtIODevice: Send + Sync + Any { +/// virtio 设备厂商ID +pub const VIRTIO_VENDOR_ID: u16 = 0x1af4; + +pub trait VirtIODevice: Device { fn handle_irq(&self, _irq: IrqNumber) -> Result; fn dev_id(&self) -> &Arc; + + fn set_device_name(&self, name: String); + + fn device_name(&self) -> String; + + fn set_virtio_device_index(&self, index: VirtIODeviceIndex); + + fn virtio_device_index(&self) -> Option; + + /// virtio 设备类型 + fn device_type_id(&self) -> u32; + + /// virtio 设备厂商 + fn vendor(&self) -> u32; } + +pub trait VirtIODriver: Driver { + fn probe(&self, device: &Arc) -> Result<(), SystemError>; +} + +int_like!(VirtIODeviceIndex, usize); diff --git a/kernel/src/driver/virtio/sysfs.rs b/kernel/src/driver/virtio/sysfs.rs new file mode 100644 index 000000000..25e434e46 --- /dev/null +++ b/kernel/src/driver/virtio/sysfs.rs @@ -0,0 +1,295 @@ +use alloc::{ + string::{String, ToString}, + sync::{Arc, Weak}, +}; +use ida::IdAllocator; +use intertrait::cast::CastArc; +use system_error::SystemError; +use unified_init::macros::unified_init; + +use crate::{ + driver::base::{ + device::{ + bus::{bus_manager, Bus}, + device_manager, + driver::{driver_manager, Driver}, + Device, + }, + kobject::KObject, + subsys::SubSysPrivate, + }, + filesystem::{ + sysfs::{ + file::sysfs_emit_str, Attribute, AttributeGroup, SysFSOpsSupport, SYSFS_ATTR_MODE_RO, + }, + vfs::syscall::ModeType, + }, + init::initcall::INITCALL_CORE, +}; + +use super::{VirtIODevice, VirtIODeviceIndex, VirtIODriver}; + +static mut VIRTIO_BUS: Option> = None; + +#[inline(always)] +pub fn virtio_bus() -> Arc { + unsafe { VIRTIO_BUS.as_ref().unwrap().clone() } +} + +#[derive(Debug)] +pub struct VirtIOBus { + private: SubSysPrivate, +} + +impl VirtIOBus { + pub fn new() -> Arc { + let w: Weak = Weak::new(); + let private = SubSysPrivate::new("virtio".to_string(), Some(w), None, &[]); + let bus = Arc::new(Self { private }); + bus.subsystem() + .set_bus(Some(Arc::downgrade(&(bus.clone() as Arc)))); + + return bus; + } +} + +impl Bus for VirtIOBus { + fn name(&self) -> String { + self.private.name() + } + + fn dev_name(&self) -> String { + return self.name(); + } + + fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] { + // todo: VirtIODeviceAttrGroup + return &[]; + } + + fn subsystem(&self) -> &SubSysPrivate { + return &self.private; + } + + fn probe(&self, device: &Arc) -> Result<(), SystemError> { + let drv = device.driver().ok_or(SystemError::EINVAL)?; + let virtio_drv = drv.cast::().map_err(|_| { + kerror!( + "VirtIOBus::probe() failed: device.driver() is not a VirtioDriver. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + + let virtio_dev = device.clone().cast::().map_err(|_| { + kerror!( + "VirtIOBus::probe() failed: device is not a VirtIODevice. Device: '{:?}'", + device.name() + ); + SystemError::EINVAL + })?; + + return virtio_drv.probe(&virtio_dev); + } + + fn remove(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn sync_state(&self, _device: &Arc) { + todo!() + } + + fn shutdown(&self, _device: &Arc) { + todo!() + } + + fn resume(&self, _device: &Arc) -> Result<(), SystemError> { + todo!() + } + + fn match_device( + &self, + _device: &Arc, + _driver: &Arc, + ) -> Result { + // todo: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/virtio/virtio.c#85 + todo!("VirtIOBus::match_device() is not implemented") + } +} + +#[unified_init(INITCALL_CORE)] +fn virtio_init() -> Result<(), SystemError> { + let bus = VirtIOBus::new(); + unsafe { + VIRTIO_BUS = Some(bus.clone()); + } + bus_manager() + .register(bus) + .expect("Failed to register virtio bus!"); + Ok(()) +} + +#[inline(always)] +pub fn virtio_driver_manager() -> &'static VirtIODriverManager { + &VirtIODriverManager +} + +pub struct VirtIODriverManager; + +impl VirtIODriverManager { + pub fn register(&self, driver: Arc) -> Result<(), SystemError> { + driver.set_bus(Some(Arc::downgrade(&(virtio_bus() as Arc)))); + return driver_manager().register(driver as Arc); + } + + #[allow(dead_code)] + pub fn unregister(&self, driver: &Arc) { + driver_manager().unregister(&(driver.clone() as Arc)); + } +} + +#[inline(always)] +pub fn virtio_device_manager() -> &'static VirtIODeviceManager { + &VirtIODeviceManager +} + +pub struct VirtIODeviceManager; + +impl VirtIODeviceManager { + pub fn device_add(&self, dev: Arc) -> Result<(), SystemError> { + dev.set_bus(Some(Arc::downgrade(&(virtio_bus() as Arc)))); + device_manager().device_default_initialize(&(dev.clone() as Arc)); + let drv = dev.driver().ok_or(SystemError::EINVAL)?; + + let virtio_drv = drv.cast::().map_err(|_| { + kerror!( + "VirtIODeviceManager::device_add() failed: device.driver() is not a VirtioDriver. Device: '{:?}'", + dev.name() + ); + SystemError::EINVAL + })?; + let virtio_index = VIRTIO_DEVICE_INDEX_MANAGER.alloc(); + dev.set_virtio_device_index(virtio_index); + dev.set_device_name(format!("virtio{}", virtio_index.data())); + virtio_drv.probe(&dev)?; + + device_manager().add_device(dev.clone() as Arc)?; + device_manager().add_groups(&(dev as Arc), &[&VirtIODeviceAttrGroup]) + } + + #[allow(dead_code)] + pub fn device_remove(&self, dev: &Arc) -> Result<(), SystemError> { + device_manager().remove(&(dev.clone() as Arc)); + return Ok(()); + } +} + +static VIRTIO_DEVICE_INDEX_MANAGER: VirtIODeviceIndexManager = VirtIODeviceIndexManager::new(); + +/// VirtIO设备索引管理器 +/// +/// VirtIO设备索引管理器用于分配和管理VirtIO设备的唯一索引。 +pub struct VirtIODeviceIndexManager { + // ID分配器 + /// + /// ID分配器用于分配唯一的索引给VirtIO设备。 + ida: IdAllocator, +} + +// VirtIO设备索引管理器的新建实例 +impl VirtIODeviceIndexManager { + /// 创建新的VirtIO设备索引管理器实例 + /// + /// 创建一个新的VirtIO设备索引管理器实例,初始时分配器从0开始,直到最大usize值。 + const fn new() -> Self { + Self { + ida: IdAllocator::new(0, usize::MAX), + } + } + + /// 分配一个新的VirtIO设备索引 + /// + /// 分配一个唯一的索引给VirtIO设备。 + pub fn alloc(&self) -> VirtIODeviceIndex { + VirtIODeviceIndex(self.ida.alloc().unwrap()) + } + + // 释放一个VirtIO设备索引 + /// + /// 释放之前分配的VirtIO设备索引,使其可以被重新使用。 + #[allow(dead_code)] + pub fn free(&self, index: VirtIODeviceIndex) { + self.ida.free(index.0); + } +} + +/// VirtIO设备属性组 +/// +/// 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/virtio/virtio.c#64 +#[derive(Debug)] +pub struct VirtIODeviceAttrGroup; + +impl AttributeGroup for VirtIODeviceAttrGroup { + fn name(&self) -> Option<&str> { + None + } + + fn attrs(&self) -> &[&'static dyn Attribute] { + &[&AttrDevice, &AttrVendor] + } +} + +#[derive(Debug)] +struct AttrDevice; + +impl Attribute for AttrDevice { + fn name(&self) -> &str { + "device" + } + + fn mode(&self) -> ModeType { + SYSFS_ATTR_MODE_RO + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW + } + + fn show(&self, kobj: Arc, buf: &mut [u8]) -> Result { + let dev = kobj.cast::().map_err(|_| { + kerror!("AttrDevice::show() failed: kobj is not a VirtIODevice"); + SystemError::EINVAL + })?; + let device_type_id = dev.device_type_id(); + + return sysfs_emit_str(buf, &format!("0x{:04x}\n", device_type_id)); + } +} + +#[derive(Debug)] +struct AttrVendor; + +impl Attribute for AttrVendor { + fn name(&self) -> &str { + "vendor" + } + + fn mode(&self) -> ModeType { + SYSFS_ATTR_MODE_RO + } + + fn support(&self) -> SysFSOpsSupport { + SysFSOpsSupport::ATTR_SHOW + } + + fn show(&self, kobj: Arc, buf: &mut [u8]) -> Result { + let dev = kobj.cast::().map_err(|_| { + kerror!("AttrVendor::show() failed: kobj is not a VirtIODevice"); + SystemError::EINVAL + })?; + let vendor = dev.vendor(); + + return sysfs_emit_str(buf, &format!("0x{:04x}\n", vendor)); + } +} diff --git a/kernel/src/driver/virtio/transport.rs b/kernel/src/driver/virtio/transport.rs new file mode 100644 index 000000000..72cf0ba6e --- /dev/null +++ b/kernel/src/driver/virtio/transport.rs @@ -0,0 +1,131 @@ +use virtio_drivers::transport::Transport; + +use super::transport_pci::PciTransport; + +pub enum VirtIOTransport { + Pci(PciTransport), +} + +impl core::fmt::Debug for VirtIOTransport { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + VirtIOTransport::Pci(_) => write!(f, "VirtIOTransport::Pci"), + } + } +} + +impl Transport for VirtIOTransport { + #[inline(always)] + fn finish_init(&mut self) { + match self { + VirtIOTransport::Pci(transport) => transport.finish_init(), + } + } + + #[inline(always)] + fn device_type(&self) -> virtio_drivers::transport::DeviceType { + match self { + VirtIOTransport::Pci(transport) => transport.device_type(), + } + } + + #[inline(always)] + fn read_device_features(&mut self) -> u64 { + match self { + VirtIOTransport::Pci(transport) => transport.read_device_features(), + } + } + + #[inline(always)] + fn write_driver_features(&mut self, driver_features: u64) { + match self { + VirtIOTransport::Pci(transport) => transport.write_driver_features(driver_features), + } + } + + #[inline(always)] + fn max_queue_size(&mut self, queue: u16) -> u32 { + match self { + VirtIOTransport::Pci(transport) => transport.max_queue_size(queue), + } + } + + #[inline(always)] + fn notify(&mut self, queue: u16) { + match self { + VirtIOTransport::Pci(transport) => transport.notify(queue), + } + } + + #[inline(always)] + fn get_status(&self) -> virtio_drivers::transport::DeviceStatus { + match self { + VirtIOTransport::Pci(transport) => transport.get_status(), + } + } + + #[inline(always)] + fn set_status(&mut self, status: virtio_drivers::transport::DeviceStatus) { + match self { + VirtIOTransport::Pci(transport) => transport.set_status(status), + } + } + + #[inline(always)] + fn set_guest_page_size(&mut self, guest_page_size: u32) { + match self { + VirtIOTransport::Pci(transport) => transport.set_guest_page_size(guest_page_size), + } + } + + #[inline(always)] + fn requires_legacy_layout(&self) -> bool { + match self { + VirtIOTransport::Pci(transport) => transport.requires_legacy_layout(), + } + } + + #[inline(always)] + fn queue_set( + &mut self, + queue: u16, + size: u32, + descriptors: virtio_drivers::PhysAddr, + driver_area: virtio_drivers::PhysAddr, + device_area: virtio_drivers::PhysAddr, + ) { + match self { + VirtIOTransport::Pci(transport) => { + transport.queue_set(queue, size, descriptors, driver_area, device_area) + } + } + } + + #[inline(always)] + fn queue_unset(&mut self, queue: u16) { + match self { + VirtIOTransport::Pci(transport) => transport.queue_unset(queue), + } + } + + #[inline(always)] + fn queue_used(&mut self, queue: u16) -> bool { + match self { + VirtIOTransport::Pci(transport) => transport.queue_used(queue), + } + } + + #[inline(always)] + fn ack_interrupt(&mut self) -> bool { + match self { + VirtIOTransport::Pci(transport) => transport.ack_interrupt(), + } + } + + #[inline(always)] + fn config_space(&self) -> virtio_drivers::Result> { + match self { + VirtIOTransport::Pci(transport) => transport.config_space(), + } + } +} diff --git a/kernel/src/driver/virtio/transport_pci.rs b/kernel/src/driver/virtio/transport_pci.rs index ab6fee4bb..fc0010526 100644 --- a/kernel/src/driver/virtio/transport_pci.rs +++ b/kernel/src/driver/virtio/transport_pci.rs @@ -32,9 +32,7 @@ use virtio_drivers::{ Error, Hal, PhysAddr, }; -/// The PCI vendor ID for VirtIO devices. -/// PCI Virtio设备的vendor ID -const VIRTIO_VENDOR_ID: u16 = 0x1af4; +use super::VIRTIO_VENDOR_ID; /// The offset to add to a VirtIO device ID to get the corresponding PCI device ID. /// PCI Virtio设备的DEVICE_ID 的offset diff --git a/kernel/src/driver/virtio/virtio.rs b/kernel/src/driver/virtio/virtio.rs index 0f6b179da..db32787e1 100644 --- a/kernel/src/driver/virtio/virtio.rs +++ b/kernel/src/driver/virtio/virtio.rs @@ -1,53 +1,51 @@ +use super::mmio::virtio_probe_mmio; use super::transport_pci::PciTransport; use super::virtio_impl::HalImpl; use crate::driver::base::device::DeviceId; use crate::driver::net::virtio_net::virtio_net; use crate::driver::pci::pci::{ - get_pci_device_structure_mut, PciDeviceStructure, PciDeviceStructureGeneralDevice, - PCI_DEVICE_LINKEDLIST, + get_pci_device_structures_mut_by_vendor_id, PciDeviceStructure, + PciDeviceStructureGeneralDevice, PCI_DEVICE_LINKEDLIST, }; +use crate::driver::virtio::transport::VirtIOTransport; use crate::libs::rwlock::RwLockWriteGuard; use crate::{kdebug, kerror, kwarn}; use alloc::sync::Arc; +use alloc::vec::Vec; use alloc::{boxed::Box, collections::LinkedList}; use virtio_drivers::transport::{DeviceType, Transport}; -const NETWORK_CLASS: u8 = 0x2; -const ETHERNET_SUBCLASS: u8 = 0x0; - -//Virtio设备寻找过程中出现的问题 -enum VirtioError { - VirtioNetNotFound, - NetDeviceNotFound, -} ///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加) pub fn virtio_probe() { + virtio_probe_pci(); + virtio_probe_mmio(); +} + +fn virtio_probe_pci() { let mut list = PCI_DEVICE_LINKEDLIST.write(); - if let Ok(virtio_list) = virtio_device_search(&mut list) { - for virtio_device in virtio_list { - let dev_id = virtio_device.common_header.device_id; - let dev_id = DeviceId::new(None, Some(format!("virtio_{}", dev_id))).unwrap(); - match PciTransport::new::(virtio_device, dev_id.clone()) { - Ok(mut transport) => { - kdebug!( - "Detected virtio PCI device with device type {:?}, features {:#018x}", - transport.device_type(), - transport.read_device_features(), - ); - virtio_device_init(transport, dev_id); - } - Err(err) => { - kerror!("Pci transport create failed because of error: {}", err); - } + let virtio_list = virtio_device_search(&mut list); + for virtio_device in virtio_list { + let dev_id = virtio_device.common_header.device_id; + let dev_id = DeviceId::new(None, Some(format!("{dev_id}"))).unwrap(); + match PciTransport::new::(virtio_device, dev_id.clone()) { + Ok(mut transport) => { + kdebug!( + "Detected virtio PCI device with device type {:?}, features {:#018x}", + transport.device_type(), + transport.read_device_features(), + ); + let transport = VirtIOTransport::Pci(transport); + virtio_device_init(transport, dev_id); + } + Err(err) => { + kerror!("Pci transport create failed because of error: {}", err); } } - } else { - kerror!("Error occured when finding virtio device!"); } } ///@brief 为virtio设备寻找对应的驱动进行初始化 -fn virtio_device_init(transport: impl Transport + 'static, dev_id: Arc) { +fn virtio_device_init(transport: VirtIOTransport, dev_id: Arc) { match transport.device_type() { DeviceType::Block => { kwarn!("Not support virtio_block device for now"); @@ -65,39 +63,30 @@ fn virtio_device_init(transport: impl Transport + 'static, dev_id: Arc } } -/// @brief 寻找所有的virtio设备 -/// @param list 链表的写锁 -/// @return Result, VirtioError> 成功则返回包含所有virtio设备结构体的可变引用的链表,失败则返回err -/// 该函数主要是为其他virtio设备预留支持 +/// # virtio_device_search - 在给定的PCI设备列表中搜索符合特定标准的virtio设备 +/// +/// 该函数搜索一个PCI设备列表,找到所有由特定厂商ID(0x1AF4)和设备ID范围(0x1000至0x103F)定义的virtio设备。 +/// +/// ## 参数 +/// +/// - list: &'a mut RwLockWriteGuard<'_, LinkedList>> - 一个可写的PCI设备结构列表的互斥锁。 +/// +/// ## 返回值 +/// +/// 返回一个包含所有找到的virtio设备的数组 fn virtio_device_search<'a>( list: &'a mut RwLockWriteGuard<'_, LinkedList>>, -) -> Result, VirtioError> { - let mut virtio_list: LinkedList<&mut PciDeviceStructureGeneralDevice> = LinkedList::new(); - let virtio_net_device = get_virtio_net_device(list)?; - virtio_list.push_back(virtio_net_device); - Ok(virtio_list) -} +) -> Vec<&'a mut PciDeviceStructureGeneralDevice> { + let mut virtio_list = Vec::new(); + let result = get_pci_device_structures_mut_by_vendor_id(list, 0x1AF4); -/// @brief 寻找virtio-net设备 -/// @param list 链表的写锁 -/// @return Result<&'a mut Pci_Device_Structure_General_Device, VirtioError> 成功则返回virtio设备结构体的可变引用,失败则返回err -fn get_virtio_net_device<'a>( - list: &'a mut RwLockWriteGuard<'_, LinkedList>>, -) -> Result<&'a mut PciDeviceStructureGeneralDevice, VirtioError> { - let result = get_pci_device_structure_mut(list, NETWORK_CLASS, ETHERNET_SUBCLASS); - if result.is_empty() { - return Err(VirtioError::NetDeviceNotFound); - } for device in result { let standard_device = device.as_standard_device_mut().unwrap(); let header = &standard_device.common_header; - if header.vendor_id == 0x1AF4 - && header.device_id >= 0x1000 - && header.device_id <= 0x103F - && standard_device.subsystem_id == 1 - { - return Ok(standard_device); + if header.device_id >= 0x1000 && header.device_id <= 0x103F { + virtio_list.push(standard_device); } } - Err(VirtioError::VirtioNetNotFound) + + return virtio_list; } diff --git a/kernel/src/filesystem/sysfs/mod.rs b/kernel/src/filesystem/sysfs/mod.rs index a1567a46e..2c2dce136 100644 --- a/kernel/src/filesystem/sysfs/mod.rs +++ b/kernel/src/filesystem/sysfs/mod.rs @@ -107,7 +107,13 @@ pub trait AttributeGroup: Debug + Send + Sync { /// /// 如果返回Some,则使用返回的权限。 /// 如果要标识属性不可见,则返回Some(ModeType::empty()) - fn is_visible(&self, kobj: Arc, attr: &'static dyn Attribute) -> Option; + fn is_visible( + &self, + _kobj: Arc, + attr: &'static dyn Attribute, + ) -> Option { + return Some(attr.mode()); + } } /// sysfs只读属性文件的权限 diff --git a/kernel/src/net/mod.rs b/kernel/src/net/mod.rs index ee2cdf95f..609be50c1 100644 --- a/kernel/src/net/mod.rs +++ b/kernel/src/net/mod.rs @@ -5,7 +5,7 @@ use core::{ use alloc::{collections::BTreeMap, sync::Arc}; -use crate::{driver::net::NetDriver, libs::rwlock::RwLock}; +use crate::{driver::net::NetDevice, libs::rwlock::RwLock}; use smoltcp::wire::IpEndpoint; use self::socket::SocketInode; @@ -18,7 +18,7 @@ pub mod syscall; lazy_static! { /// # 所有网络接口的列表 /// 这个列表在中断上下文会使用到,因此需要irqsave - pub static ref NET_DRIVERS: RwLock>> = RwLock::new(BTreeMap::new()); + pub static ref NET_DEVICES: RwLock>> = RwLock::new(BTreeMap::new()); } /// 生成网络接口的id (全局自增) diff --git a/kernel/src/net/net_core.rs b/kernel/src/net/net_core.rs index 6e727effe..eb7efe7b6 100644 --- a/kernel/src/net/net_core.rs +++ b/kernel/src/net/net_core.rs @@ -3,10 +3,10 @@ use smoltcp::{socket::dhcpv4, wire}; use system_error::SystemError; use crate::{ - driver::net::NetDriver, + driver::net::NetDevice, kdebug, kinfo, kwarn, libs::rwlock::RwLockReadGuard, - net::{socket::SocketPollMethod, NET_DRIVERS}, + net::{socket::SocketPollMethod, NET_DEVICES}, time::timer::{next_n_ms_timer_jiffies, Timer, TimerFunction}, }; @@ -41,7 +41,7 @@ pub fn net_init() -> Result<(), SystemError> { } fn dhcp_query() -> Result<(), SystemError> { - let binding = NET_DRIVERS.write_irqsave(); + let binding = NET_DEVICES.write_irqsave(); let net_face = binding.get(&0).ok_or(SystemError::ENODEV)?.clone(); @@ -119,7 +119,7 @@ fn dhcp_query() -> Result<(), SystemError> { } pub fn poll_ifaces() { - let guard: RwLockReadGuard>> = NET_DRIVERS.read_irqsave(); + let guard: RwLockReadGuard>> = NET_DEVICES.read_irqsave(); if guard.len() == 0 { kwarn!("poll_ifaces: No net driver found!"); return; @@ -139,8 +139,8 @@ pub fn poll_ifaces() { pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> { let mut i = 0; while i < times { - let guard: RwLockReadGuard>> = - NET_DRIVERS.read_irqsave(); + let guard: RwLockReadGuard>> = + NET_DEVICES.read_irqsave(); if guard.len() == 0 { kwarn!("poll_ifaces: No net driver found!"); // 没有网卡,返回错误 @@ -170,7 +170,7 @@ pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> { /// @return 加锁超时,返回SystemError::EAGAIN_OR_EWOULDBLOCK /// @return 没有网卡,返回SystemError::ENODEV pub fn poll_ifaces_try_lock_onetime() -> Result<(), SystemError> { - let guard: RwLockReadGuard>> = NET_DRIVERS.read_irqsave(); + let guard: RwLockReadGuard>> = NET_DEVICES.read_irqsave(); if guard.len() == 0 { kwarn!("poll_ifaces: No net driver found!"); // 没有网卡,返回错误 diff --git a/kernel/src/net/socket/inet.rs b/kernel/src/net/socket/inet.rs index f5e4699e1..6c4580a6a 100644 --- a/kernel/src/net/socket/inet.rs +++ b/kernel/src/net/socket/inet.rs @@ -7,12 +7,12 @@ use system_error::SystemError; use crate::{ arch::rand::rand, - driver::net::NetDriver, + driver::net::NetDevice, kerror, kwarn, libs::rwlock::RwLock, net::{ event_poll::EPollEventType, net_core::poll_ifaces, Endpoint, Protocol, ShutdownType, - NET_DRIVERS, + NET_DEVICES, }, }; @@ -151,7 +151,7 @@ impl Socket for RawSocket { socket_set_guard.get_mut::(self.handle.smoltcp_handle().unwrap()); // 暴力解决方案:只考虑0号网卡。 TODO:考虑多网卡的情况!!! - let iface = NET_DRIVERS.read_irqsave().get(&0).unwrap().clone(); + let iface = NET_DEVICES.read_irqsave().get(&0).unwrap().clone(); // 构造IP头 let ipv4_src_addr: Option = @@ -700,7 +700,7 @@ impl Socket for TcpSocket { PORT_MANAGER.bind_port(self.metadata.socket_type, temp_port, self.clone())?; // kdebug!("temp_port: {}", temp_port); - let iface: Arc = NET_DRIVERS.write_irqsave().get(&0).unwrap().clone(); + let iface: Arc = NET_DEVICES.write_irqsave().get(&0).unwrap().clone(); let mut inner_iface = iface.inner_iface().lock(); // kdebug!("to connect: {ip:?}"); diff --git a/tools/run-qemu.sh b/tools/run-qemu.sh index f1e211546..1cc6911b9 100644 --- a/tools/run-qemu.sh +++ b/tools/run-qemu.sh @@ -76,6 +76,7 @@ QEMU_SERIAL="-serial file:../serial_opt.txt" QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none" QEMU_ACCELARATE="" QEMU_ARGUMENT="" +QEMU_DEVICES= # 如果qemu_accel不为空 if [ -n "${qemu_accel}" ]; then @@ -86,8 +87,11 @@ if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then QEMU_MACHINE=" -machine q35,memory-backend=${QEMU_MEMORY_BACKEND} " QEMU_CPU_FEATURES+="-cpu IvyBridge,apic,x2apic,+fpu,check,+vmx,${allflags}" QEMU_RTC_CLOCK+=" -rtc clock=host,base=localtime" + QEMU_DEVICES_DISK="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 " else QEMU_MACHINE=" -machine virt,memory-backend=${QEMU_MEMORY_BACKEND} -cpu sifive-u54 " + QEMU_DEVICES_DISK="-device virtio-blk-device,drive=disk " + fi if [ ${ARCH} == "riscv64" ]; then @@ -101,7 +105,8 @@ fi # ps: 下面这条使用tap的方式,无法dhcp获取到ip,暂时不知道为什么 # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 " -QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -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 " +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} "