MemoryShore cf7f801e1d
feat(mm): 简单实现fat文件系统的文件映射 (#840)
- 添加文件映射相关接口,目前已简单实现fat文件系统的私有映射和共享映射
- 添加msync系统调用(由于当前未实现脏页自动回写,需要手动调用msync进行同步)
- 简单实现PageCache(暂时使用HashMap进行文件页号与页的映射)
- 添加新的PageFlags标志结构,原PageFlags改名为EntryFlags
- 参考linux使用protection_map映射表进行页面标志的获取
- 添加页面回收机制
- 添加页面回收内核线程
- 缺页中断使用的锁修改为irq_save; 添加脏页回写机制
- 修复do_cow_page死锁问题
- 访问非法地址时发送信号终止进程
- 修复重复插入反向vma表的错误
- 添加test_filemap文件映射测试程序
2024-09-05 00:35:27 +08:00

116 lines
3.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::arch::mm::LockedFrameAllocator;
use crate::arch::mm::PageMapper;
use crate::arch::MMArch;
use crate::mm::page::EntryFlags;
use crate::mm::{PageTableKind, PhysAddr, VirtAddr};
use crate::smp::core::smp_get_processor_id;
use crate::smp::cpu::AtomicProcessorId;
use crate::smp::cpu::ProcessorId;
use core::sync::atomic::{compiler_fence, AtomicUsize, Ordering};
use system_error::SystemError;
use x86::msr;
/// Check if MTRR is supported
pub fn check_ept_features() -> Result<(), SystemError> {
const MTRR_ENABLE_BIT: u64 = 1 << 11;
let ia32_mtrr_def_type = unsafe { msr::rdmsr(msr::IA32_MTRR_DEF_TYPE) };
if (ia32_mtrr_def_type & MTRR_ENABLE_BIT) == 0 {
return Err(SystemError::ENOSYS);
}
Ok(())
}
// pub fn ept_build_mtrr_map() -> Result<(), SystemError> {
// let ia32_mtrr_cap = unsafe { msr::rdmsr(msr::IA32_MTRRCAP) };
// Ok(())
// }
/// 标志当前没有处理器持有内核映射器的锁
/// 之所以需要这个标志是因为AtomicUsize::new(0)会把0当作一个处理器的id
const EPT_MAPPER_NO_PROCESSOR: ProcessorId = ProcessorId::INVALID;
/// 当前持有内核映射器锁的处理器
static EPT_MAPPER_LOCK_OWNER: AtomicProcessorId = AtomicProcessorId::new(EPT_MAPPER_NO_PROCESSOR);
/// 内核映射器的锁计数器
static EPT_MAPPER_LOCK_COUNT: AtomicUsize = AtomicUsize::new(0);
pub struct EptMapper {
/// EPT页表映射器
mapper: PageMapper,
/// 标记当前映射器是否为只读
readonly: bool,
// EPT页表根地址
// root_hpa: PhysAddr,
}
impl EptMapper {
fn lock_cpu(cpuid: ProcessorId, mapper: PageMapper) -> Self {
loop {
match EPT_MAPPER_LOCK_OWNER.compare_exchange_weak(
EPT_MAPPER_NO_PROCESSOR,
cpuid,
Ordering::Acquire,
Ordering::Relaxed,
) {
Ok(_) => break,
// 当前处理器已经持有了锁
Err(id) if id == cpuid => break,
// either CAS failed, or some other hardware thread holds the lock
Err(_) => core::hint::spin_loop(),
}
}
let prev_count = EPT_MAPPER_LOCK_COUNT.fetch_add(1, Ordering::Relaxed);
compiler_fence(Ordering::Acquire);
// 本地核心已经持有过锁,因此标记当前加锁获得的映射器为只读
let readonly = prev_count > 0;
return Self { mapper, readonly };
}
/// @brief 锁定内核映射器, 并返回一个内核映射器对象
#[inline(always)]
pub fn lock() -> Self {
let cpuid = smp_get_processor_id();
let mapper = unsafe { PageMapper::current(PageTableKind::EPT, LockedFrameAllocator) };
return Self::lock_cpu(cpuid, mapper);
}
/// 映射guest physical addr(gpa)到指定的host physical addr(hpa)。
///
/// ## 参数
///
/// - `gpa`: 要映射的guest physical addr
/// - `hpa`: 要映射的host physical addr
/// - `flags`: 页面标志
///
/// ## 返回
///
/// - 成功返回Ok(())
/// - 失败: 如果当前映射器为只读则返回EAGAIN_OR_EWOULDBLOCK
pub unsafe fn walk(
&mut self,
gpa: u64,
hpa: u64,
flags: EntryFlags<MMArch>,
) -> Result<(), SystemError> {
if self.readonly {
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
}
self.mapper
.map_phys(
VirtAddr::new(gpa as usize),
PhysAddr::new(hpa as usize),
flags,
)
.unwrap()
.flush();
return Ok(());
}
// fn get_ept_index(addr: u64, level: usize) -> u64 {
// let pt64_level_shift = PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS;
// (addr >> pt64_level_shift) & ((1 << PT64_LEVEL_BITS) - 1)
// }
}