ept.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. use crate::arch::mm::LockedFrameAllocator;
  2. use crate::arch::mm::PageMapper;
  3. use crate::arch::MMArch;
  4. use crate::mm::page::EntryFlags;
  5. use crate::mm::{PageTableKind, PhysAddr, VirtAddr};
  6. use crate::smp::core::smp_get_processor_id;
  7. use crate::smp::cpu::AtomicProcessorId;
  8. use crate::smp::cpu::ProcessorId;
  9. use core::sync::atomic::{compiler_fence, AtomicUsize, Ordering};
  10. use system_error::SystemError;
  11. use x86::msr;
  12. /// Check if MTRR is supported
  13. pub fn check_ept_features() -> Result<(), SystemError> {
  14. const MTRR_ENABLE_BIT: u64 = 1 << 11;
  15. let ia32_mtrr_def_type = unsafe { msr::rdmsr(msr::IA32_MTRR_DEF_TYPE) };
  16. if (ia32_mtrr_def_type & MTRR_ENABLE_BIT) == 0 {
  17. return Err(SystemError::ENOSYS);
  18. }
  19. Ok(())
  20. }
  21. // pub fn ept_build_mtrr_map() -> Result<(), SystemError> {
  22. // let ia32_mtrr_cap = unsafe { msr::rdmsr(msr::IA32_MTRRCAP) };
  23. // Ok(())
  24. // }
  25. /// 标志当前没有处理器持有内核映射器的锁
  26. /// 之所以需要这个标志,是因为AtomicUsize::new(0)会把0当作一个处理器的id
  27. const EPT_MAPPER_NO_PROCESSOR: ProcessorId = ProcessorId::INVALID;
  28. /// 当前持有内核映射器锁的处理器
  29. static EPT_MAPPER_LOCK_OWNER: AtomicProcessorId = AtomicProcessorId::new(EPT_MAPPER_NO_PROCESSOR);
  30. /// 内核映射器的锁计数器
  31. static EPT_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0);
  32. pub struct EptMapper {
  33. /// EPT页表映射器
  34. mapper: PageMapper,
  35. /// 标记当前映射器是否为只读
  36. readonly: bool,
  37. // EPT页表根地址
  38. // root_hpa: PhysAddr,
  39. }
  40. impl EptMapper {
  41. fn lock_cpu(cpuid: ProcessorId, mapper: PageMapper) -> Self {
  42. loop {
  43. match EPT_MAPPER_LOCK_OWNER.compare_exchange_weak(
  44. EPT_MAPPER_NO_PROCESSOR,
  45. cpuid,
  46. Ordering::Acquire,
  47. Ordering::Relaxed,
  48. ) {
  49. Ok(_) => break,
  50. // 当前处理器已经持有了锁
  51. Err(id) if id == cpuid => break,
  52. // either CAS failed, or some other hardware thread holds the lock
  53. Err(_) => core::hint::spin_loop(),
  54. }
  55. }
  56. let prev_count = EPT_MAPPER_LOCK_COUNT.fetch_add(1, Ordering::Relaxed);
  57. compiler_fence(Ordering::Acquire);
  58. // 本地核心已经持有过锁,因此标记当前加锁获得的映射器为只读
  59. let readonly = prev_count > 0;
  60. return Self { mapper, readonly };
  61. }
  62. /// @brief 锁定内核映射器, 并返回一个内核映射器对象
  63. #[inline(always)]
  64. pub fn lock() -> Self {
  65. let cpuid = smp_get_processor_id();
  66. let mapper = unsafe { PageMapper::current(PageTableKind::EPT, LockedFrameAllocator) };
  67. return Self::lock_cpu(cpuid, mapper);
  68. }
  69. /// 映射guest physical addr(gpa)到指定的host physical addr(hpa)。
  70. ///
  71. /// ## 参数
  72. ///
  73. /// - `gpa`: 要映射的guest physical addr
  74. /// - `hpa`: 要映射的host physical addr
  75. /// - `flags`: 页面标志
  76. ///
  77. /// ## 返回
  78. ///
  79. /// - 成功:返回Ok(())
  80. /// - 失败: 如果当前映射器为只读,则返回EAGAIN_OR_EWOULDBLOCK
  81. pub unsafe fn walk(
  82. &mut self,
  83. gpa: u64,
  84. hpa: u64,
  85. flags: EntryFlags<MMArch>,
  86. ) -> Result<(), SystemError> {
  87. if self.readonly {
  88. return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
  89. }
  90. self.mapper
  91. .map_phys(
  92. VirtAddr::new(gpa as usize),
  93. PhysAddr::new(hpa as usize),
  94. flags,
  95. )
  96. .unwrap()
  97. .flush();
  98. return Ok(());
  99. }
  100. // fn get_ept_index(addr: u64, level: usize) -> u64 {
  101. // let pt64_level_shift = PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS;
  102. // (addr >> pt64_level_shift) & ((1 << PT64_LEVEL_BITS) - 1)
  103. // }
  104. }