kernel_mapper.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. use super::{page::PageFlags, PageTableKind, PhysAddr, VirtAddr};
  2. use crate::{
  3. arch::{
  4. mm::{LockedFrameAllocator, PageMapper},
  5. CurrentIrqArch,
  6. },
  7. exception::InterruptArch,
  8. libs::align::page_align_up,
  9. mm::allocator::page_frame::PageFrameCount,
  10. mm::{MMArch, MemoryManagementArch},
  11. smp::core::smp_get_processor_id,
  12. syscall::SystemError,
  13. };
  14. use core::{
  15. ops::Deref,
  16. sync::atomic::{compiler_fence, AtomicUsize, Ordering},
  17. };
  18. /// 标志当前没有处理器持有内核映射器的锁
  19. /// 之所以需要这个标志,是因为AtomicUsize::new(0)会把0当作一个处理器的id
  20. const KERNEL_MAPPER_NO_PROCESSOR: usize = !0;
  21. /// 当前持有内核映射器锁的处理器
  22. static KERNEL_MAPPER_LOCK_OWNER: AtomicUsize = AtomicUsize::new(KERNEL_MAPPER_NO_PROCESSOR);
  23. /// 内核映射器的锁计数器
  24. static KERNEL_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0);
  25. pub struct KernelMapper {
  26. /// 内核空间映射器
  27. mapper: PageMapper,
  28. /// 标记当前映射器是否为只读
  29. readonly: bool,
  30. }
  31. impl KernelMapper {
  32. fn lock_cpu(cpuid: usize, mapper: PageMapper) -> Self {
  33. loop {
  34. match KERNEL_MAPPER_LOCK_OWNER.compare_exchange_weak(
  35. KERNEL_MAPPER_NO_PROCESSOR,
  36. cpuid,
  37. Ordering::Acquire,
  38. Ordering::Relaxed,
  39. ) {
  40. Ok(_) => break,
  41. // 当前处理器已经持有了锁
  42. Err(id) if id == cpuid => break,
  43. // either CAS failed, or some other hardware thread holds the lock
  44. Err(_) => core::hint::spin_loop(),
  45. }
  46. }
  47. let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_add(1, Ordering::Relaxed);
  48. compiler_fence(Ordering::Acquire);
  49. // 本地核心已经持有过锁,因此标记当前加锁获得的映射器为只读
  50. let readonly = prev_count > 0;
  51. return Self { mapper, readonly };
  52. }
  53. /// @brief 锁定内核映射器, 并返回一个内核映射器对象
  54. #[inline(always)]
  55. pub fn lock() -> Self {
  56. let cpuid = smp_get_processor_id() as usize;
  57. let mapper = unsafe { PageMapper::current(PageTableKind::Kernel, LockedFrameAllocator) };
  58. return Self::lock_cpu(cpuid, mapper);
  59. }
  60. /// @brief 获取内核映射器的page mapper的可变引用。如果当前映射器为只读,则返回 None
  61. #[inline(always)]
  62. pub fn as_mut(&mut self) -> Option<&mut PageMapper> {
  63. if self.readonly {
  64. return None;
  65. } else {
  66. return Some(&mut self.mapper);
  67. }
  68. }
  69. /// @brief 获取内核映射器的page mapper的不可变引用
  70. #[inline(always)]
  71. pub fn as_ref(&self) -> &PageMapper {
  72. return &self.mapper;
  73. }
  74. /// 映射一段物理地址到指定的虚拟地址。
  75. ///
  76. /// ## 参数
  77. ///
  78. /// - `vaddr`: 要映射的虚拟地址
  79. /// - `paddr`: 要映射的物理地址
  80. /// - `size`: 要映射的大小(字节,必须是页大小的整数倍,否则会向上取整)
  81. /// - `flags`: 页面标志
  82. /// - `flush`: 是否刷新TLB
  83. ///
  84. /// ## 返回
  85. ///
  86. /// - 成功:返回Ok(())
  87. /// - 失败: 如果当前映射器为只读,则返回EAGAIN_OR_EWOULDBLOCK
  88. pub unsafe fn map_phys_with_size(
  89. &mut self,
  90. mut vaddr: VirtAddr,
  91. mut paddr: PhysAddr,
  92. size: usize,
  93. flags: PageFlags<MMArch>,
  94. flush: bool,
  95. ) -> Result<(), SystemError> {
  96. if self.readonly {
  97. return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
  98. }
  99. let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
  100. // kdebug!("kernel mapper: map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
  101. for _ in 0..count.data() {
  102. let flusher = self.mapper.map_phys(vaddr, paddr, flags).unwrap();
  103. if flush {
  104. flusher.flush();
  105. }
  106. vaddr += MMArch::PAGE_SIZE;
  107. paddr += MMArch::PAGE_SIZE;
  108. }
  109. return Ok(());
  110. }
  111. }
  112. impl Drop for KernelMapper {
  113. fn drop(&mut self) {
  114. // 为了防止fetch_sub和store之间,由于中断,导致store错误清除了owner,导致错误,因此需要关中断。
  115. let guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  116. let prev_count = KERNEL_MAPPER_LOCK_COUNT.fetch_sub(1, Ordering::Relaxed);
  117. if prev_count == 1 {
  118. KERNEL_MAPPER_LOCK_OWNER.store(KERNEL_MAPPER_NO_PROCESSOR, Ordering::Release);
  119. }
  120. drop(guard);
  121. compiler_fence(Ordering::Release);
  122. }
  123. }
  124. impl Deref for KernelMapper {
  125. type Target = PageMapper;
  126. fn deref(&self) -> &Self::Target {
  127. return self.as_ref();
  128. }
  129. }