xref: /DragonOS/kernel/src/driver/virtio/virtio_impl.rs (revision 40fe15e0953f989ccfeb74826d61621d43dea6bb)
1*40fe15e0SLoGin use crate::arch::mm::kernel_page_flags;
2*40fe15e0SLoGin 
3*40fe15e0SLoGin use crate::arch::MMArch;
4*40fe15e0SLoGin 
5*40fe15e0SLoGin use crate::mm::kernel_mapper::KernelMapper;
6*40fe15e0SLoGin use crate::mm::page::PageFlags;
7*40fe15e0SLoGin use crate::mm::{
8*40fe15e0SLoGin     allocator::page_frame::{
9*40fe15e0SLoGin         allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
10*40fe15e0SLoGin     },
11*40fe15e0SLoGin     MemoryManagementArch, PhysAddr, VirtAddr,
1226d84a31SYJwu2023 };
13004e86ffSlogin use core::ptr::NonNull;
14*40fe15e0SLoGin use virtio_drivers::{BufferDirection, Hal, PAGE_SIZE};
15*40fe15e0SLoGin 
1626d84a31SYJwu2023 pub struct HalImpl;
1713776c11Slogin unsafe impl Hal for HalImpl {
1826d84a31SYJwu2023     /// @brief 申请用于DMA的内存页
1926d84a31SYJwu2023     /// @param pages 页数(4k一页)
2026d84a31SYJwu2023     /// @return PhysAddr 获得的内存页的初始物理地址
21*40fe15e0SLoGin     fn dma_alloc(
22*40fe15e0SLoGin         pages: usize,
23*40fe15e0SLoGin         _direction: BufferDirection,
24*40fe15e0SLoGin     ) -> (virtio_drivers::PhysAddr, NonNull<u8>) {
25*40fe15e0SLoGin         let page_num = PageFrameCount::new(
26*40fe15e0SLoGin             ((pages * PAGE_SIZE + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE).next_power_of_two(),
27*40fe15e0SLoGin         );
2826d84a31SYJwu2023         unsafe {
29*40fe15e0SLoGin             let (paddr, count) =
30*40fe15e0SLoGin                 allocate_page_frames(page_num).expect("VirtIO Impl: alloc page failed");
31*40fe15e0SLoGin             let virt = MMArch::phys_2_virt(paddr).unwrap();
32*40fe15e0SLoGin             // 清空这块区域,防止出现脏数据
33*40fe15e0SLoGin             core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);
34*40fe15e0SLoGin 
35*40fe15e0SLoGin             let dma_flags: PageFlags<MMArch> = PageFlags::mmio_flags();
36*40fe15e0SLoGin 
37*40fe15e0SLoGin             let mut kernel_mapper = KernelMapper::lock();
38*40fe15e0SLoGin             let kernel_mapper = kernel_mapper.as_mut().unwrap();
39*40fe15e0SLoGin             let flusher = kernel_mapper
40*40fe15e0SLoGin                 .remap(virt, dma_flags)
41*40fe15e0SLoGin                 .expect("VirtIO Impl: remap failed");
42*40fe15e0SLoGin             flusher.flush();
43*40fe15e0SLoGin             return (
44*40fe15e0SLoGin                 paddr.data(),
45*40fe15e0SLoGin                 NonNull::new(MMArch::phys_2_virt(paddr).unwrap().data() as _).unwrap(),
46*40fe15e0SLoGin             );
4726d84a31SYJwu2023         }
4826d84a31SYJwu2023     }
4926d84a31SYJwu2023     /// @brief 释放用于DMA的内存页
5026d84a31SYJwu2023     /// @param paddr 起始物理地址 pages 页数(4k一页)
5126d84a31SYJwu2023     /// @return i32 0表示成功
52*40fe15e0SLoGin     unsafe fn dma_dealloc(
53*40fe15e0SLoGin         paddr: virtio_drivers::PhysAddr,
54*40fe15e0SLoGin         vaddr: NonNull<u8>,
55*40fe15e0SLoGin         pages: usize,
56*40fe15e0SLoGin     ) -> i32 {
57*40fe15e0SLoGin         let page_count = PageFrameCount::new(
58*40fe15e0SLoGin             ((pages * PAGE_SIZE + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE).next_power_of_two(),
59*40fe15e0SLoGin         );
60*40fe15e0SLoGin 
61*40fe15e0SLoGin         // 恢复页面属性
62*40fe15e0SLoGin         let vaddr = VirtAddr::new(vaddr.as_ptr() as *mut u8 as usize);
63*40fe15e0SLoGin         let mut kernel_mapper = KernelMapper::lock();
64*40fe15e0SLoGin         let kernel_mapper = kernel_mapper.as_mut().unwrap();
65*40fe15e0SLoGin         let flusher = kernel_mapper
66*40fe15e0SLoGin             .remap(vaddr, kernel_page_flags(vaddr))
67*40fe15e0SLoGin             .expect("VirtIO Impl: remap failed");
68*40fe15e0SLoGin         flusher.flush();
69*40fe15e0SLoGin 
7026d84a31SYJwu2023         unsafe {
71*40fe15e0SLoGin             deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
7226d84a31SYJwu2023         }
7326d84a31SYJwu2023         return 0;
7426d84a31SYJwu2023     }
7573c607aaSYJwu2023     /// @brief mmio物理地址转换为虚拟地址,不需要使用
7626d84a31SYJwu2023     /// @param paddr 起始物理地址
7773c607aaSYJwu2023     /// @return NonNull<u8> 虚拟地址的指针
78*40fe15e0SLoGin     unsafe fn mmio_phys_to_virt(_paddr: virtio_drivers::PhysAddr, _size: usize) -> NonNull<u8> {
7973c607aaSYJwu2023         NonNull::new((0) as _).unwrap()
8026d84a31SYJwu2023     }
8126d84a31SYJwu2023     /// @brief 与真实物理设备共享
8226d84a31SYJwu2023     /// @param buffer 要共享的buffer _direction:设备到driver或driver到设备
8326d84a31SYJwu2023     /// @return buffer在内存中的物理地址
84*40fe15e0SLoGin     unsafe fn share(
85*40fe15e0SLoGin         buffer: NonNull<[u8]>,
86*40fe15e0SLoGin         _direction: BufferDirection,
87*40fe15e0SLoGin     ) -> virtio_drivers::PhysAddr {
88*40fe15e0SLoGin         let vaddr = VirtAddr::new(buffer.as_ptr() as *mut u8 as usize);
8973c607aaSYJwu2023         //kdebug!("virt:{:x}", vaddr);
9026d84a31SYJwu2023         // Nothing to do, as the host already has access to all memory.
91*40fe15e0SLoGin         return MMArch::virt_2_phys(vaddr).unwrap().data();
9226d84a31SYJwu2023     }
9326d84a31SYJwu2023     /// @brief 停止共享(让主机可以访问全部内存的话什么都不用做)
94*40fe15e0SLoGin     unsafe fn unshare(
95*40fe15e0SLoGin         _paddr: virtio_drivers::PhysAddr,
96*40fe15e0SLoGin         _buffer: NonNull<[u8]>,
97*40fe15e0SLoGin         _direction: BufferDirection,
98*40fe15e0SLoGin     ) {
9926d84a31SYJwu2023         // Nothing to do, as the host already has access to all memory and we didn't copy the buffer
10026d84a31SYJwu2023         // anywhere else.
10126d84a31SYJwu2023     }
10226d84a31SYJwu2023 }
103