Browse Source

新增VirtIO网卡驱动 (#194)

* 修复内存bug与grub安装脚本的错误

* 修改小bug

* PCI增加功能与virtio-net驱动

* little fix

* virtio-net小修改
YJwu2023 2 years ago
parent
commit
26d84a3139

+ 2 - 1
.vscode/settings.json

@@ -169,7 +169,8 @@
         "acpi.h": "c",
         "assert.h": "c",
         "sys_version.h": "c",
-        "cmd.h": "c"
+        "cmd.h": "c",
+        "net.h": "c"
     },
     "C_Cpp.errorSquiggles": "Enabled",
     "esbonio.sphinx.confDir": "",

+ 3 - 0
kernel/Cargo.toml

@@ -11,6 +11,8 @@ crate-type = ["staticlib"]
 # 运行时依赖项
 [dependencies]
 x86_64 = "0.14.10"
+virtio-drivers = "0.2.0"
+bitflags = "1.3"
 
 # 构建时依赖项
 [build-dependencies]
@@ -22,3 +24,4 @@ version = "1.4.0"
 features = ["spin_no_std"]
 
 
+

+ 0 - 0
kernel/src/arch/x86_64/x86_64_pci.c


+ 0 - 0
kernel/src/arch/x86_64/x86_64_pci.h


+ 2 - 2
kernel/src/driver/Makefile

@@ -1,7 +1,7 @@
 
 CFLAGS += -I .
 
-kernel_driver_subdirs:=video interrupt usb pci acpi disk keyboard mouse multiboot2 timers tty hid
+kernel_driver_subdirs:=video interrupt usb pci acpi disk keyboard mouse multiboot2 timers tty hid virtio
 
 ECHO:
 	@echo "$@"
@@ -14,4 +14,4 @@ all: $(kernel_driver_subdirs)
 
 
 clean:
-	echo "Done."
+	echo "Done."

+ 2 - 0
kernel/src/driver/mod.rs

@@ -1,2 +1,4 @@
+pub mod pci;
 pub mod timers;
 pub mod uart;
+pub mod virtio;

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

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

+ 1 - 1
kernel/src/driver/pci/msi.c

