feat(virtio): riscv: 添加virtio-blk driver,并在riscv下能够正确挂载FAT32 (#761)

This commit is contained in:
LoGin
2024-04-23 17:19:54 +08:00
committed by GitHub
parent 0c1ef30087
commit 731bc2b32d
27 changed files with 998 additions and 124 deletions

View File

@ -72,6 +72,10 @@ impl DeviceManager {
if dev.driver().is_some() {
if self.device_is_bound(dev) {
kdebug!(
"do_device_attach: device '{}' is already bound.",
dev.name()
);
return Ok(true);
}
@ -82,6 +86,7 @@ impl DeviceManager {
return Ok(false);
}
} else {
kdebug!("do_device_attach: device '{}' is not bound.", dev.name());
let bus = dev
.bus()
.and_then(|bus| bus.upgrade())
@ -198,15 +203,9 @@ impl DeviceManager {
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#496
pub fn device_bind_driver(&self, dev: &Arc<dyn Device>) -> 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
);
if r.is_ok() {
self.device_links_force_bind(dev);
driver_manager().driver_bound(dev);
return Err(e);
} else if let Some(bus) = dev.bus().and_then(|bus| bus.upgrade()) {
bus.subsystem().bus_notifier().call_chain(
BusNotifyEvent::DriverNotBound,
@ -214,6 +213,14 @@ impl DeviceManager {
None,
);
}
if let Err(e) = r.as_ref() {
kerror!(
"device_bind_driver: driver_sysfs_add failed, dev: '{}', err: {:?}",
dev.name(),
e
);
}
return r;
}

View File

@ -806,7 +806,7 @@ impl DeviceManager {
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/core.c?fi=device_links_force_bind#1226
pub fn device_links_force_bind(&self, _dev: &Arc<dyn Device>) {
todo!("device_links_force_bind")
kwarn!("device_links_force_bind not implemented");
}
/// 把device对象的一些结构进行默认初始化

View File

@ -1 +1,2 @@
pub mod cache;
pub mod virtio_blk;

View File

@ -0,0 +1,526 @@
use core::{any::Any, fmt::Debug};
use alloc::{
string::{String, ToString},
sync::{Arc, Weak},
vec::Vec,
};
use system_error::SystemError;
use unified_init::macros::unified_init;
use virtio_drivers::device::blk::VirtIOBlk;
use crate::{
driver::{
base::{
block::{
block_device::{BlockDevice, BlockId, LBA_SIZE},
disk_info::Partition,
},
class::Class,
device::{
bus::Bus,
driver::{Driver, DriverCommonData},
Device, DeviceCommonData, DeviceId, DeviceType, IdTable,
},
kobject::{KObjType, KObject, KObjectCommonData, KObjectState, LockedKObjectState},
kset::KSet,
},
virtio::{
sysfs::{virtio_bus, virtio_device_manager, virtio_driver_manager},
transport::VirtIOTransport,
virtio_impl::HalImpl,
VirtIODevice, VirtIODeviceIndex, VirtIODriver, VIRTIO_VENDOR_ID,
},
},
filesystem::{kernfs::KernFSInode, mbr::MbrDiskPartionTable},
init::initcall::INITCALL_POSTCORE,
libs::{
rwlock::{RwLockReadGuard, RwLockWriteGuard},
spinlock::{SpinLock, SpinLockGuard},
},
};
const VIRTIO_BLK_BASENAME: &str = "virtio_blk";
static mut VIRTIO_BLK_DRIVER: Option<Arc<VirtIOBlkDriver>> = None;
#[inline(always)]
fn virtio_blk_driver() -> Arc<VirtIOBlkDriver> {
unsafe { VIRTIO_BLK_DRIVER.as_ref().unwrap().clone() }
}
/// Get the first virtio block device
#[allow(dead_code)]
pub fn virtio_blk_0() -> Option<Arc<VirtIOBlkDevice>> {
virtio_blk_driver()
.devices()
.first()
.cloned()
.map(|dev| dev.arc_any().downcast().unwrap())
}
pub fn virtio_blk(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
let device = VirtIOBlkDevice::new(transport, dev_id);
if let Some(device) = device {
kdebug!("VirtIOBlkDevice '{:?}' created", device.dev_id);
virtio_device_manager()
.device_add(device.clone() as Arc<dyn VirtIODevice>)
.expect("Add virtio blk failed");
}
}
/// virtio block device
#[derive(Debug)]
#[cast_to([sync] VirtIODevice)]
#[cast_to([sync] Device)]
pub struct VirtIOBlkDevice {
dev_id: Arc<DeviceId>,
inner: SpinLock<InnerVirtIOBlkDevice>,
locked_kobj_state: LockedKObjectState,
self_ref: Weak<Self>,
}
unsafe impl Send for VirtIOBlkDevice {}
unsafe impl Sync for VirtIOBlkDevice {}
impl VirtIOBlkDevice {
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
let device_inner = VirtIOBlk::<HalImpl, VirtIOTransport>::new(transport);
if let Err(e) = device_inner {
kerror!("VirtIOBlkDevice '{dev_id:?}' create failed: {:?}", e);
return None;
}
// !!!! 在这里临时测试virtio-blk的读写功能后续需要删除 !!!!
// 目前read会报错 `NotReady`
let device_inner: VirtIOBlk<HalImpl, VirtIOTransport> = device_inner.unwrap();
let dev = Arc::new_cyclic(|self_ref| Self {
self_ref: self_ref.clone(),
dev_id,
locked_kobj_state: LockedKObjectState::default(),
inner: SpinLock::new(InnerVirtIOBlkDevice {
device_inner,
name: None,
virtio_index: None,
device_common: DeviceCommonData::default(),
kobject_common: KObjectCommonData::default(),
}),
});
dev.set_driver(Some(Arc::downgrade(
&(virtio_blk_driver() as Arc<dyn Driver>),
)));
Some(dev)
}
fn inner(&self) -> SpinLockGuard<InnerVirtIOBlkDevice> {
self.inner.lock()
}
}
impl BlockDevice for VirtIOBlkDevice {
fn read_at_sync(
&self,
lba_id_start: BlockId,
count: usize,
buf: &mut [u8],
) -> Result<usize, SystemError> {
let mut inner = self.inner();
inner
.device_inner
.read_blocks(lba_id_start, &mut buf[..count * LBA_SIZE])
.map_err(|e| {
kerror!(
"VirtIOBlkDevice '{:?}' read_at_sync failed: {:?}",
self.dev_id,
e
);
SystemError::EIO
})?;
Ok(count)
}
fn write_at_sync(
&self,
lba_id_start: BlockId,
count: usize,
buf: &[u8],
) -> Result<usize, SystemError> {
self.inner()
.device_inner
.write_blocks(lba_id_start, &buf[..count * LBA_SIZE])
.map_err(|_| SystemError::EIO)?;
Ok(count)
}
fn sync(&self) -> Result<(), SystemError> {
Ok(())
}
fn blk_size_log2(&self) -> u8 {
9
}
fn as_any_ref(&self) -> &dyn Any {
self
}
fn device(&self) -> Arc<dyn Device> {
self.self_ref.upgrade().unwrap()
}
fn block_size(&self) -> usize {
todo!()
}
fn partitions(&self) -> Vec<Arc<Partition>> {
let device = self.self_ref.upgrade().unwrap() as Arc<dyn BlockDevice>;
let mbr_table = MbrDiskPartionTable::from_disk(device.clone())
.expect("Failed to get MBR partition table");
mbr_table.partitions(Arc::downgrade(&device))
}
}
struct InnerVirtIOBlkDevice {
device_inner: VirtIOBlk<HalImpl, VirtIOTransport>,
name: Option<String>,
virtio_index: Option<VirtIODeviceIndex>,
device_common: DeviceCommonData,
kobject_common: KObjectCommonData,
}
impl Debug for InnerVirtIOBlkDevice {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("InnerVirtIOBlkDevice").finish()
}
}
impl VirtIODevice for VirtIOBlkDevice {
fn handle_irq(
&self,
_irq: crate::exception::IrqNumber,
) -> Result<crate::exception::irqdesc::IrqReturn, system_error::SystemError> {
todo!("VirtIOBlkDevice::handle_irq")
}
fn dev_id(&self) -> &Arc<DeviceId> {
&self.dev_id
}
fn set_device_name(&self, name: String) {
self.inner().name = Some(name);
}
fn device_name(&self) -> String {
self.inner()
.name
.clone()
.unwrap_or_else(|| VIRTIO_BLK_BASENAME.to_string())
}
fn set_virtio_device_index(&self, index: VirtIODeviceIndex) {
self.inner().virtio_index = Some(index);
}
fn virtio_device_index(&self) -> Option<VirtIODeviceIndex> {
self.inner().virtio_index
}
fn device_type_id(&self) -> u32 {
virtio_drivers::transport::DeviceType::Block as u32
}
fn vendor(&self) -> u32 {
VIRTIO_VENDOR_ID.into()
}
}
impl Device for VirtIOBlkDevice {
fn dev_type(&self) -> DeviceType {
DeviceType::Net
}
fn id_table(&self) -> IdTable {
IdTable::new(VIRTIO_BLK_BASENAME.to_string(), None)
}
fn bus(&self) -> Option<Weak<dyn Bus>> {
self.inner().device_common.bus.clone()
}
fn set_bus(&self, bus: Option<Weak<dyn Bus>>) {
self.inner().device_common.bus = bus;
}
fn class(&self) -> Option<Arc<dyn Class>> {
let mut guard = self.inner();
let r = guard.device_common.class.clone()?.upgrade();
if r.is_none() {
guard.device_common.class = None;
}
return r;
}
fn set_class(&self, class: Option<Weak<dyn Class>>) {
self.inner().device_common.class = class;
}
fn driver(&self) -> Option<Arc<dyn Driver>> {
let r = self.inner().device_common.driver.clone()?.upgrade();
if r.is_none() {
self.inner().device_common.driver = None;
}
return r;
}
fn set_driver(&self, driver: Option<Weak<dyn Driver>>) {
self.inner().device_common.driver = driver;
}
fn is_dead(&self) -> bool {
false
}
fn can_match(&self) -> bool {
self.inner().device_common.can_match
}
fn set_can_match(&self, can_match: bool) {
self.inner().device_common.can_match = can_match;
}
fn state_synced(&self) -> bool {
true
}
}
impl KObject for VirtIOBlkDevice {
fn as_any_ref(&self) -> &dyn Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner().kobject_common.kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner().kobject_common.kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner().kobject_common.parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner().kobject_common.parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner().kobject_common.kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner().kobject_common.kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
self.inner().kobject_common.kobj_type
}
fn name(&self) -> String {
self.device_name()
}
fn set_name(&self, _name: String) {
// do nothing
}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.locked_kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.locked_kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.locked_kobj_state.write() = state;
}
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner().kobject_common.kobj_type = ktype;
}
}
#[unified_init(INITCALL_POSTCORE)]
fn virtio_blk_driver_init() -> Result<(), SystemError> {
let driver = VirtIOBlkDriver::new();
virtio_driver_manager()
.register(driver.clone() as Arc<dyn VirtIODriver>)
.expect("Add virtio net driver failed");
unsafe {
VIRTIO_BLK_DRIVER = Some(driver);
}
return Ok(());
}
#[derive(Debug)]
#[cast_to([sync] VirtIODriver)]
#[cast_to([sync] Driver)]
struct VirtIOBlkDriver {
inner: SpinLock<InnerVirtIOBlkDriver>,
kobj_state: LockedKObjectState,
}
impl VirtIOBlkDriver {
pub fn new() -> Arc<Self> {
let inner = InnerVirtIOBlkDriver {
driver_common: DriverCommonData::default(),
kobj_common: KObjectCommonData::default(),
};
Arc::new(VirtIOBlkDriver {
inner: SpinLock::new(inner),
kobj_state: LockedKObjectState::default(),
})
}
fn inner(&self) -> SpinLockGuard<InnerVirtIOBlkDriver> {
return self.inner.lock();
}
}
#[derive(Debug)]
struct InnerVirtIOBlkDriver {
driver_common: DriverCommonData,
kobj_common: KObjectCommonData,
}
impl VirtIODriver for VirtIOBlkDriver {
fn probe(&self, device: &Arc<dyn VirtIODevice>) -> Result<(), SystemError> {
let _dev = device
.clone()
.arc_any()
.downcast::<VirtIOBlkDevice>()
.map_err(|_| {
kerror!(
"VirtIOBlkDriver::probe() failed: device is not a VirtIO block device. Device: '{:?}'",
device.name()
);
SystemError::EINVAL
})?;
return Ok(());
}
}
impl Driver for VirtIOBlkDriver {
fn id_table(&self) -> Option<IdTable> {
Some(IdTable::new(VIRTIO_BLK_BASENAME.to_string(), None))
}
fn add_device(&self, device: Arc<dyn Device>) {
let iface = device
.arc_any()
.downcast::<VirtIOBlkDevice>()
.expect("VirtIOBlkDriver::add_device() failed: device is not a VirtIOBlkDevice");
self.inner()
.driver_common
.devices
.push(iface as Arc<dyn Device>);
}
fn delete_device(&self, device: &Arc<dyn Device>) {
let _iface = device
.clone()
.arc_any()
.downcast::<VirtIOBlkDevice>()
.expect("VirtIOBlkDriver::delete_device() failed: device is not a VirtIOBlkDevice");
let mut guard = self.inner();
let index = guard
.driver_common
.devices
.iter()
.position(|dev| Arc::ptr_eq(device, dev))
.expect("VirtIOBlkDriver::delete_device() failed: device not found");
guard.driver_common.devices.remove(index);
}
fn devices(&self) -> Vec<Arc<dyn Device>> {
self.inner().driver_common.devices.clone()
}
fn bus(&self) -> Option<Weak<dyn Bus>> {
Some(Arc::downgrade(&virtio_bus()) as Weak<dyn Bus>)
}
fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
// do nothing
}
}
impl KObject for VirtIOBlkDriver {
fn as_any_ref(&self) -> &dyn Any {
self
}
fn set_inode(&self, inode: Option<Arc<KernFSInode>>) {
self.inner().kobj_common.kern_inode = inode;
}
fn inode(&self) -> Option<Arc<KernFSInode>> {
self.inner().kobj_common.kern_inode.clone()
}
fn parent(&self) -> Option<Weak<dyn KObject>> {
self.inner().kobj_common.parent.clone()
}
fn set_parent(&self, parent: Option<Weak<dyn KObject>>) {
self.inner().kobj_common.parent = parent;
}
fn kset(&self) -> Option<Arc<KSet>> {
self.inner().kobj_common.kset.clone()
}
fn set_kset(&self, kset: Option<Arc<KSet>>) {
self.inner().kobj_common.kset = kset;
}
fn kobj_type(&self) -> Option<&'static dyn KObjType> {
self.inner().kobj_common.kobj_type
}
fn set_kobj_type(&self, ktype: Option<&'static dyn KObjType>) {
self.inner().kobj_common.kobj_type = ktype;
}
fn name(&self) -> String {
VIRTIO_BLK_BASENAME.to_string()
}
fn set_name(&self, _name: String) {
// do nothing
}
fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
self.kobj_state.read()
}
fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
self.kobj_state.write()
}
fn set_kobj_state(&self, state: KObjectState) {
*self.kobj_state.write() = state;
}
}

