xref: /DragonOS/kernel/src/mm/kernel_mapper.rs (revision cf7f801e1d50ee5b04cb728e4251a57f4183bfbc)
191e9d4abSLoGin use system_error::SystemError;
291e9d4abSLoGin 
3*cf7f801eSMemoryShore use super::{page::EntryFlags, PageTableKind, PhysAddr, VirtAddr};
440fe15e0SLoGin use crate::{
540fe15e0SLoGin     arch::{
640fe15e0SLoGin         mm::{LockedFrameAllocator, PageMapper},
79550910aSChiichen         CurrentIrqArch,
840fe15e0SLoGin     },
99550910aSChiichen     exception::InterruptArch,
1040fe15e0SLoGin     libs::align::page_align_up,
11e2841179SLoGin     mm::{allocator::page_frame::PageFrameCount, MMArch, MemoryManagementArch},
12e2841179SLoGin     smp::{
13e2841179SLoGin         core::smp_get_processor_id,
14e2841179SLoGin         cpu::{AtomicProcessorId, ProcessorId},
15e2841179SLoGin     },
1640fe15e0SLoGin };
1740fe15e0SLoGin use core::{
1840fe15e0SLoGin     ops::Deref,
1940fe15e0SLoGin     sync::atomic::{compiler_fence, AtomicUsize, Ordering},
2040fe15e0SLoGin };
2140fe15e0SLoGin 
2240fe15e0SLoGin /// 标志当前没有处理器持有内核映射器的锁
23e2841179SLoGin /// 之所以需要这个标志,是因为 AtomicProcessorId::new(0) 会把0当作一个处理器的id
24e2841179SLoGin const KERNEL_MAPPER_NO_PROCESSOR: ProcessorId = ProcessorId::INVALID;
2540fe15e0SLoGin /// 当前持有内核映射器锁的处理器
26e2841179SLoGin static KERNEL_MAPPER_LOCK_OWNER: AtomicProcessorId =
27e2841179SLoGin     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 {
lock_cpu(cpuid: ProcessorId, mapper: PageMapper) -> Self39e2841179SLoGin     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)]
lock() -> Self6640fe15e0SLoGin     pub fn lock() -> Self {
67e2841179SLoGin         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)]
as_mut(&mut self) -> Option<&mut PageMapper>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)]
as_ref(&self) -> &PageMapper8440fe15e0SLoGin     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
map_phys_with_size( &mut self, mut vaddr: VirtAddr, mut paddr: PhysAddr, size: usize, flags: EntryFlags<MMArch>, flush: bool, ) -> Result<(), SystemError>10240fe15e0SLoGin     pub unsafe fn map_phys_with_size(
10340fe15e0SLoGin         &mut self,
10440fe15e0SLoGin         mut vaddr: VirtAddr,
10540fe15e0SLoGin         mut paddr: PhysAddr,
10640fe15e0SLoGin         size: usize,
107*cf7f801eSMemoryShore         flags: EntryFlags<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);
1152eab6dd7S曾俊         // debug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
11640fe15e0SLoGin         for _ in 0..count.data() {
11740fe15e0SLoGin             let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap();
11840fe15e0SLoGin 
11940fe15e0SLoGin             if flush {
12040fe15e0SLoGin                 flusher.flush();
12140fe15e0SLoGin             }
12240fe15e0SLoGin 
12340fe15e0SLoGin             vaddr += MMArch::PAGE_SIZE;
12440fe15e0SLoGin             paddr += MMArch::PAGE_SIZE;
12540fe15e0SLoGin         }
1269621ab16SLoGin         compiler_fence(Ordering::SeqCst);
12740fe15e0SLoGin         return Ok(());
12840fe15e0SLoGin     }
12940fe15e0SLoGin }
13040fe15e0SLoGin 
13140fe15e0SLoGin impl Drop for KernelMapper {
drop(&mut self)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 
deref(&self) -> &Self::Target14740fe15e0SLoGin     fn deref(&self) -> &Self::Target {
14840fe15e0SLoGin         return self.as_ref();
14940fe15e0SLoGin     }
15040fe15e0SLoGin }
151