xref: /DragonOS/kernel/src/mm/kernel_mapper.rs (revision 40fe15e0953f989ccfeb74826d61621d43dea6bb)
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