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