diff --git a/kernel/src/drivers/block/mod.rs b/kernel/src/drivers/block/mod.rs index 04d3c79d75ddb09ce4a30e99c87e126199f66b5e..30667673a3123cbf7ea7f044279dca7b63365bf1 100644 --- a/kernel/src/drivers/block/mod.rs +++ b/kernel/src/drivers/block/mod.rs @@ -1,12 +1,13 @@ //! å—设备驱动层 mod virtio_blk; +mod virtio_impl; pub use virtio_blk::VirtIOBlock; +use crate::board::BlockDeviceImpl; use alloc::sync::Arc; use fat32::BlockDevice; -use crate::board::BlockDeviceImpl; lazy_static! { pub static ref BLOCK_DEVICE: Arc<dyn BlockDevice> = Arc::new(BlockDeviceImpl::new()); diff --git a/kernel/src/drivers/block/virtio_blk.rs b/kernel/src/drivers/block/virtio_blk.rs index 1bfa7f15e75428f90536faa69e670709ddc5f964..a3091a81cc4f1ec48cb5a920e58d1493e9197382 100644 --- a/kernel/src/drivers/block/virtio_blk.rs +++ b/kernel/src/drivers/block/virtio_blk.rs @@ -8,23 +8,46 @@ use crate::{ VirtAddr, }, }; +use alloc::sync::Arc; use alloc::vec::Vec; +use core::ptr::NonNull; use spin::Mutex; -use virtio_drivers::{VirtIOBlk, VirtIOHeader}; +use virtio_drivers::{ + device::blk::VirtIOBlk, + transport::{ + self, + mmio::{MmioTransport, VirtIOHeader}, + DeviceType, Transport, + }, +}; + +use super::virtio_impl::HalImpl; #[allow(unused)] const VIRTIO0: usize = 0x10001000; -lazy_static! { - static ref QUEUE_FRAMES: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new()); -} - /// VirtIO 总线架构下的å—设备 -/// +/// /// å°† `virtio-drivers` crate æä¾›çš„ VirtIO å—设备抽象 `VirtIOBlk` 包装为我们自己的 `VirtIOBlock` -/// -/// å®žè´¨ä¸Šåªæ˜¯åŠ ä¸Šäº†ä¸€å±‚äº’æ–¥é”,生æˆä¸€ä¸ªæ–°çš„类型æ¥å®žçް fat32 需è¦çš„ `BlockDevice` Trait -pub struct VirtIOBlock(Mutex<VirtIOBlk<'static>>); +pub struct VirtIOBlock(Mutex<VirtIOBlk<HalImpl, MmioTransport>>); + +unsafe impl Send for VirtIOBlock {} +unsafe impl Sync for VirtIOBlock {} + +impl VirtIOBlock { + pub fn new() -> Self { + let header = NonNull::new(VIRTIO0 as *mut VirtIOHeader).unwrap(); + let mut blk = match unsafe { MmioTransport::new(header) } { + Err(e) => { + panic!("Error creating VirtIO MMIO transport: {}", e) + } + Ok(transport) => VirtIOBlk::<HalImpl, MmioTransport>::new(transport) + .expect("failed to create blk driver"), + }; + + Self(Mutex::new(blk)) + } +} impl BlockDevice for VirtIOBlock { fn read_block(&self, block_id: usize, buf: &mut [u8]) { @@ -45,51 +68,51 @@ impl BlockDevice for VirtIOBlock { } } -impl VirtIOBlock { - #[allow(unused)] - pub fn new() -> Self { - unsafe { - Self(Mutex::new( - // VirtIOHeader 实际上就代表以 MMIO æ–¹å¼è®¿é—® VirtIO 设备所需的一组设备寄å˜å™¨ - VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(), - )) - } - } -} - -#[no_mangle] -pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr { - let mut ppn_base = PhysPageNum(0); - for i in 0..pages { - let frame = alloc_frame().unwrap(); - if i == 0 { - ppn_base = frame.ppn; - } - assert_eq!(frame.ppn.0, ppn_base.0 + i); - QUEUE_FRAMES.lock().push(frame); - } - ppn_base.into() -} - -#[no_mangle] -pub extern "C" fn virtio_dma_dealloc(pa: PhysAddr, pages: usize) -> i32 { - let mut ppn_base: PhysPageNum = pa.into(); - for _ in 0..pages { - dealloc_frame(ppn_base); - ppn_base.step(); - } - - 0 -} - -#[no_mangle] -pub extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr { - VirtAddr(paddr.0) -} - -#[no_mangle] -pub extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr { - PageTable::from_token(kernel_token!()) - .translate_va(vaddr) - .unwrap() -} +// use virtio_drivers::{VirtIOBlk, VirtIOHeader}; +// lazy_static! { +// static ref QUEUE_FRAMES: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new()); +// } +// pub struct VirtIOBlock(Mutex<VirtIOBlk<'static>>); +// impl VirtIOBlock { +// #[allow(unused)] +// pub fn new() -> Self { +// unsafe { +// Self(Mutex::new( +// // VirtIOHeader 实际上就代表以 MMIO æ–¹å¼è®¿é—® VirtIO 设备所需的一组设备寄å˜å™¨ +// VirtIOBlk::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(), +// )) +// } +// } +// } +// #[no_mangle] +// pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr { +// let mut ppn_base = PhysPageNum(0); +// for i in 0..pages { +// let frame = alloc_frame().unwrap(); +// if i == 0 { +// ppn_base = frame.ppn; +// } +// assert_eq!(frame.ppn.0, ppn_base.0 + i); +// QUEUE_FRAMES.lock().push(frame); +// } +// ppn_base.into() +// } +// #[no_mangle] +// pub extern "C" fn virtio_dma_dealloc(pa: PhysAddr, pages: usize) -> i32 { +// let mut ppn_base: PhysPageNum = pa.into(); +// for _ in 0..pages { +// dealloc_frame(ppn_base); +// ppn_base.step(); +// } +// 0 +// } +// #[no_mangle] +// pub extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr { +// VirtAddr(paddr.0) +// } +// #[no_mangle] +// pub extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr { +// PageTable::from_token(kernel_token!()) +// .translate_va(vaddr) +// .unwrap() +// } diff --git a/kernel/src/drivers/block/virtio_impl.rs b/kernel/src/drivers/block/virtio_impl.rs new file mode 100644 index 0000000000000000000000000000000000000000..ac1ea3512c33c441dd97035c1bfb4279722e814d --- /dev/null +++ b/kernel/src/drivers/block/virtio_impl.rs @@ -0,0 +1,80 @@ +use core::{ + ptr::NonNull, + sync::atomic::{AtomicUsize, Ordering}, +}; +use lazy_static::lazy_static; +use virtio_drivers::{BufferDirection, Hal, PhysAddr, PAGE_SIZE}; + +use crate::{ + kernel_token, + mm::{ + alloc_frame, dealloc_frame, FrameTracker, PageTable, PhysAddr as KPhysAddr, PhysPageNum, + StepByOne, VirtAddr, + }, +}; +use alloc::vec::Vec; +use spin::Mutex; + +lazy_static! { + static ref DMA_PADDR: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new()); +} + +pub struct HalImpl; + +unsafe impl Hal for HalImpl { + #[no_mangle] + fn dma_alloc(pages: usize, _direction: BufferDirection) -> (PhysAddr, NonNull<u8>) { + let mut ppn_base = PhysPageNum(0); + for i in 0..pages { + let frame = alloc_frame().unwrap(); + if i == 0 { + ppn_base = frame.ppn; + } + assert_eq!(frame.ppn.0, ppn_base.0 + i); + DMA_PADDR.lock().push(frame); + } + let kpaddr: KPhysAddr = ppn_base.into(); + let paddr: PhysAddr = kpaddr.0; + + crate::info!("alloc DMA: paddr={:#x}, pages={}", paddr, pages); + let vaddr = NonNull::new(paddr as _).unwrap(); + (paddr, vaddr) + } + + #[no_mangle] + unsafe fn dma_dealloc(paddr: PhysAddr, _vaddr: NonNull<u8>, pages: usize) -> i32 { + let pa: KPhysAddr = paddr.into(); + let mut ppn_base: PhysPageNum = pa.into(); + for _ in 0..pages { + dealloc_frame(ppn_base); + ppn_base.step(); + } + crate::info!("dealloc DMA: paddr={:#x}, pages={}", paddr, pages); + 0 + } + + #[no_mangle] + unsafe fn mmio_phys_to_virt(paddr: PhysAddr, _size: usize) -> NonNull<u8> { + NonNull::new(paddr as _).unwrap() + } + + #[no_mangle] + unsafe 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) + } + + #[no_mangle] + unsafe 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. + } +} + +fn virt_to_phys(vaddr: usize) -> PhysAddr { + PageTable::from_token(kernel_token!()) + .translate_va(vaddr.into()) + .unwrap() + .0 +} diff --git a/kernel/src/fs/inode.rs b/kernel/src/fs/inode.rs index a0607055ba3358bfb9635b8bf120e30fc492b8e8..d0ec12aa56722c81ffc61cf454d3751a086bcba6 100644 --- a/kernel/src/fs/inode.rs +++ b/kernel/src/fs/inode.rs @@ -263,24 +263,41 @@ pub fn open( } // display debug todo +// work_path ç»å¯¹è·¯å¾„ pub fn chdir(work_path: &str, path: &str) -> Option<String> { + let mut current_work_path_vec: Vec<&str> = work_path.split('/').collect(); + if work_path.chars().nth(0).unwrap() == '/' { + current_work_path_vec.remove(0); // 移除一个多余的 "" + } + let path_vec: Vec<&str> = path.split('/').collect(); + let current_inode = { if path.chars().nth(0).unwrap() == '/' { // ä¼ å…¥è·¯å¾„æ˜¯ç»å¯¹è·¯å¾„ ROOT_INODE.clone() } else { // ä¼ å…¥è·¯å¾„æ˜¯ç›¸å¯¹è·¯å¾„ - let current_work_pathv: Vec<&str> = work_path.split('/').collect(); - ROOT_INODE.find_vfile_bypath(current_work_pathv).unwrap() + ROOT_INODE + .find_vfile_bypath(current_work_path_vec.clone()) + .unwrap() } }; - let pathv: Vec<&str> = path.split('/').collect(); - if let Some(_) = current_inode.find_vfile_bypath(pathv) { - let new_current_path = String::from_str("/").unwrap() + &String::from_str(path).unwrap(); - if current_inode.name() == "/" { - Some(new_current_path) + if let Some(_) = current_inode.find_vfile_bypath(path_vec.clone()) { + if path.chars().nth(0).unwrap() == '/' { + Some(path.to_string()) } else { - Some(String::from_str(current_inode.name()).unwrap() + &new_current_path) + // å°† work_path å’Œ path 拼接, work_path 为ç»å¯¹è·¯å¾„, path 为相对路径 + for i in 0..path_vec.len() { + if path_vec[i] == "." || path_vec[i] == "" { + continue; + } else if path_vec[i] == ".." { + current_work_path_vec.pop(); + } else { + current_work_path_vec.push(path_vec[i]); + } + } + + Some(current_work_path_vec.join("/")) } } else { None