@@ -71,7 +71,7 @@ static __always_inline struct pci_msi_cap_t __msi_read_cap_list(struct msi_desc_
 }
 
 /**
- * @brief 映射设备的msix表
+ * @brief 映射设备的msix表  //MSIX表不再单独映射(To do)
  *
  * @param pci_dev pci设备信息结构体
  * @param msix_cap msix capability list的结构体

+ 495 - 0
kernel/src/driver/pci/pci.rs

@@ -0,0 +1,495 @@
+use crate::include::bindings::bindings::{
+    initial_mm, mm_map, mm_struct, pci_read_config, pci_write_config, VM_DONTCOPY, VM_IO,
+};
+use crate::mm::mmio_buddy::MMIO_POOL;
+use crate::{kdebug, kerror, kwarn};
+use bitflags::bitflags;
+use core::{
+    convert::TryFrom,
+    fmt::{self, Display, Formatter},
+    ptr::NonNull,
+};
+//Bar0寄存器的offset
+const BAR0_OFFSET: u8 = 0x10;
+//Status、Command寄存器的offset
+const STATUS_COMMAND_OFFSET: u8 = 0x04;
+/// ID for vendor-specific PCI capabilities.(Virtio Capabilities)
+pub const PCI_CAP_ID_VNDR: u8 = 0x09;
+
+bitflags! {
+    /// The status register in PCI configuration space.
+    pub struct Status: u16 {
+        // Bits 0-2 are reserved.
+        /// The state of the device's INTx# signal.
+        const INTERRUPT_STATUS = 1 << 3;
+        /// The device has a linked list of capabilities.
+        const CAPABILITIES_LIST = 1 << 4;
+        /// The device is capabile of running at 66 MHz rather than 33 MHz.
+        const MHZ_66_CAPABLE = 1 << 5;
+        // Bit 6 is reserved.
+        /// The device can accept fast back-to-back transactions not from the same agent.
+        const FAST_BACK_TO_BACK_CAPABLE = 1 << 7;
+        /// The bus agent observed a parity error (if parity error handling is enabled).
+        const MASTER_DATA_PARITY_ERROR = 1 << 8;
+        // Bits 9-10 are DEVSEL timing.
+        /// A target device terminated a transaction with target-abort.
+        const SIGNALED_TARGET_ABORT = 1 << 11;
+        /// A master device transaction was terminated with target-abort.
+        const RECEIVED_TARGET_ABORT = 1 << 12;
+        /// A master device transaction was terminated with master-abort.
+        const RECEIVED_MASTER_ABORT = 1 << 13;
+        /// A device asserts SERR#.
+        const SIGNALED_SYSTEM_ERROR = 1 << 14;
+        /// The device detects a parity error, even if parity error handling is disabled.
+        const DETECTED_PARITY_ERROR = 1 << 15;
+    }
+}
+
+bitflags! {
+    /// The command register in PCI configuration space.
+    pub struct Command: u16 {
+        /// The device can respond to I/O Space accesses.
+        const IO_SPACE = 1 << 0;
+        /// The device can respond to Memory Space accesses.
+        const MEMORY_SPACE = 1 << 1;
+        /// The device can behave as a bus master.
+        const BUS_MASTER = 1 << 2;
+        /// The device can monitor Special Cycle operations.
+        const SPECIAL_CYCLES = 1 << 3;
+        /// The device can generate the Memory Write and Invalidate command.
+        const MEMORY_WRITE_AND_INVALIDATE_ENABLE = 1 << 4;
+        /// The device will snoop palette register data.
+        const VGA_PALETTE_SNOOP = 1 << 5;
+        /// The device should take its normal action when a parity error is detected.
+        const PARITY_ERROR_RESPONSE = 1 << 6;
+        // Bit 7 is reserved.
+        /// The SERR# driver is enabled.
+        const SERR_ENABLE = 1 << 8;
+        /// The device is allowed to generate fast back-to-back transactions.
+        const FAST_BACK_TO_BACK_ENABLE = 1 << 9;
+        /// Assertion of the device's INTx# signal is disabled.
+        const INTERRUPT_DISABLE = 1 << 10;
+    }
+}
+
+/// Gets the capabilities 'pointer' for the device function, if any.
+///@brief 获取第一个capability 的offset
+///@param device_function PCI设备的唯一标识
+///@return Option<u8> offset
+pub fn capabilities_offset(device_function: DeviceFunction) -> Option<u8> {
+    let status: Status = unsafe {
+        let temp = pci_read_config(
+            device_function.bus,
+            device_function.device,
+            device_function.function,
+            STATUS_COMMAND_OFFSET,
+        );
+        Status::from_bits_truncate((temp >> 16) as u16)
+    };
+    if status.contains(Status::CAPABILITIES_LIST) {
+        let cap_pointer = unsafe {
+            let temp = pci_read_config(
+                device_function.bus,
+                device_function.device,
+                device_function.function,
+                0x34,
+            );
+            temp as u8 & 0xFC
+        };
+        Some(cap_pointer)
+    } else {
+        None
+    }
+}
+/// An identifier for a PCI bus, device and function.
+/// PCI设备的唯一标识
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct DeviceFunction {
+    /// The PCI bus number, between 0 and 255.
+    pub bus: u8,
+    /// The device number on the bus, between 0 and 31.
+    pub device: u8,
+    /// The function number of the device, between 0 and 7.
+    pub function: u8,
+}
+///PCI的Error
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum PciError {
+    /// The device reported an invalid BAR type.
+    InvalidBarType,
+    CreateMmioError,
+}
+///实现PciError的Display trait,使其可以直接输出
+impl Display for PciError {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        match self {
+            Self::InvalidBarType => write!(f, "Invalid PCI BAR type."),
+            Self::CreateMmioError => write!(f, "Error occurred while creating mmio"),
+        }
+    }
+}
+
+impl DeviceFunction {
+    /// Returns whether the device and function numbers are valid, i.e. the device is between 0 and
+    /// 31, and the function is between 0 and 7.
+    ///@brief 检测DeviceFunction实例是否有效
+    ///@param self
+    ///@return bool 是否有效
+    pub fn valid(&self) -> bool {
+        self.device < 32 && self.function < 8
+    }
+}
+///实现DeviceFunction的Display trait,使其可以直接输出
+impl Display for DeviceFunction {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "{:02x}:{:02x}.{}", self.bus, self.device, self.function)
+    }
+}
+/// The location allowed for a memory BAR.
+/// memory BAR的三种情况
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum MemoryBarType {
+    /// The BAR has a 32-bit address and can be mapped anywhere in 32-bit address space.
+    Width32,
+    /// The BAR must be mapped below 1MiB.
+    Below1MiB,
+    /// The BAR has a 64-bit address and can be mapped anywhere in 64-bit address space.
+    Width64,
+}
+///实现MemoryBarType与u8的类型转换
+impl From<MemoryBarType> for u8 {
+    fn from(bar_type: MemoryBarType) -> Self {
+        match bar_type {
+            MemoryBarType::Width32 => 0,
+            MemoryBarType::Below1MiB => 1,
+            MemoryBarType::Width64 => 2,
+        }
+    }
+}
+///实现MemoryBarType与u8的类型转换
+impl TryFrom<u8> for MemoryBarType {
+    type Error = PciError;
+    fn try_from(value: u8) -> Result<Self, Self::Error> {
+        match value {
+            0 => Ok(Self::Width32),
+            1 => Ok(Self::Below1MiB),
+            2 => Ok(Self::Width64),
+            _ => Err(PciError::InvalidBarType),
+        }
+    }
+}
+
+/// Information about a PCI Base Address Register.
+/// BAR的三种类型 Memory/IO/Unused
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum BarInfo {
+    /// The BAR is for a memory region.
+    Memory {
+        /// The size of the BAR address and where it can be located.
+        address_type: MemoryBarType,
+        /// If true, then reading from the region doesn't have side effects. The CPU may cache reads
+        /// and merge repeated stores.
+        prefetchable: bool,
+        /// The memory address, always 16-byte aligned.
+        address: u64,
+        /// The size of the BAR in bytes.
+        size: u32,
+        /// The virtaddress for a memory bar(mapped).
+        virtaddress: u64,
+    },
+    /// The BAR is for an I/O region.
+    IO {
+        /// The I/O address, always 4-byte aligned.
+        address: u32,
+        /// The size of the BAR in bytes.
+        size: u32,
+    },
+    Unused,
+}
+
+impl BarInfo {
+    /// Returns the address and size of this BAR if it is a memory bar, or `None` if it is an IO
+    /// BAR.
+    ///@brief 得到某个bar的memory_address与size(前提是他的类型为Memory Bar)
+    ///@param self
+    ///@return Option<(u64, u32) 是Memory Bar返回内存地址与大小,不是则返回None
+    pub fn memory_address_size(&self) -> Option<(u64, u32)> {
+        if let Self::Memory { address, size, .. } = self {
+            Some((*address, *size))
+        } else {
+            None
+        }
+    }
+    ///@brief 得到某个bar的virtaddress(前提是他的类型为Memory Bar)
+    ///@param self
+    ///@return Option<(u64) 是Memory Bar返回映射的虚拟地址,不是则返回None
+    pub fn virtual_address(&self) -> Option<u64> {
+        if let Self::Memory { virtaddress, .. } = self {
+            Some(*virtaddress)
+        } else {
+            None
+        }
+    }
+}
+///实现BarInfo的Display trait,使其可以直接输出
+impl Display for BarInfo {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Memory {
+                address_type,
+                prefetchable,
+                address,
+                size,
+                virtaddress,
+            } => write!(
+                f,
+                "Memory space at {:#010x}, size {}, type {:?}, prefetchable {},mapped at {:#x}",
+                address, size, address_type, prefetchable, virtaddress
+            ),
+            Self::IO { address, size } => {
+                write!(f, "I/O space at {:#010x}, size {}", address, size)
+            }
+            Self::Unused => {
+                write!(f, "Unused bar")
+            }
+        }
+    }
+}
+///一个PCI设备有6个BAR寄存器,PciDeviceBar存储其全部信息
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct PciDeviceBar {
+    bar0: BarInfo,
+    bar1: BarInfo,
+    bar2: BarInfo,
+    bar3: BarInfo,
+    bar4: BarInfo,
+    bar5: BarInfo,
+}
+
+impl PciDeviceBar {
+    ///@brief 得到某个bar的barinfo
+    ///@param self ,bar_index(0-5)
+    ///@return Result<&BarInfo, PciError> bar_index在0-5则返回对应的bar_info结构体,超出范围则返回错误
+    pub fn get_bar(&self, bar_index: u8) -> Result<&BarInfo, PciError> {
+        match bar_index {
+            0 => Ok(&self.bar0),
+            1 => Ok(&self.bar1),
+            2 => Ok(&self.bar2),
+            3 => Ok(&self.bar3),
+            4 => Ok(&self.bar4),
+            _ => Err(PciError::InvalidBarType),
+        }
+    }
+}
+///实现PciDeviceBar的Display trait,使其可以直接输出
+impl Display for PciDeviceBar {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "\r\nBar0:{}\r\n Bar1:{}\r\n Bar2:{}\r\n Bar3:{}\r\nBar4:{}\r\nBar5:{}",
+            self.bar0, self.bar1, self.bar2, self.bar3, self.bar4, self.bar5
+        )
+    }
+}
+///实现PciDeviceBar的Default trait,使其可以简单初始化
+impl Default for PciDeviceBar {
+    fn default() -> Self {
+        PciDeviceBar {
+            bar0: BarInfo::Unused,
+            bar1: BarInfo::Unused,
+            bar2: BarInfo::Unused,
+            bar3: BarInfo::Unused,
+            bar4: BarInfo::Unused,
+            bar5: BarInfo::Unused,
+        }
+    }
+}
+
+///@brief 将某个pci设备的bar全部初始化,memory
+///@param self ,device_function PCI设备的唯一标识符
+///@return Result<PciDeviceBar, PciError> 成功则返回对应的PciDeviceBar结构体,失败则返回错误类型
+pub fn pci_bar_init(device_function: DeviceFunction) -> Result<PciDeviceBar, PciError> {
+    let mut device_bar: PciDeviceBar = PciDeviceBar::default();
+    let mut bar_index_ignore: u8 = 255;
+    for bar_index in 0..6 {
+        if bar_index == bar_index_ignore {
+            continue;
+        }
+        let bar_info;
+        let mut virtaddress: u64 = 0;
+        let bar_orig = unsafe {
+            let bar_temp = pci_read_config(
+                device_function.bus,
+                device_function.device,
+                device_function.function,
+                BAR0_OFFSET + 4 * bar_index,
+            );
+            bar_temp
+        };
+        unsafe {
+            pci_write_config(
+                device_function.bus,
+                device_function.device,
+                device_function.function,
+                BAR0_OFFSET + 4 * bar_index,
+                0xffffffff,
+            );
+        }
+        let size_mask = unsafe {
+            let bar_temp = pci_read_config(
+                device_function.bus,
+                device_function.device,
+                device_function.function,
+                BAR0_OFFSET + 4 * bar_index,
+            );
+            bar_temp
+        };
+        // A wrapping add is necessary to correctly handle the case of unused BARs, which read back
+        // as 0, and should be treated as size 0.
+        let size = (!(size_mask & 0xfffffff0)).wrapping_add(1);
+        //kdebug!("bar_orig:{:#x},size: {:#x}", bar_orig,size);
+        // Restore the original value.
+        unsafe {
+            pci_write_config(
+                device_function.bus,
+                device_function.device,
+                device_function.function,
+                BAR0_OFFSET + 4 * bar_index,
+                bar_orig,
+            );
+        }
+        if size == 0 {
+            continue;
+        }
+        if bar_orig & 0x00000001 == 0x00000001 {
+            // I/O space
+            let address = bar_orig & 0xfffffffc;
+            bar_info = BarInfo::IO { address, size };
+        } else {
+            // Memory space
+            let mut address = u64::from(bar_orig & 0xfffffff0);
+            let prefetchable = bar_orig & 0x00000008 != 0;
+            let address_type = MemoryBarType::try_from(((bar_orig & 0x00000006) >> 1) as u8)?;
+            if address_type == MemoryBarType::Width64 {
+                if bar_index >= 5 {
+                    return Err(PciError::InvalidBarType);
+                }
+                let address_top = unsafe {
+                    let bar_temp = pci_read_config(
+                        device_function.bus,
+                        device_function.device,
+                        device_function.function,
+                        BAR0_OFFSET + 4 * (bar_index + 1),
+                    );
+                    bar_temp
+                };
+                address |= u64::from(address_top) << 32;
+                bar_index_ignore = bar_index + 1; //下个bar跳过,因为64位的memory bar覆盖了两个bar
+            }
+            //kdebug!("address={:#x},size={:#x}",address,size);
+            unsafe {
+                let vaddr_ptr = &mut virtaddress as *mut u64;
+                let mut virtsize: u64 = 0;
+                let virtsize_ptr = &mut virtsize as *mut u64;
+                let initial_mm_ptr = &mut initial_mm as *mut mm_struct;
+                //kdebug!("size want={:#x}", size);
+                if let Err(_) = MMIO_POOL.create_mmio(
+                    size,
+                    (VM_IO | VM_DONTCOPY) as u64,
+                    vaddr_ptr,
+                    virtsize_ptr,
+                ) {
+                    kerror!("Create mmio failed when initing pci bar");
+                    return Err(PciError::CreateMmioError);
+                };
+                //kdebug!("virtaddress={:#x},virtsize={:#x}",virtaddress,virtsize);
+                mm_map(initial_mm_ptr, virtaddress, size as u64, address);
+            }
+            bar_info = BarInfo::Memory {
+                address_type,
+                prefetchable,
+                address,
+                size,
+                virtaddress,
+            };
+        }
+        match bar_index {
+            0 => {
+                device_bar.bar0 = bar_info;
+            }
+            1 => {
+                device_bar.bar1 = bar_info;
+            }
+            2 => {
+                device_bar.bar2 = bar_info;
+            }
+            3 => {
+                device_bar.bar3 = bar_info;
+            }
+            4 => {
+                device_bar.bar4 = bar_info;
+            }
+            5 => {
+                device_bar.bar5 = bar_info;
+            }
+            _ => {}
+        }
+    }
+    kdebug!("pci_device_bar:{}", device_bar);
+    return Ok(device_bar);
+}
+
+/// Information about a PCI device capability.
+/// PCI设备的capability的信息
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub struct CapabilityInfo {
+    /// The offset of the capability in the PCI configuration space of the device function.
+    pub offset: u8,
+    /// The ID of the capability.
+    pub id: u8,
+    /// The third and fourth bytes of the capability, to save reading them again.
+    pub private_header: u16,
+}
+/// Iterator over capabilities for a device.
+/// 创建迭代器以遍历PCI设备的capability
+#[derive(Debug)]
+pub struct CapabilityIterator {
+    pub device_function: DeviceFunction,
+    pub next_capability_offset: Option<u8>,
+}
+
+impl Iterator for CapabilityIterator {
+    type Item = CapabilityInfo;
+    fn next(&mut self) -> Option<Self::Item> {
+        let offset = self.next_capability_offset?;
+
+        // Read the first 4 bytes of the capability.
+        let capability_header = unsafe {
+            let temp = pci_read_config(
+                self.device_function.bus,
+                self.device_function.device,
+                self.device_function.function,
+                offset,
+            );
+            temp
+        };
+        let id = capability_header as u8;
+        let next_offset = (capability_header >> 8) as u8;
+        let private_header = (capability_header >> 16) as u16;
+
+        self.next_capability_offset = if next_offset == 0 {
+            None
+        } else if next_offset < 64 || next_offset & 0x3 != 0 {
+            kwarn!("Invalid next capability offset {:#04x}", next_offset);
+            None
+        } else {
+            Some(next_offset)
+        };
+
+        Some(CapabilityInfo {
+            offset,
+            id,
+            private_header,
+        })
+    }
+}

+ 2 - 0
kernel/src/driver/usb/xhci/xhci.c

@@ -640,6 +640,8 @@ uint64_t xhci_hc_irq_install(uint64_t irq_num, void *arg)
     msi_desc.pci.msi_attribute.is_64 = 1;
     msi_desc.pci.msi_attribute.is_msix = 1;
     io_mfence();
+    //因pci_enable_msi不再单独映射MSIX表,所以需要对pci设备的bar进行映射
+    
     int retval = pci_enable_msi(&msi_desc);
 
     return 0;

+ 7 - 0
kernel/src/driver/virtio/Makefile

@@ -0,0 +1,7 @@
+all: virtio.o
+
+CFLAGS += -I .
+
+virtio.o: virtio.c
+	$(CC) $(CFLAGS) -c virtio.c -o virtio.o
+

+ 4 - 0
kernel/src/driver/virtio/mod.rs

@@ -0,0 +1,4 @@
+pub mod transport_pci;
+pub mod virtio;
+pub mod virtio_impl;
+pub mod volatile;

+ 515 - 0
kernel/src/driver/virtio/transport_pci.rs

@@ -0,0 +1,515 @@
+//! PCI transport for VirtIO.
+use super::volatile::{
+    volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
+};
+use crate::driver::pci::pci::{
+    capabilities_offset, pci_bar_init, CapabilityIterator, DeviceFunction, PciDeviceBar, PciError,
+    PCI_CAP_ID_VNDR,
+};
+use crate::include::bindings::bindings::pci_read_config;
+use core::{
+    fmt::{self, Display, Formatter},
+    mem::{align_of, size_of},
+    ptr::{self, addr_of_mut, NonNull},
+};
+use virtio_drivers::{
+    transport::{DeviceStatus, DeviceType, Transport},
+    Error, Hal, PhysAddr, VirtAddr,
+};
+
+/// The PCI vendor ID for VirtIO devices.
+/// PCI Virtio设备的vendor ID
+const VIRTIO_VENDOR_ID: u16 = 0x1af4;
+
+/// The offset to add to a VirtIO device ID to get the corresponding PCI device ID.
+/// PCI Virtio设备的DEVICE_ID 的offset
+const PCI_DEVICE_ID_OFFSET: u16 = 0x1040;
+/// PCI Virtio 设备的DEVICE_ID及其对应的设备类型
+const TRANSITIONAL_NETWORK: u16 = 0x1000;
+const TRANSITIONAL_BLOCK: u16 = 0x1001;
+const TRANSITIONAL_MEMORY_BALLOONING: u16 = 0x1002;
+const TRANSITIONAL_CONSOLE: u16 = 0x1003;
+const TRANSITIONAL_SCSI_HOST: u16 = 0x1004;
+const TRANSITIONAL_ENTROPY_SOURCE: u16 = 0x1005;
+const TRANSITIONAL_9P_TRANSPORT: u16 = 0x1009;
+
+/// The offset of the bar field within `virtio_pci_cap`.
+const CAP_BAR_OFFSET: u8 = 4;
+/// The offset of the offset field with `virtio_pci_cap`.
+const CAP_BAR_OFFSET_OFFSET: u8 = 8;
+/// The offset of the `length` field within `virtio_pci_cap`.
+const CAP_LENGTH_OFFSET: u8 = 12;
+/// The offset of the`notify_off_multiplier` field within `virtio_pci_notify_cap`.
+const CAP_NOTIFY_OFF_MULTIPLIER_OFFSET: u8 = 16;
+
+/// Common configuration.
+const VIRTIO_PCI_CAP_COMMON_CFG: u8 = 1;
+/// Notifications.
+const VIRTIO_PCI_CAP_NOTIFY_CFG: u8 = 2;
+/// ISR Status.
+const VIRTIO_PCI_CAP_ISR_CFG: u8 = 3;
+/// Device specific configuration.
+const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4;
+
+///@brief device id 转换为设备类型
+///@param pci_device_id,device_id
+///@return DeviceType 对应的设备类型
+fn device_type(pci_device_id: u16) -> DeviceType {
+    match pci_device_id {
+        TRANSITIONAL_NETWORK => DeviceType::Network,
+        TRANSITIONAL_BLOCK => DeviceType::Block,
+        TRANSITIONAL_MEMORY_BALLOONING => DeviceType::MemoryBalloon,
+        TRANSITIONAL_CONSOLE => DeviceType::Console,
+        TRANSITIONAL_SCSI_HOST => DeviceType::ScsiHost,
+        TRANSITIONAL_ENTROPY_SOURCE => DeviceType::EntropySource,
+        TRANSITIONAL_9P_TRANSPORT => DeviceType::_9P,
+        id if id >= PCI_DEVICE_ID_OFFSET => DeviceType::from(id - PCI_DEVICE_ID_OFFSET),
+        _ => DeviceType::Invalid,
+    }
+}
+
+/// PCI transport for VirtIO.
+///
+/// Ref: 4.1 Virtio Over PCI Bus
+#[derive(Debug)]
+pub struct PciTransport {
+    device_type: DeviceType,
+    /// The bus, device and function identifier for the VirtIO device.
+    device_function: DeviceFunction,
+    /// The common configuration structure within some BAR.
+    common_cfg: NonNull<CommonCfg>,
+    /// The start of the queue notification region within some BAR.
+    notify_region: NonNull<[WriteOnly<u16>]>,
+    notify_off_multiplier: u32,
+    /// The ISR status register within some BAR.
+    isr_status: NonNull<Volatile<u8>>,
+    /// The VirtIO device-specific configuration within some BAR.
+    config_space: Option<NonNull<[u32]>>,
+}
+
+impl PciTransport {
+    /// Construct a new PCI VirtIO device driver for the given device function on the given PCI
+    /// root controller.
+    ///
+    /// The PCI device must already have had its BARs allocated.
+    pub fn new<H: Hal>(device_function: DeviceFunction) -> Result<Self, VirtioPciError> {
+        let device_vendor = unsafe {
+            let bar_temp = pci_read_config(
+                device_function.bus,
+                device_function.device,
+                device_function.function,
+                0,
+            );
+            bar_temp
+        };
+        let device_id = (device_vendor >> 16) as u16;
+        let vendor_id = device_vendor as u16;
+        if vendor_id != VIRTIO_VENDOR_ID {
+            return Err(VirtioPciError::InvalidVendorId(vendor_id));
+        }
+        let device_type = device_type(device_id);
+        // Find the PCI capabilities we need.
+        let mut common_cfg = None;
+        let mut notify_cfg = None;
+        let mut notify_off_multiplier = 0;
+        let mut isr_cfg = None;
+        let mut device_cfg = None;
+        //device_capability为迭代器,遍历其相当于遍历所有的cap空间
+        let device_capability = CapabilityIterator {
+            device_function: device_function,
+            next_capability_offset: capabilities_offset(device_function),
+        };
+        let device_bar = pci_bar_init(device_function)?;
+
+        for capability in device_capability {
+            if capability.id != PCI_CAP_ID_VNDR {
+                continue;
+            }
+            let cap_len = capability.private_header as u8;
+            let cfg_type = (capability.private_header >> 8) as u8;
+            if cap_len < 16 {
+                continue;
+            }
+            let struct_info = VirtioCapabilityInfo {
+                bar: unsafe {
+                    let temp = pci_read_config(
+                        device_function.bus,
+                        device_function.device,
+                        device_function.function,
+                        capability.offset + CAP_BAR_OFFSET,
+                    );
+                    temp as u8
+                },
+                offset: unsafe {
+                    let temp = pci_read_config(
+                        device_function.bus,
+                        device_function.device,
+                        device_function.function,
+                        capability.offset + CAP_BAR_OFFSET_OFFSET,
+                    );
+                    temp
+                },
+                length: unsafe {
+                    let temp = pci_read_config(
+                        device_function.bus,
+                        device_function.device,
+                        device_function.function,
+                        capability.offset + CAP_LENGTH_OFFSET,
+                    );
+                    temp
+                },
+            };
+
+            match cfg_type {
+                VIRTIO_PCI_CAP_COMMON_CFG if common_cfg.is_none() => {
+                    common_cfg = Some(struct_info);
+                }
+                VIRTIO_PCI_CAP_NOTIFY_CFG if cap_len >= 20 && notify_cfg.is_none() => {
+                    notify_cfg = Some(struct_info);
+                    notify_off_multiplier = unsafe {
+                        let temp = pci_read_config(
+                            device_function.bus,
+                            device_function.device,
+                            device_function.function,
+                            capability.offset + CAP_NOTIFY_OFF_MULTIPLIER_OFFSET,
+                        );
+                        temp
+                    };
+                }
+                VIRTIO_PCI_CAP_ISR_CFG if isr_cfg.is_none() => {
+                    isr_cfg = Some(struct_info);
+                }
+                VIRTIO_PCI_CAP_DEVICE_CFG if device_cfg.is_none() => {
+                    device_cfg = Some(struct_info);
+                }
+                _ => {}
+            }
+        }
+
+        let common_cfg = get_bar_region::<_>(
+            &device_bar,
+            &common_cfg.ok_or(VirtioPciError::MissingCommonConfig)?,
+        )?;
+
+        let notify_cfg = notify_cfg.ok_or(VirtioPciError::MissingNotifyConfig)?;
+        if notify_off_multiplier % 2 != 0 {
+            return Err(VirtioPciError::InvalidNotifyOffMultiplier(
+                notify_off_multiplier,
+            ));
+        }
+        let notify_region = get_bar_region_slice::<_>(&device_bar, &notify_cfg)?;
+        let isr_status = get_bar_region::<_>(
+            &device_bar,
+            &isr_cfg.ok_or(VirtioPciError::MissingIsrConfig)?,
+        )?;
+        let config_space = if let Some(device_cfg) = device_cfg {
+            Some(get_bar_region_slice::<_>(&device_bar, &device_cfg)?)
+        } else {
+            None
+        };
+        Ok(Self {
+            device_type,
+            device_function,
+            common_cfg,
+            notify_region,
+            notify_off_multiplier,
+            isr_status,
+            config_space,
+        })
+    }
+}
+
+impl Transport for PciTransport {
+    fn device_type(&self) -> DeviceType {
+        self.device_type
+    }
+
+    fn read_device_features(&mut self) -> u64 {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        unsafe {
+            volwrite!(self.common_cfg, device_feature_select, 0);
+            let mut device_features_bits = volread!(self.common_cfg, device_feature) as u64;
+            volwrite!(self.common_cfg, device_feature_select, 1);
+            device_features_bits |= (volread!(self.common_cfg, device_feature) as u64) << 32;
+            device_features_bits
+        }
+    }
+
+    fn write_driver_features(&mut self, driver_features: u64) {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        unsafe {
+            volwrite!(self.common_cfg, driver_feature_select, 0);
+            volwrite!(self.common_cfg, driver_feature, driver_features as u32);
+            volwrite!(self.common_cfg, driver_feature_select, 1);
+            volwrite!(
+                self.common_cfg,
+                driver_feature,
+                (driver_features >> 32) as u32
+            );
+        }
+    }
+
+    fn max_queue_size(&self) -> u32 {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        unsafe { volread!(self.common_cfg, queue_size) }.into()
+    }
+
+    fn notify(&mut self, queue: u16) {
+        // Safe because the common config and notify region pointers are valid and we checked in
+        // get_bar_region that they were aligned.
+        unsafe {
+            volwrite!(self.common_cfg, queue_select, queue);
+            // TODO: Consider caching this somewhere (per queue).
+            let queue_notify_off = volread!(self.common_cfg, queue_notify_off);
+
+            let offset_bytes = usize::from(queue_notify_off) * self.notify_off_multiplier as usize;
+            let index = offset_bytes / size_of::<u16>();
+            addr_of_mut!((*self.notify_region.as_ptr())[index]).vwrite(queue);
+        }
+    }
+
+    fn set_status(&mut self, status: DeviceStatus) {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        unsafe {
+            volwrite!(self.common_cfg, device_status, status.bits() as u8);
+        }
+    }
+
+    fn set_guest_page_size(&mut self, _guest_page_size: u32) {
+        // No-op, the PCI transport doesn't care.
+    }
+
+    fn queue_set(
+        &mut self,
+        queue: u16,
+        size: u32,
+        descriptors: PhysAddr,
+        driver_area: PhysAddr,
+        device_area: PhysAddr,
+    ) {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        unsafe {
+            volwrite!(self.common_cfg, queue_select, queue);
+            volwrite!(self.common_cfg, queue_size, size as u16);
+            volwrite!(self.common_cfg, queue_desc, descriptors as u64);
+            volwrite!(self.common_cfg, queue_driver, driver_area as u64);
+            volwrite!(self.common_cfg, queue_device, device_area as u64);
+            volwrite!(self.common_cfg, queue_enable, 1);
+        }
+    }
+
+    fn queue_unset(&mut self, queue: u16) {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        unsafe {
+            volwrite!(self.common_cfg, queue_enable, 0);
+            volwrite!(self.common_cfg, queue_select, queue);
+            volwrite!(self.common_cfg, queue_size, 0);
+            volwrite!(self.common_cfg, queue_desc, 0);
+            volwrite!(self.common_cfg, queue_driver, 0);
+            volwrite!(self.common_cfg, queue_device, 0);
+        }
+    }
+
+    fn queue_used(&mut self, queue: u16) -> bool {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        unsafe {
+            volwrite!(self.common_cfg, queue_select, queue);
+            volread!(self.common_cfg, queue_enable) == 1
+        }
+    }
+
+    fn ack_interrupt(&mut self) -> bool {
+        // Safe because the common config pointer is valid and we checked in get_bar_region that it
+        // was aligned.
+        // Reading the ISR status resets it to 0 and causes the device to de-assert the interrupt.
+        let isr_status = unsafe { self.isr_status.as_ptr().vread() };
+        // TODO: Distinguish between queue interrupt and device configuration interrupt.
+        isr_status & 0x3 != 0
+    }
+
+    fn config_space<T>(&self) -> Result<NonNull<T>, Error> {
+        if let Some(config_space) = self.config_space {
+            if size_of::<T>() > config_space.len() * size_of::<u32>() {
+                Err(Error::ConfigSpaceTooSmall)
+            } else if align_of::<T>() > 4 {
+                // Panic as this should only happen if the driver is written incorrectly.
+                panic!(
+                    "Driver expected config space alignment of {} bytes, but VirtIO only guarantees 4 byte alignment.",
+                    align_of::<T>()
+                );
+            } else {
+                // TODO: Use NonNull::as_non_null_ptr once it is stable.
+                let config_space_ptr = NonNull::new(config_space.as_ptr() as *mut u32).unwrap();
+                Ok(config_space_ptr.cast())
+            }
+        } else {
+            Err(Error::ConfigSpaceMissing)
+        }
+    }
+}
+
+/// `virtio_pci_common_cfg`, see 4.1.4.3 "Common configuration structure layout".
+///
+#[repr(C)]
+struct CommonCfg {
+    device_feature_select: Volatile<u32>,
+    device_feature: ReadOnly<u32>,
+    driver_feature_select: Volatile<u32>,
+    driver_feature: Volatile<u32>,
+    msix_config: Volatile<u16>,
+    num_queues: ReadOnly<u16>,
+    device_status: Volatile<u8>,
+    config_generation: ReadOnly<u8>,
+    queue_select: Volatile<u16>,
+    queue_size: Volatile<u16>,
+    queue_msix_vector: Volatile<u16>,
+    queue_enable: Volatile<u16>,
+    queue_notify_off: Volatile<u16>,
+    queue_desc: Volatile<u64>,
+    queue_driver: Volatile<u64>,
+    queue_device: Volatile<u64>,
+}
+
+/// Information about a VirtIO structure within some BAR, as provided by a `virtio_pci_cap`.
+///cfg空间在哪个bar的多少偏移处,长度多少
+#[derive(Clone, Debug, Eq, PartialEq)]
+struct VirtioCapabilityInfo {
+    /// The bar in which the structure can be found.
+    bar: u8,
+    /// The offset within the bar.
+    offset: u32,
+    /// The length in bytes of the structure within the bar.
+    length: u32,
+}
+
+/// An error encountered initialising a VirtIO PCI transport.
+/// VirtIO PCI transport 初始化时的错误
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum VirtioPciError {
+    /// PCI device vender ID was not the VirtIO vendor ID.
+    InvalidVendorId(u16),
+    /// No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found.
+    MissingCommonConfig,
+    /// No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found.
+    MissingNotifyConfig,
+    /// `VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple
+    /// of 2.
+    InvalidNotifyOffMultiplier(u32),
+    /// No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.
+    MissingIsrConfig,
+    /// An IO BAR was provided rather than a memory BAR.
+    UnexpectedBarType,
+    /// A BAR which we need was not allocated an address.
+    BarNotAllocated(u8),
+    /// The offset for some capability was greater than the length of the BAR.
+    BarOffsetOutOfRange,
+    /// The virtual address was not aligned as expected.
+    Misaligned {
+        /// The virtual address in question.
+        vaddr: VirtAddr,
+        /// The expected alignment in bytes.
+        alignment: usize,
+    },
+    ///获取虚拟地址失败
+    BarGetVaddrFailed,
+    /// A generic PCI error,
+    Pci(PciError),
+}
+
+impl Display for VirtioPciError {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        match self {
+            Self::InvalidVendorId(vendor_id) => write!(
+                f,
+                "PCI device vender ID {:#06x} was not the VirtIO vendor ID {:#06x}.",
+                vendor_id, VIRTIO_VENDOR_ID
+            ),
+            Self::MissingCommonConfig => write!(
+                f,
+                "No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found."
+            ),
+            Self::MissingNotifyConfig => write!(
+                f,
+                "No valid `VIRTIO_PCI_CAP_NOTIFY_CFG` capability was found."
+            ),
+            Self::InvalidNotifyOffMultiplier(notify_off_multiplier) => {
+                write!(
+                    f,
+                    "`VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple of 2: {}",
+                    notify_off_multiplier
+                )
+            }
+            Self::MissingIsrConfig => {
+                write!(f, "No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.")
+            }
+            Self::UnexpectedBarType => write!(f, "Unexpected BAR (expected memory BAR)."),
+            Self::BarNotAllocated(bar_index) => write!(f, "Bar {} not allocated.", bar_index),
+            Self::BarOffsetOutOfRange => write!(f, "Capability offset greater than BAR length."),
+            Self::Misaligned { vaddr, alignment } => write!(
+                f,
+                "Virtual address {:#018x} was not aligned to a {} byte boundary as expected.",
+                vaddr, alignment
+            ),
+            Self::BarGetVaddrFailed => write!(f, "Get bar virtaddress failed"),
+            Self::Pci(pci_error) => pci_error.fmt(f),
+        }
+    }
+}
+///PCI error到VirtioPciError的转换,层层上报
+impl From<PciError> for VirtioPciError {
+    fn from(error: PciError) -> Self {
+        Self::Pci(error)
+    }
+}
+
+///@brief 获取虚拟地址并将其转化为对应类型的指针
+///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息
+///@return Result<NonNull<T>, VirtioPciError> 成功则返回对应类型的指针,失败则返回Error
+fn get_bar_region<T>(
+    device_bar: &PciDeviceBar,
+    struct_info: &VirtioCapabilityInfo,
+) -> Result<NonNull<T>, VirtioPciError> {
+    let bar_info = device_bar.get_bar(struct_info.bar)?;
+    let (bar_address, bar_size) = bar_info
+        .memory_address_size()
+        .ok_or(VirtioPciError::UnexpectedBarType)?;
+    if bar_address == 0 {
+        return Err(VirtioPciError::BarNotAllocated(struct_info.bar));
+    }
+    if struct_info.offset + struct_info.length > bar_size
+        || size_of::<T>() > struct_info.length as usize
+    {
+        return Err(VirtioPciError::BarOffsetOutOfRange);
+    }
+    let vaddr = (bar_info
+        .virtual_address()
+        .ok_or(VirtioPciError::BarGetVaddrFailed)?) as usize
+        + struct_info.offset as usize;
+    if vaddr % align_of::<T>() != 0 {
+        return Err(VirtioPciError::Misaligned {
+            vaddr,
+            alignment: align_of::<T>(),
+        });
+    }
+    Ok(NonNull::new((vaddr) as _).unwrap())
+}
+
+///@brief 获取虚拟地址并将其转化为对应类型的指针
+///@param device_bar 存储bar信息的结构体 struct_info 存储cfg空间的位置信息
+///@return Result<NonNull<[T]>, VirtioPciError> 成功则返回对应类型的指针切片,失败则返回Error
+fn get_bar_region_slice<T>(
+    device_bar: &PciDeviceBar,
+    struct_info: &VirtioCapabilityInfo,
+) -> Result<NonNull<[T]>, VirtioPciError> {
+    let ptr = get_bar_region::<T>(device_bar, struct_info)?;
+    let raw_slice =
+        ptr::slice_from_raw_parts_mut(ptr.as_ptr(), struct_info.length as usize / size_of::<T>());
+    Ok(NonNull::new(raw_slice).unwrap())
+}

+ 46 - 0
kernel/src/driver/virtio/virtio.c

@@ -0,0 +1,46 @@
+#include "virtio.h"
+#include <common/kprint.h>
+#include <common/errno.h>
+#include <driver/pci/pci.h>
+
+#define MAX_NET_NUM 8 // pci总线上的net设备的最大数量
+
+// 在pci总线上寻找到net设备控制器的header
+static struct pci_device_structure_header_t *net_pdevs[MAX_NET_NUM];
+static int net_pdevs_count = 0;
+static struct pci_device_structure_header_t *virtio_net_pdev;
+static int virtio_net_pdev_count = 0;
+static uint8_t NETWORK_CLASS = 0x2;
+static uint8_t ETHERNET_SUBCLASS = 0x0;
+
+/** 
+ * @brief 获取virtio-net MMIO映射的虚拟地址
+ * @param virt_addr 外部传入的虚拟地址指针
+ * @return 获取成功,返回0,失败,返回错误码
+ */
+uint8_t get_virtio_net_device(uint8_t * bus, uint8_t *device,uint8_t * function)
+{
+    // 获取所有net-pci设备的列表
+    pci_get_device_structure(NETWORK_CLASS, ETHERNET_SUBCLASS, net_pdevs, &net_pdevs_count);
+    //检测其中的virt-io-net设备
+    for(int i = 0; i < net_pdevs_count;i++) {
+        struct pci_device_structure_general_device_t *dev = net_pdevs[i];
+        if(net_pdevs[i]->Vendor_ID==0x1AF4 && net_pdevs[i]->Device_ID>=0x1000 && net_pdevs[i]->Device_ID<=0x103F && dev->Subsystem_ID==1)
+        { 
+            virtio_net_pdev=net_pdevs[i];
+            virtio_net_pdev_count++;
+            break;
+        }
+    }
+    if (virtio_net_pdev_count == 0) {
+        kwarn("There is no virtio-net device in this computer!");
+        return NOT_FOUND_DEVICE;
+    }
+      if (virtio_net_pdev->Command==0) {
+        kwarn("The virtio-net device isn't support mmio!");
+        return NOT_SUPPORTE_MMIO;
+    }
+    *bus=virtio_net_pdev->bus;
+    *device=virtio_net_pdev->device;
+    *function=virtio_net_pdev->func;
+}

