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