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