+ 12 - 0
kernel/src/driver/virtio/virtio.h

@@ -0,0 +1,12 @@
+#pragma once
+#include <common/glib.h>
+
+#define GET_VIRTADDRESS_SUCCESS 0
+#define NOT_FOUND_DEVICE 1
+#define NOT_SUPPORTE_MMIO 2
+#define GET_VIRTADDRESS_FAILURE 3
+
+// 获取virtio-net 设备
+uint8_t get_virtio_net_device(uint8_t * bus, uint8_t *device,uint8_t * function);
+//寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备后续也可添加)
+void  c_virtio_probe();

+ 136 - 0
kernel/src/driver/virtio/virtio.rs

@@ -0,0 +1,136 @@
+use super::transport_pci::PciTransport;
+use super::virtio_impl::HalImpl;
+use crate::driver::pci::pci::DeviceFunction;
+use crate::include::bindings::bindings::get_virtio_net_device;
+use crate::{kdebug, kerror, kwarn};
+use alloc::{boxed::Box, collections::LinkedList};
+use virtio_drivers::device::net::VirtIONet;
+use virtio_drivers::transport::{DeviceType, Transport};
+
+//Virtio设备寻找过程中出现的问题
+enum VirtioError {
+    VirtioNetNotFound,
+}
+
+///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)(for c)
+#[no_mangle]
+pub extern "C" fn c_virtio_probe() {
+    if let Ok(virtio_list) = virtio_device_search() {
+        for device_function in virtio_list {
+            match PciTransport::new::<HalImpl>(*device_function) {
+                Ok(mut transport) => {
+                    kdebug!(
+                        "Detected virtio PCI device with device type {:?}, features {:#018x}",
+                        transport.device_type(),
+                        transport.read_device_features(),
+                    );
+                    virtio_device(transport);
+                }
+                Err(err) => {
+                    kerror!("Pci transport create failed because of error: {}", err);
+                }
+            }
+        }
+    } else {
+        kerror!("Error occured when finding virtio device!");
+    }
+}
+
+///@brief 寻找并加载所有virtio设备的驱动(目前只有virtio-net,但其他virtio设备也可添加)
+fn virtio_probe() {
+    if let Ok(virtio_list) = virtio_device_search() {
+        for device_function in virtio_list {
+            match PciTransport::new::<HalImpl>(*device_function) {
+                Ok(mut transport) => {
+                    kdebug!(
+                        "Detected virtio PCI device with device type {:?}, features {:#018x}",
+                        transport.device_type(),
+                        transport.read_device_features(),
+                    );
+                    virtio_device(transport);
+                }
+                Err(err) => {
+                    kerror!("Pci transport create failed because of error: {}", err);
+                }
+            }
+        }
+    } else {
+        kerror!("Error occured when finding virtio device!");
+    }
+}
+
+///@brief 为virtio设备寻找对应的驱动进行初始化
+fn virtio_device(transport: impl Transport) {
+    match transport.device_type() {
+        DeviceType::Block => {
+            kwarn!("Not support virtio_block device for now");
+        }
+        DeviceType::GPU => {
+            kwarn!("Not support virtio_gpu device for now");
+        }
+        DeviceType::Input => {
+            kwarn!("Not support virtio_input device for now");
+        }
+        DeviceType::Network => virtio_net(transport),
+        t => {
+            kwarn!("Unrecognized virtio device: {:?}", t);
+        }
+    }
+}
+
+///@brief virtio-net 驱动的初始化与测试
+fn virtio_net<T: Transport>(transport: T) {
+    let mut driver_net = match VirtIONet::<HalImpl, T>::new(transport) {
+        Ok(mut net) => {
+            kdebug!("Virtio-net driver init successfully.");
+            net
+        }
+        Err(_) => {
+            kerror!("VirtIONet init failed");
+            return;
+        }
+    };
+    // let mut buf = [0u8; 0x100];
+    // let len = match driver_net.recv(&mut buf)
+    // {
+    //     Ok(len) =>{len},
+    //     Err(_) =>{kerror!("virtio_net recv failed");return;}
+    // };
+    // kdebug!("recv: {:?}", &buf[..len]);
+    // match driver_net.send(&buf[..len])
+    // {
+    //     Ok(_) =>{kdebug!("virtio_net send success");},
+    //     Err(_) =>{kerror!("virtio_net send failed");return;},
+    // }
+    let mac = driver_net.mac();
+    kdebug!("virtio_net MAC={:?}", mac);
+    kdebug!("virtio-net test finished");
+}
+
+/// @brief 寻找所有的virtio设备
+/// @return Result<LinkedList<Box<DeviceFunction>>,VirtioError> 成功则返回包含所有virtio设备的链表,失败则返回err
+/// 该函数主要是为其他virtio设备预留支持
+fn virtio_device_search() -> Result<LinkedList<Box<DeviceFunction>>, VirtioError> {
+    let mut virtio_list: LinkedList<Box<DeviceFunction>> = LinkedList::new();
+    let (bus, device, function) = unsafe {
+        let mut bus: u8 = 0;
+        let mut device: u8 = 0;
+        let mut function: u8 = 0;
+        let bus_ptr = &mut bus as *mut u8;
+        let device_ptr = &mut device as *mut u8;
+        let function_ptr = &mut function as *mut u8;
+        get_virtio_net_device(bus_ptr, device_ptr, function_ptr);
+        (bus, device, function)
+    };
+    if bus == 0 && device == 0 && function == 0 {
+        kdebug!("get_virtio_net_device failed");
+        return Err(VirtioError::VirtioNetNotFound);
+    }
+    let device_function = DeviceFunction {
+        bus: bus,
+        device: device,
+        function: function,
+    };
+    virtio_list.push_back(Box::new(device_function));
+    Ok(virtio_list)
+}

