191e9d4abSLoGin use system_error::SystemError; 291e9d4abSLoGin 340fe15e0SLoGin use super::{page::PageFlags, PageTableKind, PhysAddr, VirtAddr}; 440fe15e0SLoGin use crate::{ 540fe15e0SLoGin arch::{ 640fe15e0SLoGin mm::{LockedFrameAllocator, PageMapper}, 79550910aSChiichen CurrentIrqArch, 840fe15e0SLoGin }, 99550910aSChiichen exception::InterruptArch, 1040fe15e0SLoGin libs::align::page_align_up, 11*e2841179SLoGin mm::{allocator::page_frame::PageFrameCount, MMArch, MemoryManagementArch}, 12*e2841179SLoGin smp::{ 13*e2841179SLoGin core::smp_get_processor_id, 14*e2841179SLoGin cpu::{AtomicProcessorId, ProcessorId}, 15*e2841179SLoGin }, 1640fe15e0SLoGin }; 1740fe15e0SLoGin use core::{ 1840fe15e0SLoGin ops::Deref, 1940fe15e0SLoGin sync::atomic::{compiler_fence, AtomicUsize, Ordering}, 2040fe15e0SLoGin }; 2140fe15e0SLoGin 2240fe15e0SLoGin /// 标志当前没有处理器持有内核映射器的锁 23*e2841179SLoGin /// 之所以需要这个标志,是因为 AtomicProcessorId::new(0) 会把0当作一个处理器的id 24*e2841179SLoGin const KERNEL_MAPPER_NO_PROCESSOR: ProcessorId = ProcessorId::INVALID; 2540fe15e0SLoGin /// 当前持有内核映射器锁的处理器 26*e2841179SLoGin static KERNEL_MAPPER_LOCK_OWNER: AtomicProcessorId = 27*e2841179SLoGin AtomicProcessorId::new(KERNEL_MAPPER_NO_PROCESSOR); 2840fe15e0SLoGin /// 内核映射器的锁计数器 2940fe15e0SLoGin static KERNEL_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0); 3040fe15e0SLoGin 3140fe15e0SLoGin pub struct KernelMapper { 3240fe15e0SLoGin /// 内核空间映射器 3340fe15e0SLoGin mapper: PageMapper, 3440fe15e0SLoGin /// 标记当前映射器是否为只读 3540fe15e0SLoGin readonly: bool, 3640fe15e0SLoGin } 3740fe15e0SLoGin 3840fe15e0SLoGin impl KernelMapper { 39*e2841179SLoGin fn lock_cpu(cpuid: ProcessorId, mapper: PageMapper) -> Self { 4040fe15e0SLoGin loop { 4140fe15e0SLoGin match KERNEL_MAPPER_LOCK_OWNER.compare_exchange_weak( 4240fe15e0SLoGin KERNEL_MAPPER_NO_PROCESSOR, 4340fe15e0SLoGin cpuid, 4440fe15e0SLoGin Ordering::Acquire, 4540fe15e0SLoGin Ordering::Relaxed, 4640fe15e0SLoGin ) { 4740fe15e0SLoGin Ok(_) => break, 4840fe15e0SLoGin // 当前处理器已经持有了锁 4940fe15e0SLoGin Err(id) if id == cpuid => break, 5040fe15e0SLoGin // either CAS failed, or some other hardware thread holds the lock 5140fe15e0SLoGin Err(_) => core::hint::spin_loop(), 5240fe15e0SLoGin } 5340fe15e0SLoGin } 5440fe15e0SLoGin 5540fe15e0SLoGin let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_add(1, Ordering::Relaxed); 5640fe15e0SLoGin compiler_fence(Ordering::Acquire); 5740fe15e0SLoGin 5840fe15e0SLoGin // 本地核心已经持有过锁,因此标记当前加锁获得的映射器为只读 5940fe15e0SLoGin let readonly = prev_count > 0; 6040fe15e0SLoGin 6140fe15e0SLoGin return Self { mapper, readonly }; 6240fe15e0SLoGin } 6340fe15e0SLoGin 6440fe15e0SLoGin /// @brief 锁定内核映射器, 并返回一个内核映射器对象 6540fe15e0SLoGin #[inline(always)] 6640fe15e0SLoGin pub fn lock() -> Self { 67*e2841179SLoGin let cpuid = smp_get_processor_id(); 6840fe15e0SLoGin let mapper = unsafe { PageMapper::current(PageTableKind::Kernel, LockedFrameAllocator) }; 6940fe15e0SLoGin return Self::lock_cpu(cpuid, mapper); 7040fe15e0SLoGin } 7140fe15e0SLoGin 7240fe15e0SLoGin /// @brief 获取内核映射器的page mapper的可变引用。如果当前映射器为只读,则返回 None 7340fe15e0SLoGin #[inline(always)] 7440fe15e0SLoGin pub fn as_mut(&mut self) -> Option<&mut PageMapper> { 7540fe15e0SLoGin if self.readonly { 7640fe15e0SLoGin return None; 7740fe15e0SLoGin } else { 7840fe15e0SLoGin return Some(&mut self.mapper); 7940fe15e0SLoGin } 8040fe15e0SLoGin } 8140fe15e0SLoGin 8240fe15e0SLoGin /// @brief 获取内核映射器的page mapper的不可变引用 8340fe15e0SLoGin #[inline(always)] 8440fe15e0SLoGin pub fn as_ref(&self) -> &PageMapper { 8540fe15e0SLoGin return &self.mapper; 8640fe15e0SLoGin } 8740fe15e0SLoGin 8840fe15e0SLoGin /// 映射一段物理地址到指定的虚拟地址。 8940fe15e0SLoGin /// 9040fe15e0SLoGin /// ## 参数 9140fe15e0SLoGin /// 9240fe15e0SLoGin /// - `vaddr`: 要映射的虚拟地址 9340fe15e0SLoGin /// - `paddr`: 要映射的物理地址 9440fe15e0SLoGin /// - `size`: 要映射的大小(字节,必须是页大小的整数倍,否则会向上取整) 9540fe15e0SLoGin /// - `flags`: 页面标志 9640fe15e0SLoGin /// - `flush`: 是否刷新TLB 9740fe15e0SLoGin /// 9840fe15e0SLoGin /// ## 返回 9940fe15e0SLoGin /// 10040fe15e0SLoGin /// - 成功:返回Ok(()) 10140fe15e0SLoGin /// - 失败: 如果当前映射器为只读,则返回EAGAIN_OR_EWOULDBLOCK 10240fe15e0SLoGin pub unsafe fn map_phys_with_size( 10340fe15e0SLoGin &mut self, 10440fe15e0SLoGin mut vaddr: VirtAddr, 10540fe15e0SLoGin mut paddr: PhysAddr, 10640fe15e0SLoGin size: usize, 10740fe15e0SLoGin flags: PageFlags<MMArch>, 10840fe15e0SLoGin flush: bool, 10940fe15e0SLoGin ) -> Result<(), SystemError> { 11040fe15e0SLoGin if self.readonly { 11140fe15e0SLoGin return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 11240fe15e0SLoGin } 11340fe15e0SLoGin 11440fe15e0SLoGin let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE); 11540fe15e0SLoGin // kdebug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}"); 11640fe15e0SLoGin 11740fe15e0SLoGin for _ in 0..count.data() { 11840fe15e0SLoGin let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap(); 11940fe15e0SLoGin 12040fe15e0SLoGin if flush { 12140fe15e0SLoGin flusher.flush(); 12240fe15e0SLoGin } 12340fe15e0SLoGin 12440fe15e0SLoGin vaddr += MMArch::PAGE_SIZE; 12540fe15e0SLoGin paddr += MMArch::PAGE_SIZE; 12640fe15e0SLoGin } 12740fe15e0SLoGin return Ok(()); 12840fe15e0SLoGin } 12940fe15e0SLoGin } 13040fe15e0SLoGin 13140fe15e0SLoGin impl Drop for KernelMapper { 13240fe15e0SLoGin fn drop(&mut self) { 13340fe15e0SLoGin // 为了防止fetch_sub和store之间,由于中断,导致store错误清除了owner,导致错误,因此需要关中断。 1349550910aSChiichen let guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 13540fe15e0SLoGin let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_sub(1, Ordering::Relaxed); 13640fe15e0SLoGin if prev_count == 1 { 13740fe15e0SLoGin KERNEL_MAPPER_LOCK_OWNER.store(KERNEL_MAPPER_NO_PROCESSOR, Ordering::Release); 13840fe15e0SLoGin } 1399550910aSChiichen drop(guard); 14040fe15e0SLoGin compiler_fence(Ordering::Release); 14140fe15e0SLoGin } 14240fe15e0SLoGin } 14340fe15e0SLoGin 14440fe15e0SLoGin impl Deref for KernelMapper { 14540fe15e0SLoGin type Target = PageMapper; 14640fe15e0SLoGin 14740fe15e0SLoGin fn deref(&self) -> &Self::Target { 14840fe15e0SLoGin return self.as_ref(); 14940fe15e0SLoGin } 15040fe15e0SLoGin } 151