View File

@ -1,7 +1,6 @@
use super::{_port, hba::HbaCmdTable, virt_2_phys};
use crate::driver::base::block::block_device::{BlockDevice, BlockId};
use crate::driver::base::block::disk_info::Partition;
use crate::driver::base::block::SeekFrom;
use crate::driver::base::class::Class;
use crate::driver::base::device::bus::Bus;
@ -14,9 +13,8 @@ use crate::driver::disk::ahci::HBA_PxIS_TFES;
use crate::filesystem::kernfs::KernFSInode;
use crate::filesystem::mbr::MbrDiskPartionTable;
use crate::kdebug;
use crate::libs::rwlock::{RwLockReadGuard, RwLockWriteGuard};
use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor};
use crate::libs::spinlock::SpinLock;
use crate::mm::{phys_2_virt, verify_area, VirtAddr};
use crate::{
driver::disk::ahci::hba::{
@ -69,7 +67,7 @@ impl AhciDisk {
buf: &mut [u8],
) -> Result<usize, SystemError> {
assert!((buf.len() & 511) == 0);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
let check_length = ((count - 1) >> 4) + 1; // prdt length
if count * 512 > buf.len() || check_length > 8_usize {
kerror!("ahci read: e2big");
@ -204,7 +202,7 @@ impl AhciDisk {
buf.copy_from_slice(kbuf.as_ref().unwrap());
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
// successfully read
return Ok(count * 512);
}
@ -216,7 +214,7 @@ impl AhciDisk {
buf: &[u8],
) -> Result<usize, SystemError> {
assert!((buf.len() & 511) == 0);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
let check_length = ((count - 1) >> 4) + 1; // prdt length
if count * 512 > buf.len() || check_length > 8 {
// 不可能的操作
@ -235,7 +233,7 @@ impl AhciDisk {
return Err(SystemError::EIO);
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
#[allow(unused_unsafe)]
let cmdheader: &mut HbaCmdHeader = unsafe {
(phys_2_virt(
@ -244,7 +242,7 @@ impl AhciDisk {
.as_mut()
.unwrap()
};
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
volatile_write_bit!(
cmdheader.cfl,
@ -256,7 +254,7 @@ impl AhciDisk {
volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count
// 设置数据存放地址
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
let mut buf_ptr = buf as *const [u8] as *mut usize as usize;
// 由于目前的内存管理机制无法把用户空间的内存地址转换为物理地址,所以只能先把数据拷贝到内核空间
@ -282,7 +280,7 @@ impl AhciDisk {
.unwrap()
};
let mut tmp_count = count;
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
unsafe {
// 清空整个table的旧数据
@ -343,7 +341,7 @@ impl AhciDisk {
}
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
// successfully read
return Ok(count * 512);
}
@ -362,70 +360,29 @@ impl LockedAhciDisk {
port_num: u8,
) -> Result<Arc<LockedAhciDisk>, SystemError> {
// 构建磁盘结构体
let result: Arc<LockedAhciDisk> = Arc::new(LockedAhciDisk(SpinLock::new(AhciDisk {
name,
flags,
partitions: Default::default(),
ctrl_num,
port_num,
self_ref: Weak::default(),
})));
let result: Arc<LockedAhciDisk> = Arc::new_cyclic(|self_ref| {
LockedAhciDisk(SpinLock::new(AhciDisk {
name,
flags,
partitions: Default::default(),
ctrl_num,
port_num,
self_ref: self_ref.clone(),
}))
});
let table: MbrDiskPartionTable = result.read_mbr_table()?;
// 求出有多少可用分区
for i in 0..4 {
compiler_fence(Ordering::SeqCst);
if table.dpte[i].part_type != 0 {
let w = Arc::downgrade(&result);
result.0.lock().partitions.push(Partition::new(
table.dpte[i].starting_sector() as u64,
table.dpte[i].starting_lba as u64,
table.dpte[i].total_sectors as u64,
w,
i as u16,
));
}
}
result.0.lock().self_ref = Arc::downgrade(&result);
let partitions = table.partitions(Arc::downgrade(&result) as Weak<dyn BlockDevice>);
result.0.lock().partitions = partitions;
return Ok(result);
}
/// @brief: 从磁盘中读取 MBR 分区表结构体 TODO: Cursor
/// @brief: 从磁盘中读取 MBR 分区表结构体
pub fn read_mbr_table(&self) -> Result<MbrDiskPartionTable, SystemError> {
let mut table: MbrDiskPartionTable = Default::default();
// 数据缓冲区
let mut buf: Vec<u8> = vec![0; size_of::<MbrDiskPartionTable>()];
buf.resize(size_of::<MbrDiskPartionTable>(), 0);
self.read_at_sync(0, 1, &mut buf)?;
// 创建 Cursor 用于按字节读取
let mut cursor = VecCursor::new(buf);
cursor.seek(SeekFrom::SeekCurrent(446))?;
for i in 0..4 {
kdebug!("infomation of partition {}:\n", i);
table.dpte[i].flags = cursor.read_u8()?;
table.dpte[i].starting_head = cursor.read_u8()?;
table.dpte[i].starting_sector_cylinder = cursor.read_u16()?;
table.dpte[i].part_type = cursor.read_u8()?;
table.dpte[i].ending_head = cursor.read_u8()?;
table.dpte[i].ending_sector_cylingder = cursor.read_u16()?;
table.dpte[i].starting_lba = cursor.read_u32()?;
table.dpte[i].total_sectors = cursor.read_u32()?;
kdebug!("dpte[i] = {:?}", table.dpte[i]);
}
table.bs_trailsig = cursor.read_u16()?;
// kdebug!("bs_trailsig = {}", unsafe {
// read_unaligned(addr_of!(table.bs_trailsig))
// });
return Ok(table);
let disk = self.0.lock().self_ref.upgrade().unwrap() as Arc<dyn BlockDevice>;
MbrDiskPartionTable::from_disk(disk)
}
}

View File

@ -46,6 +46,7 @@ pub trait SerioDriver: Driver {
///todo: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/input/serio/serio.c#810
#[allow(dead_code)]
#[inline(always)]
pub fn serio_driver_manager() -> &'static SerioDriverManager {
&SerioDriverManager

View File

@ -128,6 +128,7 @@ impl Debug for VirtIONicDeviceInner {
}
#[cast_to([sync] VirtIODevice)]
#[cast_to([sync] Device)]
pub struct VirtioInterface {
device_inner: VirtIONicDeviceInnerWrapper,
iface_id: usize,
@ -293,7 +294,7 @@ impl Device for VirtioInterface {
}
fn can_match(&self) -> bool {
true
self.inner().device_common.can_match
}
fn set_can_match(&self, can_match: bool) {
@ -552,8 +553,10 @@ fn virtio_net_driver_init() -> Result<(), SystemError> {
return Ok(());
}
#[derive(Debug)]
#[cast_to([sync] VirtIODriver)]
#[cast_to([sync] Driver)]
struct VirtIONetDriver {
inner: SpinLock<InnerVirtIODriver>,
kobj_state: LockedKObjectState,

View File

@ -76,7 +76,7 @@ impl OpenFirmwareFdtDriver {
/// 获取FDT的引用
pub fn fdt_ref(&self) -> Result<Fdt<'static>, SystemError> {
let fdt_vaddr = boot_params().read().fdt().unwrap();
let fdt_vaddr = boot_params().read().fdt().ok_or(SystemError::ENODEV)?;
let fdt: Fdt<'_> = unsafe {
fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
kerror!("failed to parse fdt, err={:?}", e);
@ -213,10 +213,7 @@ impl OpenFirmwareFdtDriver {
use crate::{
arch::MMArch,
libs::align::page_align_down,
mm::{
memblock::{mem_block_manager, MemBlockManager},
MemoryManagementArch, PhysAddr,
},
mm::{memblock::MemBlockManager, MemoryManagementArch},
};
let mut base = base as usize;

View File

@ -1 +1,2 @@
#[cfg(target_arch = "x86_64")]
pub mod hpet;

View File

@ -1,3 +1,30 @@
use fdt::node::FdtNode;
use system_error::SystemError;
use crate::driver::{
open_firmware::fdt::open_firmware_fdt_driver, virtio::transport_mmio::VirtIOMmioTransport,
};
use super::{transport::VirtIOTransport, virtio::virtio_device_init};
pub(super) fn virtio_probe_mmio() {
// todo: implement virtio_probe_mmio
if let Err(e) = do_probe_virtio_mmio() {
kerror!("virtio_probe_mmio failed: {:?}", e);
}
}
fn do_probe_virtio_mmio() -> Result<(), SystemError> {
let fdt = open_firmware_fdt_driver().fdt_ref()?;
let do_check = |node: FdtNode| -> Result<(), SystemError> {
let mmio_transport = VirtIOMmioTransport::new(node)?;
let device_id = mmio_transport.device_id();
virtio_device_init(VirtIOTransport::Mmio(mmio_transport), device_id);
Ok(())
};
for node in open_firmware_fdt_driver().find_node_by_compatible(&fdt, "virtio,mmio") {
do_check(node).ok();
}
Ok(())
}

View File

@ -9,6 +9,7 @@ pub(super) mod irq;
pub mod mmio;
pub mod sysfs;
pub mod transport;
pub mod transport_mmio;
pub mod transport_pci;
#[allow(clippy::module_inception)]
pub mod virtio;

View File

@ -1,15 +1,17 @@
use virtio_drivers::transport::Transport;
use super::transport_pci::PciTransport;
use super::{transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport};
pub enum VirtIOTransport {
Pci(PciTransport),
Mmio(VirtIOMmioTransport),
}
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"),
VirtIOTransport::Mmio(_) => write!(f, "VirtIOTransport::Mmio"),
}
}
}
@ -19,6 +21,7 @@ impl Transport for VirtIOTransport {
fn finish_init(&mut self) {
match self {
VirtIOTransport::Pci(transport) => transport.finish_init(),
VirtIOTransport::Mmio(transport) => transport.finish_init(),
}
}
@ -26,6 +29,7 @@ impl Transport for VirtIOTransport {
fn device_type(&self) -> virtio_drivers::transport::DeviceType {
match self {
VirtIOTransport::Pci(transport) => transport.device_type(),
VirtIOTransport::Mmio(transport) => transport.device_type(),
}
}
@ -33,6 +37,7 @@ impl Transport for VirtIOTransport {
fn read_device_features(&mut self) -> u64 {
match self {
VirtIOTransport::Pci(transport) => transport.read_device_features(),
VirtIOTransport::Mmio(transport) => transport.read_device_features(),
}
}
@ -40,6 +45,7 @@ impl Transport for VirtIOTransport {
fn write_driver_features(&mut self, driver_features: u64) {
match self {
VirtIOTransport::Pci(transport) => transport.write_driver_features(driver_features),
VirtIOTransport::Mmio(transport) => transport.write_driver_features(driver_features),
}
}
@ -47,6 +53,7 @@ impl Transport for VirtIOTransport {
fn max_queue_size(&mut self, queue: u16) -> u32 {
match self {
VirtIOTransport::Pci(transport) => transport.max_queue_size(queue),
VirtIOTransport::Mmio(transport) => transport.max_queue_size(queue),
}
}
@ -54,6 +61,7 @@ impl Transport for VirtIOTransport {
fn notify(&mut self, queue: u16) {
match self {
VirtIOTransport::Pci(transport) => transport.notify(queue),
VirtIOTransport::Mmio(transport) => transport.notify(queue),
}
}
@ -61,6 +69,7 @@ impl Transport for VirtIOTransport {
fn get_status(&self) -> virtio_drivers::transport::DeviceStatus {
match self {
VirtIOTransport::Pci(transport) => transport.get_status(),
VirtIOTransport::Mmio(transport) => transport.get_status(),
}
}
@ -68,6 +77,7 @@ impl Transport for VirtIOTransport {
fn set_status(&mut self, status: virtio_drivers::transport::DeviceStatus) {
match self {
VirtIOTransport::Pci(transport) => transport.set_status(status),
VirtIOTransport::Mmio(transport) => transport.set_status(status),
}
}
@ -75,6 +85,7 @@ impl Transport for VirtIOTransport {
fn set_guest_page_size(&mut self, guest_page_size: u32) {
match self {
VirtIOTransport::Pci(transport) => transport.set_guest_page_size(guest_page_size),
VirtIOTransport::Mmio(transport) => transport.set_guest_page_size(guest_page_size),
}
}
@ -82,6 +93,7 @@ impl Transport for VirtIOTransport {
fn requires_legacy_layout(&self) -> bool {
match self {
VirtIOTransport::Pci(transport) => transport.requires_legacy_layout(),
VirtIOTransport::Mmio(transport) => transport.requires_legacy_layout(),
}
}
@ -98,6 +110,9 @@ impl Transport for VirtIOTransport {
VirtIOTransport::Pci(transport) => {
transport.queue_set(queue, size, descriptors, driver_area, device_area)
}
VirtIOTransport::Mmio(transport) => {
transport.queue_set(queue, size, descriptors, driver_area, device_area)
}
}
}
@ -105,6 +120,7 @@ impl Transport for VirtIOTransport {
fn queue_unset(&mut self, queue: u16) {
match self {
VirtIOTransport::Pci(transport) => transport.queue_unset(queue),
VirtIOTransport::Mmio(transport) => transport.queue_unset(queue),
}
}
@ -112,6 +128,7 @@ impl Transport for VirtIOTransport {
fn queue_used(&mut self, queue: u16) -> bool {
match self {
VirtIOTransport::Pci(transport) => transport.queue_used(queue),
VirtIOTransport::Mmio(transport) => transport.queue_used(queue),
}
}
@ -119,6 +136,7 @@ impl Transport for VirtIOTransport {
fn ack_interrupt(&mut self) -> bool {
match self {
VirtIOTransport::Pci(transport) => transport.ack_interrupt(),
VirtIOTransport::Mmio(transport) => transport.ack_interrupt(),
}
}
@ -126,6 +144,7 @@ impl Transport for VirtIOTransport {
fn config_space<T: 'static>(&self) -> virtio_drivers::Result<core::ptr::NonNull<T>> {
match self {
VirtIOTransport::Pci(transport) => transport.config_space(),
VirtIOTransport::Mmio(transport) => transport.config_space(),
}
}
}

View File

@ -0,0 +1,157 @@
use core::ptr::NonNull;
use alloc::sync::Arc;
use fdt::node::FdtNode;
use system_error::SystemError;
use virtio_drivers::transport::{
mmio::{MmioTransport, VirtIOHeader},
Transport,
};
use crate::{
arch::MMArch,
driver::base::device::DeviceId,
exception::HardwareIrqNumber,
libs::align::page_align_up,
mm::{
mmio_buddy::{mmio_pool, MMIOSpaceGuard},
MemoryManagementArch, PhysAddr,
},
};
pub struct VirtIOMmioTransport {
mmio_transport: MmioTransport,
_mmio_guard: MMIOSpaceGuard,
irq: HardwareIrqNumber,
device_id: Arc<DeviceId>,
}
impl VirtIOMmioTransport {
pub fn new(node: FdtNode) -> Result<Self, SystemError> {
let reg = node
.reg()
.ok_or(SystemError::EINVAL)?
.next()
.ok_or(SystemError::EINVAL)?;
let paddr = reg.starting_address as usize;
let size = reg.size.unwrap_or(0);
let page_offset = paddr % MMArch::PAGE_SIZE;
let paddr = paddr - page_offset;
let size = page_align_up(size + page_offset);
let irq = node
.interrupts()
.ok_or(SystemError::EINVAL)?
.next()
.ok_or(SystemError::EINVAL)?;
let device_id = DeviceId::new(None, Some(format!("virtio_mmio_{:#X}", paddr))).unwrap();
let mmio_guard = mmio_pool().create_mmio(size)?;
unsafe { mmio_guard.map_phys(PhysAddr::new(paddr), size) }?;
let vaddr = mmio_guard.vaddr() + page_offset;
let header = NonNull::new(vaddr.data() as *mut VirtIOHeader).unwrap();
match unsafe { MmioTransport::new(header) } {
Ok(mmio_transport) => {
kinfo!( "Detected virtio MMIO device with vendor id {:#X}, device type {:?}, version {:?}, hw irq: {}",
mmio_transport.vendor_id(),
mmio_transport.device_type(),
mmio_transport.version(),
irq as u32
);
Ok(Self {
mmio_transport,
_mmio_guard: mmio_guard,
irq: HardwareIrqNumber::new(irq as u32),
device_id,
})
}
Err(_) => {
// kwarn!("MmioTransport::new failed: {:?}", e);
Err(SystemError::EINVAL)
}
}
}
#[allow(dead_code)]
#[inline]
pub fn irq(&self) -> HardwareIrqNumber {
self.irq
}
pub fn device_id(&self) -> Arc<DeviceId> {
self.device_id.clone()
}
}
impl Transport for VirtIOMmioTransport {
fn device_type(&self) -> virtio_drivers::transport::DeviceType {
self.mmio_transport.device_type()
}
fn read_device_features(&mut self) -> u64 {
self.mmio_transport.read_device_features()
}
fn write_driver_features(&mut self, driver_features: u64) {
self.mmio_transport.write_driver_features(driver_features)
}
fn max_queue_size(&mut self, queue: u16) -> u32 {
self.mmio_transport.max_queue_size(queue)
}
fn notify(&mut self, queue: u16) {
self.mmio_transport.notify(queue)
}
fn get_status(&self) -> virtio_drivers::transport::DeviceStatus {
self.mmio_transport.get_status()
}
fn set_status(&mut self, status: virtio_drivers::transport::DeviceStatus) {
self.mmio_transport.set_status(status)
}
fn set_guest_page_size(&mut self, guest_page_size: u32) {
self.mmio_transport.set_guest_page_size(guest_page_size)
}
fn requires_legacy_layout(&self) -> bool {
self.mmio_transport.requires_legacy_layout()
}
fn queue_set(
&mut self,
queue: u16,
size: u32,
descriptors: virtio_drivers::PhysAddr,
driver_area: virtio_drivers::PhysAddr,
device_area: virtio_drivers::PhysAddr,
) {
self.mmio_transport
.queue_set(queue, size, descriptors, driver_area, device_area)
}
fn queue_unset(&mut self, queue: u16) {
self.mmio_transport.queue_unset(queue)
}
fn queue_used(&mut self, queue: u16) -> bool {
self.mmio_transport.queue_used(queue)
}
fn ack_interrupt(&mut self) -> bool {
self.mmio_transport.ack_interrupt()
}
fn config_space<T: 'static>(&self) -> virtio_drivers::Result<core::ptr::NonNull<T>> {
self.mmio_transport.config_space()
}
fn finish_init(&mut self) {
self.mmio_transport.finish_init()
}
}

View File

@ -2,6 +2,7 @@ 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::block::virtio_blk::virtio_blk;
use crate::driver::net::virtio_net::virtio_net;
use crate::driver::pci::pci::{
get_pci_device_structures_mut_by_vendor_id, PciDeviceStructure,
@ -17,10 +18,12 @@ use virtio_drivers::transport::{DeviceType, Transport};
///@brief 寻找并加载所有virtio设备的驱动目前只有virtio-net但其他virtio设备也可添加
pub fn virtio_probe() {
#[cfg(not(target_arch = "riscv64"))]
virtio_probe_pci();
virtio_probe_mmio();
}
#[allow(dead_code)]
fn virtio_probe_pci() {
let mut list = PCI_DEVICE_LINKEDLIST.write();
let virtio_list = virtio_device_search(&mut list);
@ -45,11 +48,9 @@ fn virtio_probe_pci() {
}
///@brief 为virtio设备寻找对应的驱动进行初始化
fn virtio_device_init(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
pub(super) fn virtio_device_init(transport: VirtIOTransport, dev_id: Arc<DeviceId>) {
match transport.device_type() {
DeviceType::Block => {
kwarn!("Not support virtio_block device for now");
}
DeviceType::Block => virtio_blk(transport, dev_id),
DeviceType::GPU => {
kwarn!("Not support virtio_gpu device for now");
}

View File

@ -79,8 +79,8 @@ unsafe impl Hal for HalImpl {
/// @brief mmio物理地址转换为虚拟地址不需要使用
/// @param paddr 起始物理地址
/// @return NonNull<u8> 虚拟地址的指针
unsafe fn mmio_phys_to_virt(_paddr: virtio_drivers::PhysAddr, _size: usize) -> NonNull<u8> {
NonNull::new((0) as _).unwrap()
unsafe fn mmio_phys_to_virt(paddr: virtio_drivers::PhysAddr, _size: usize) -> NonNull<u8> {
NonNull::new((MMArch::phys_2_virt(PhysAddr::new(paddr))).unwrap().data() as _).unwrap()
}
/// @brief 与真实物理设备共享
/// @param buffer 要共享的buffer _direction设备到driver或driver到设备