+ 75 - 0
kernel/src/driver/virtio/virtio_impl.rs

@@ -0,0 +1,75 @@
+use crate::include::bindings::bindings::{
+    alloc_pages, free_pages, memory_management_struct, Page, PAGE_2M_SHIFT, PAGE_2M_SIZE,
+    PAGE_OFFSET, PAGE_SHARED, ZONE_NORMAL,
+};
+use crate::kdebug;
+use core::mem::size_of;
+use core::{ptr::NonNull};
+use virtio_drivers::{BufferDirection, Hal, PhysAddr, VirtAddr, PAGE_SIZE};
+
+pub struct HalImpl;
+impl Hal for HalImpl {
+    /// @brief 申请用于DMA的内存页
+    /// @param pages 页数(4k一页)
+    /// @return PhysAddr 获得的内存页的初始物理地址
+    fn dma_alloc(pages: usize) -> PhysAddr {
+        let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize);
+        let page_num = if reminder > 0 {
+            (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32
+        } else {
+            (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32
+        };
+
+        unsafe {
+            let pa = alloc_pages(ZONE_NORMAL, page_num, PAGE_SHARED as u64);
+            let page = *pa;
+            //kdebug!("alloc pages num:{},Phyaddr={}",page_num,page.addr_phys);
+            return page.addr_phys as PhysAddr;
+        }
+    }
+    /// @brief 释放用于DMA的内存页
+    /// @param paddr 起始物理地址 pages 页数(4k一页)
+    /// @return i32 0表示成功
+    fn dma_dealloc(paddr: PhysAddr, pages: usize) -> i32 {
+        let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize);
+        let page_num = if reminder > 0 {
+            (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32
+        } else {
+            (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32
+        };
+        unsafe {
+            let pa = (memory_management_struct.pages_struct as usize
+                + (paddr >> PAGE_2M_SHIFT) * size_of::<Page>()) as *mut Page;
+            //kdebug!("free pages num:{},Phyaddr={}",page_num,paddr);
+            free_pages(pa, page_num);
+        }
+        return 0;
+    }
+    /// @brief 物理地址转换为虚拟地址
+    /// @param paddr 起始物理地址
+    /// @return VirtAddr 虚拟地址
+    fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
+        paddr + PAGE_OFFSET as usize
+
+    }
+    /// @brief 与真实物理设备共享
+    /// @param buffer 要共享的buffer _direction:设备到driver或driver到设备
+    /// @return buffer在内存中的物理地址
+    fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr {
+        let vaddr = buffer.as_ptr() as *mut u8 as usize;
+        // Nothing to do, as the host already has access to all memory.
+        virt_to_phys(vaddr)
+    }
+    /// @brief 停止共享(让主机可以访问全部内存的话什么都不用做)
+    fn unshare(_paddr: PhysAddr, _buffer: NonNull<[u8]>, _direction: BufferDirection) {
+        // Nothing to do, as the host already has access to all memory and we didn't copy the buffer
+        // anywhere else.
+    }
+}
+
+/// @brief 虚拟地址转换为物理地址
+/// @param vaddr 虚拟地址
+/// @return PhysAddr 物理地址
+fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
+    vaddr - PAGE_OFFSET as usize
+}

