1*40fe15e0SLoGin use super::{page::PageFlags, PageTableKind, PhysAddr, VirtAddr}; 2*40fe15e0SLoGin use crate::{ 3*40fe15e0SLoGin arch::{ 4*40fe15e0SLoGin asm::irqflags::{local_irq_restore, local_irq_save}, 5*40fe15e0SLoGin mm::{LockedFrameAllocator, PageMapper}, 6*40fe15e0SLoGin }, 7*40fe15e0SLoGin libs::align::page_align_up, 8*40fe15e0SLoGin mm::allocator::page_frame::PageFrameCount, 9*40fe15e0SLoGin mm::{MMArch, MemoryManagementArch}, 10*40fe15e0SLoGin smp::core::smp_get_processor_id, 11*40fe15e0SLoGin syscall::SystemError, 12*40fe15e0SLoGin }; 13*40fe15e0SLoGin use core::{ 14*40fe15e0SLoGin ops::Deref, 15*40fe15e0SLoGin sync::atomic::{compiler_fence, AtomicUsize, Ordering}, 16*40fe15e0SLoGin }; 17*40fe15e0SLoGin 18*40fe15e0SLoGin /// 标志当前没有处理器持有内核映射器的锁 19*40fe15e0SLoGin /// 之所以需要这个标志,是因为AtomicUsize::new(0)会把0当作一个处理器的id 20*40fe15e0SLoGin const KERNEL_MAPPER_NO_PROCESSOR: usize = !0; 21*40fe15e0SLoGin /// 当前持有内核映射器锁的处理器 22*40fe15e0SLoGin static KERNEL_MAPPER_LOCK_OWNER: AtomicUsize = AtomicUsize::new(KERNEL_MAPPER_NO_PROCESSOR); 23*40fe15e0SLoGin /// 内核映射器的锁计数器 24*40fe15e0SLoGin static KERNEL_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0); 25*40fe15e0SLoGin 26*40fe15e0SLoGin pub struct KernelMapper { 27*40fe15e0SLoGin /// 内核空间映射器 28*40fe15e0SLoGin mapper: PageMapper, 29*40fe15e0SLoGin /// 标记当前映射器是否为只读 30*40fe15e0SLoGin readonly: bool, 31*40fe15e0SLoGin } 32*40fe15e0SLoGin 33*40fe15e0SLoGin impl KernelMapper { 34*40fe15e0SLoGin fn lock_cpu(cpuid: usize, mapper: PageMapper) -> Self { 35*40fe15e0SLoGin loop { 36*40fe15e0SLoGin match KERNEL_MAPPER_LOCK_OWNER.compare_exchange_weak( 37*40fe15e0SLoGin KERNEL_MAPPER_NO_PROCESSOR, 38*40fe15e0SLoGin cpuid, 39*40fe15e0SLoGin Ordering::Acquire, 40*40fe15e0SLoGin Ordering::Relaxed, 41*40fe15e0SLoGin ) { 42*40fe15e0SLoGin Ok(_) => break, 43*40fe15e0SLoGin // 当前处理器已经持有了锁 44*40fe15e0SLoGin Err(id) if id == cpuid => break, 45*40fe15e0SLoGin // either CAS failed, or some other hardware thread holds the lock 46*40fe15e0SLoGin Err(_) => core::hint::spin_loop(), 47*40fe15e0SLoGin } 48*40fe15e0SLoGin } 49*40fe15e0SLoGin 50*40fe15e0SLoGin let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_add(1, Ordering::Relaxed); 51*40fe15e0SLoGin compiler_fence(Ordering::Acquire); 52*40fe15e0SLoGin 53*40fe15e0SLoGin // 本地核心已经持有过锁,因此标记当前加锁获得的映射器为只读 54*40fe15e0SLoGin let readonly = prev_count > 0; 55*40fe15e0SLoGin 56*40fe15e0SLoGin return Self { mapper, readonly }; 57*40fe15e0SLoGin } 58*40fe15e0SLoGin 59*40fe15e0SLoGin /// @brief 锁定内核映射器, 并返回一个内核映射器对象 60*40fe15e0SLoGin #[inline(always)] 61*40fe15e0SLoGin pub fn lock() -> Self { 62*40fe15e0SLoGin let cpuid = smp_get_processor_id() as usize; 63*40fe15e0SLoGin let mapper = unsafe { PageMapper::current(PageTableKind::Kernel, LockedFrameAllocator) }; 64*40fe15e0SLoGin return Self::lock_cpu(cpuid, mapper); 65*40fe15e0SLoGin } 66*40fe15e0SLoGin 67*40fe15e0SLoGin /// @brief 获取内核映射器的page mapper的可变引用。如果当前映射器为只读,则返回 None 68*40fe15e0SLoGin #[inline(always)] 69*40fe15e0SLoGin pub fn as_mut(&mut self) -> Option<&mut PageMapper> { 70*40fe15e0SLoGin if self.readonly { 71*40fe15e0SLoGin return None; 72*40fe15e0SLoGin } else { 73*40fe15e0SLoGin return Some(&mut self.mapper); 74*40fe15e0SLoGin } 75*40fe15e0SLoGin } 76*40fe15e0SLoGin 77*40fe15e0SLoGin /// @brief 获取内核映射器的page mapper的不可变引用 78*40fe15e0SLoGin #[inline(always)] 79*40fe15e0SLoGin pub fn as_ref(&self) -> &PageMapper { 80*40fe15e0SLoGin return &self.mapper; 81*40fe15e0SLoGin } 82*40fe15e0SLoGin 83*40fe15e0SLoGin /// 映射一段物理地址到指定的虚拟地址。 84*40fe15e0SLoGin /// 85*40fe15e0SLoGin /// ## 参数 86*40fe15e0SLoGin /// 87*40fe15e0SLoGin /// - `vaddr`: 要映射的虚拟地址 88*40fe15e0SLoGin /// - `paddr`: 要映射的物理地址 89*40fe15e0SLoGin /// - `size`: 要映射的大小(字节,必须是页大小的整数倍,否则会向上取整) 90*40fe15e0SLoGin /// - `flags`: 页面标志 91*40fe15e0SLoGin /// - `flush`: 是否刷新TLB 92*40fe15e0SLoGin /// 93*40fe15e0SLoGin /// ## 返回 94*40fe15e0SLoGin /// 95*40fe15e0SLoGin /// - 成功:返回Ok(()) 96*40fe15e0SLoGin /// - 失败: 如果当前映射器为只读,则返回EAGAIN_OR_EWOULDBLOCK 97*40fe15e0SLoGin pub unsafe fn map_phys_with_size( 98*40fe15e0SLoGin &mut self, 99*40fe15e0SLoGin mut vaddr: VirtAddr, 100*40fe15e0SLoGin mut paddr: PhysAddr, 101*40fe15e0SLoGin size: usize, 102*40fe15e0SLoGin flags: PageFlags<MMArch>, 103*40fe15e0SLoGin flush: bool, 104*40fe15e0SLoGin ) -> Result<(), SystemError> { 105*40fe15e0SLoGin if self.readonly { 106*40fe15e0SLoGin return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 107*40fe15e0SLoGin } 108*40fe15e0SLoGin 109*40fe15e0SLoGin let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE); 110*40fe15e0SLoGin // kdebug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}"); 111*40fe15e0SLoGin 112*40fe15e0SLoGin for _ in 0..count.data() { 113*40fe15e0SLoGin let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap(); 114*40fe15e0SLoGin 115*40fe15e0SLoGin if flush { 116*40fe15e0SLoGin flusher.flush(); 117*40fe15e0SLoGin } 118*40fe15e0SLoGin 119*40fe15e0SLoGin vaddr += MMArch::PAGE_SIZE; 120*40fe15e0SLoGin paddr += MMArch::PAGE_SIZE; 121*40fe15e0SLoGin } 122*40fe15e0SLoGin return Ok(()); 123*40fe15e0SLoGin } 124*40fe15e0SLoGin } 125*40fe15e0SLoGin 126*40fe15e0SLoGin impl Drop for KernelMapper { 127*40fe15e0SLoGin fn drop(&mut self) { 128*40fe15e0SLoGin // 为了防止fetch_sub和store之间,由于中断,导致store错误清除了owner,导致错误,因此需要关中断。 129*40fe15e0SLoGin let flags = local_irq_save(); 130*40fe15e0SLoGin let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_sub(1, Ordering::Relaxed); 131*40fe15e0SLoGin if prev_count == 1 { 132*40fe15e0SLoGin KERNEL_MAPPER_LOCK_OWNER.store(KERNEL_MAPPER_NO_PROCESSOR, Ordering::Release); 133*40fe15e0SLoGin } 134*40fe15e0SLoGin local_irq_restore(flags); 135*40fe15e0SLoGin compiler_fence(Ordering::Release); 136*40fe15e0SLoGin } 137*40fe15e0SLoGin } 138*40fe15e0SLoGin 139*40fe15e0SLoGin impl Deref for KernelMapper { 140*40fe15e0SLoGin type Target = PageMapper; 141*40fe15e0SLoGin 142*40fe15e0SLoGin fn deref(&self) -> &Self::Target { 143*40fe15e0SLoGin return self.as_ref(); 144*40fe15e0SLoGin } 145*40fe15e0SLoGin } 146