+ 104 - 0
kernel/src/driver/virtio/volatile.rs

@@ -0,0 +1,104 @@
+/// An MMIO register which can only be read from.
+#[derive(Default)]
+#[repr(transparent)]
+pub struct ReadOnly<T: Copy>(T);
+
+impl<T: Copy> ReadOnly<T> {
+    /// Construct a new instance for testing.
+    pub fn new(value: T) -> Self {
+        Self(value)
+    }
+}
+
+/// An MMIO register which can only be written to.
+#[derive(Default)]
+#[repr(transparent)]
+pub struct WriteOnly<T: Copy>(T);
+
+/// An MMIO register which may be both read and written.
+#[derive(Default)]
+#[repr(transparent)]
+pub struct Volatile<T: Copy>(T);
+
+impl<T: Copy> Volatile<T> {
+    /// Construct a new instance for testing.
+    pub fn new(value: T) -> Self {
+        Self(value)
+    }
+}
+
+/// A trait implemented by MMIO registers which may be read from.
+pub trait VolatileReadable<T> {
+    /// Performs a volatile read from the MMIO register.
+    unsafe fn vread(self) -> T;
+}
+
+impl<T: Copy> VolatileReadable<T> for *const ReadOnly<T> {
+    unsafe fn vread(self) -> T {
+        self.read_volatile().0
+    }
+}
+
+impl<T: Copy> VolatileReadable<T> for *const Volatile<T> {
+    unsafe fn vread(self) -> T {
+        self.read_volatile().0
+    }
+}
+
+/// A trait implemented by MMIO registers which may be written to.
+pub trait VolatileWritable<T> {
+    /// Performs a volatile write to the MMIO register.
+    unsafe fn vwrite(self, value: T);
+}
+
+impl<T: Copy> VolatileWritable<T> for *mut WriteOnly<T> {
+    unsafe fn vwrite(self, value: T) {
+        (self as *mut T).write_volatile(value)
+    }
+}
+
+impl<T: Copy> VolatileWritable<T> for *mut Volatile<T> {
+    unsafe fn vwrite(self, value: T) {
+        (self as *mut T).write_volatile(value)
+    }
+}
+
+/// Performs a volatile read from the given field of pointer to a struct representing an MMIO region.
+///
+/// # Usage
+/// ```compile_fail
+/// # use core::ptr::NonNull;
+/// # use virtio_drivers::volatile::{ReadOnly, volread};
+/// struct MmioDevice {
+///   field: ReadOnly<u32>,
+/// }
+///
+/// let device: NonNull<MmioDevice> = NonNull::new(0x1234 as *mut MmioDevice).unwrap();
+/// let value = unsafe { volread!(device, field) };
+/// ```
+macro_rules! volread {
+    ($nonnull:expr, $field:ident) => {
+        VolatileReadable::vread(core::ptr::addr_of!((*$nonnull.as_ptr()).$field))
+    };
+}
+
+/// Performs a volatile write to the given field of pointer to a struct representing an MMIO region.
+///
+/// # Usage
+/// ```compile_fail
+/// # use core::ptr::NonNull;
+/// # use virtio_drivers::volatile::{WriteOnly, volread};
+/// struct MmioDevice {
+///   field: WriteOnly<u32>,
+/// }
+///
+/// let device: NonNull<MmioDevice> = NonNull::new(0x1234 as *mut MmioDevice).unwrap();
+/// unsafe { volwrite!(device, field, 42); }
+/// ```
+macro_rules! volwrite {
+    ($nonnull:expr, $field:ident, $value:expr) => {
+        VolatileWritable::vwrite(core::ptr::addr_of_mut!((*$nonnull.as_ptr()).$field), $value)
+    };
+}
+pub(crate) use volread;
+pub(crate) use volwrite;

+ 4 - 0
kernel/src/include/bindings/wrapper.h

@@ -31,9 +31,13 @@
 #include <include/DragonOS/refcount.h>
 #include <include/DragonOS/signal.h>
 #include <mm/mm.h>
+#include <mm/mmio.h>
 #include <mm/slab.h>
 #include <process/process.h>
 #include <sched/sched.h>
 #include <time/sleep.h>
 #include <mm/mm-types.h>
+#include <driver/pci/pci.h>
+#include <driver/virtio/virtio.h>
 #include <smp/smp.h>
+

+ 2 - 5
kernel/src/main.c

@@ -71,14 +71,11 @@ void reload_idt()
 // 初始化系统各模块
 void system_initialize()
 {
-
     c_uart_init(COM1, 115200);
     video_init();
-
     scm_init();
     textui_init();
     kinfo("Kernel Starting...");
-
     // 重新加载gdt和idt
     ul tss_item_addr = (ul)phys_2_virt(0x7c00);
 
@@ -165,7 +162,7 @@ void system_initialize()
     io_mfence();
     // current_pcb->preempt_count = 0;
     // kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
-
+    
     process_init();
     // 启用double buffer
     // scm_enable_double_buffer();  // 因为时序问题, 该函数调用被移到 initial_kernel_thread
@@ -178,7 +175,7 @@ void system_initialize()
 
     apic_timer_init();
     io_mfence();
-
+   
     // 这里不能删除,否则在O1会报错
     // while (1)
     //     pause();

+ 1 - 1
kernel/src/mm/mm.c

@@ -199,7 +199,7 @@ void mm_init()
     ZONE_NORMAL_INDEX = memory_management_struct.count_zones ;
     ZONE_UNMAPPED_INDEX = 0;
 
-    // kdebug("ZONE_DMA_INDEX=%d\tZONE_NORMAL_INDEX=%d\tZONE_UNMAPPED_INDEX=%d", ZONE_DMA_INDEX, ZONE_NORMAL_INDEX, ZONE_UNMAPPED_INDEX);
+    //kdebug("ZONE_DMA_INDEX=%d\tZONE_NORMAL_INDEX=%d\tZONE_UNMAPPED_INDEX=%d", ZONE_DMA_INDEX, ZONE_NORMAL_INDEX, ZONE_UNMAPPED_INDEX);
     //  设置内存页管理结构的地址,预留了一段空间,防止内存越界。
     memory_management_struct.end_of_struct = (ul)((ul)memory_management_struct.zones_struct + memory_management_struct.zones_struct_len + sizeof(long) * 32) & (~(sizeof(long) - 1));
 

+ 2 - 0
kernel/src/process/process.c

@@ -31,6 +31,7 @@
 #include <sched/sched.h>
 #include <syscall/syscall.h>
 #include <syscall/syscall_num.h>
+#include <driver/virtio/virtio.h>
 extern int __rust_demo_func();
 // #pragma GCC push_options
 // #pragma GCC optimize("O0")
@@ -502,6 +503,7 @@ ul initial_kernel_thread(ul arg)
     ahci_init();
     fat32_init();
     rootfs_umount();
+    c_virtio_probe();
 
     // 使用单独的内核线程来初始化usb驱动程序
     // 注释:由于目前usb驱动程序不完善,因此先将其注释掉