feat(mm): 简单实现fat文件系统的文件映射 (#840)

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

View File

@ -12,9 +12,9 @@ use crate::{
page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
},
kernel_mapper::KernelMapper,
page::{PageEntry, PageFlags, PAGE_1G_SHIFT},
page::{EntryFlags, PageEntry, PAGE_1G_SHIFT},
ucontext::UserMapper,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags,
},
smp::cpu::ProcessorId,
};
@ -256,8 +256,74 @@ impl MemoryManagementArch for RiscV64MMArch {
) -> bool {
true
}
const PAGE_NONE: usize = Self::ENTRY_FLAG_GLOBAL | Self::ENTRY_FLAG_READONLY;
const PAGE_READ: usize = PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY;
const PAGE_WRITE: usize =
PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY | Self::ENTRY_FLAG_WRITEABLE;
const PAGE_EXEC: usize = PAGE_ENTRY_BASE | Self::ENTRY_FLAG_EXEC;
const PAGE_READ_EXEC: usize =
PAGE_ENTRY_BASE | Self::ENTRY_FLAG_READONLY | Self::ENTRY_FLAG_EXEC;
const PAGE_WRITE_EXEC: usize = PAGE_ENTRY_BASE
| Self::ENTRY_FLAG_READONLY
| Self::ENTRY_FLAG_EXEC
| Self::ENTRY_FLAG_WRITEABLE;
const PAGE_COPY: usize = Self::PAGE_READ;
const PAGE_COPY_EXEC: usize = Self::PAGE_READ_EXEC;
const PAGE_SHARED: usize = Self::PAGE_WRITE;
const PAGE_SHARED_EXEC: usize = Self::PAGE_WRITE_EXEC;
const PAGE_COPY_NOEXEC: usize = 0;
const PAGE_READONLY: usize = 0;
const PAGE_READONLY_EXEC: usize = 0;
const PROTECTION_MAP: [EntryFlags<MMArch>; 16] = protection_map();
}
const fn protection_map() -> [EntryFlags<MMArch>; 16] {
let mut map = [0; 16];
map[VmFlags::VM_NONE.bits()] = MMArch::PAGE_NONE;
map[VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY;
map[VmFlags::VM_WRITE.bits()] = MMArch::PAGE_COPY;
map[VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_COPY;
map[VmFlags::VM_EXEC.bits()] = MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] = MMArch::PAGE_COPY_EXEC;
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
MMArch::PAGE_COPY_EXEC;
map[VmFlags::VM_SHARED.bits()] = MMArch::PAGE_NONE;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_READ.bits()] = MMArch::PAGE_READONLY;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits()] = MMArch::PAGE_SHARED;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
MMArch::PAGE_SHARED;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits()] = MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
MMArch::PAGE_READONLY_EXEC;
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
MMArch::PAGE_SHARED_EXEC;
map[VmFlags::VM_SHARED.bits()
| VmFlags::VM_EXEC.bits()
| VmFlags::VM_WRITE.bits()
| VmFlags::VM_READ.bits()] = MMArch::PAGE_SHARED_EXEC;
let mut ret = [unsafe { EntryFlags::from_data(0) }; 16];
let mut index = 0;
while index < 16 {
ret[index] = unsafe { EntryFlags::from_data(map[index]) };
index += 1;
}
ret
}
const PAGE_ENTRY_BASE: usize = RiscV64MMArch::ENTRY_FLAG_PRESENT
| RiscV64MMArch::ENTRY_FLAG_ACCESSED
| RiscV64MMArch::ENTRY_FLAG_USER;
impl VirtAddr {
/// 判断虚拟地址是否合法
#[inline(always)]
@ -270,8 +336,8 @@ impl VirtAddr {
}
/// 获取内核地址默认的页面标志
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> EntryFlags<A> {
EntryFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
.set_user(false)
.set_execute(true)
}

View File

@ -1,7 +1,7 @@
use crate::arch::mm::LockedFrameAllocator;
use crate::arch::mm::PageMapper;
use crate::arch::MMArch;
use crate::mm::page::PageFlags;
use crate::mm::page::EntryFlags;
use crate::mm::{PageTableKind, PhysAddr, VirtAddr};
use crate::smp::core::smp_get_processor_id;
use crate::smp::cpu::AtomicProcessorId;
@ -92,7 +92,7 @@ impl EptMapper {
&mut self,
gpa: u64,
hpa: u64,
flags: PageFlags<MMArch>,
flags: EntryFlags<MMArch>,
) -> Result<(), SystemError> {
if self.readonly {
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);

View File

@ -1,7 +1,7 @@
use crate::{
arch::kvm::vmx::ept::EptMapper,
libs::mutex::Mutex,
mm::{page::PageFlags, syscall::ProtFlags},
mm::{page::EntryFlags, syscall::ProtFlags},
virt::kvm::host_mem::{__gfn_to_pfn, kvm_vcpu_gfn_to_memslot, PAGE_MASK, PAGE_SHIFT},
};
use bitfield_struct::bitfield;
@ -218,7 +218,7 @@ pub fn __direct_map(
}
// 把gpa映射到hpa
let mut ept_mapper = EptMapper::lock();
let page_flags = PageFlags::from_prot_flags(ProtFlags::from_bits_truncate(0x7_u64), false);
let page_flags = EntryFlags::from_prot_flags(ProtFlags::from_bits_truncate(0x7_u64), false);
unsafe {
assert!(ept_mapper.walk(gpa, pfn << PAGE_SHIFT, page_flags).is_ok());
}

View File

@ -10,15 +10,18 @@ use x86::{bits64::rflags::RFlags, controlregs::Cr4};
use crate::{
arch::{
interrupt::{trap::X86PfErrorCode, TrapFrame},
ipc::signal::{SigCode, Signal},
mm::{MemoryManagementArch, X86_64MMArch},
CurrentIrqArch, MMArch,
},
exception::InterruptArch,
ipc::signal_types::{SigInfo, SigType},
mm::{
fault::{FaultFlags, PageFaultHandler, PageFaultMessage},
ucontext::{AddressSpace, LockedVMA},
VirtAddr, VmFaultReason, VmFlags,
},
process::ProcessManager,
};
use super::LockedFrameAllocator;
@ -28,7 +31,7 @@ pub type PageMapper =
impl X86_64MMArch {
pub fn vma_access_error(vma: Arc<LockedVMA>, error_code: X86PfErrorCode) -> bool {
let vm_flags = *vma.lock().vm_flags();
let vm_flags = *vma.lock_irqsave().vm_flags();
let foreign = false;
if error_code.contains(X86PfErrorCode::X86_PF_PK) {
return true;
@ -223,20 +226,30 @@ impl X86_64MMArch {
}
let current_address_space: Arc<AddressSpace> = AddressSpace::current().unwrap();
let mut space_guard = current_address_space.write();
let mut space_guard = current_address_space.write_irqsave();
let mut fault;
loop {
let vma = space_guard.mappings.find_nearest(address);
// let vma = space_guard.mappings.contains(address);
let vma = vma.unwrap_or_else(|| {
panic!(
"can not find nearest vma, error_code: {:#b}, address: {:#x}",
error_code,
address.data(),
)
});
let guard = vma.lock();
let vma = match vma {
Some(vma) => vma,
None => {
log::error!(
"can not find nearest vma, error_code: {:#b}, address: {:#x}",
error_code,
address.data(),
);
let pid = ProcessManager::current_pid();
let mut info =
SigInfo::new(Signal::SIGSEGV, 0, SigCode::User, SigType::Kill(pid));
Signal::SIGSEGV
.send_signal_info(Some(&mut info), pid)
.expect("failed to send SIGSEGV to process");
return;
}
};
let guard = vma.lock_irqsave();
let region = *guard.region();
let vm_flags = *guard.vm_flags();
drop(guard);
@ -253,11 +266,18 @@ impl X86_64MMArch {
)
});
} else {
panic!(
log::error!(
"No mapped vma, error_code: {:#b}, address: {:#x}",
error_code,
address.data(),
)
);
let pid = ProcessManager::current_pid();
let mut info =
SigInfo::new(Signal::SIGSEGV, 0, SigCode::User, SigType::Kill(pid));
Signal::SIGSEGV
.send_signal_info(Some(&mut info), pid)
.expect("failed to send SIGSEGV to process");
return;
}
}
@ -269,11 +289,9 @@ impl X86_64MMArch {
);
}
let mapper = &mut space_guard.user_mapper.utable;
let message = PageFaultMessage::new(vma.clone(), address, flags, mapper);
fault = PageFaultHandler::handle_mm_fault(
PageFaultMessage::new(vma.clone(), address, flags),
mapper,
);
fault = PageFaultHandler::handle_mm_fault(message);
if fault.contains(VmFaultReason::VM_FAULT_COMPLETED) {
return;

View File

@ -28,8 +28,8 @@ use crate::{
};
use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::{PageEntry, PageFlags, PAGE_1G_SHIFT};
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
use crate::mm::page::{EntryFlags, PageEntry, PAGE_1G_SHIFT};
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, VmFlags};
use system_error::SystemError;
@ -326,6 +326,93 @@ impl MemoryManagementArch for X86_64MMArch {
}
pkru::pkru_allows_pkey(pkru::vma_pkey(vma), write)
}
const PROTECTION_MAP: [EntryFlags<MMArch>; 16] = protection_map();
const PAGE_NONE: usize =
Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_ACCESSED | Self::ENTRY_FLAG_GLOBAL;
const PAGE_SHARED: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_READWRITE
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;
const PAGE_SHARED_EXEC: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_READWRITE
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED;
const PAGE_COPY_NOEXEC: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;
const PAGE_COPY_EXEC: usize =
Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_USER | Self::ENTRY_FLAG_ACCESSED;
const PAGE_COPY: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;
const PAGE_READONLY: usize = Self::ENTRY_FLAG_PRESENT
| Self::ENTRY_FLAG_USER
| Self::ENTRY_FLAG_ACCESSED
| Self::ENTRY_FLAG_NO_EXEC;
const PAGE_READONLY_EXEC: usize =
Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_USER | Self::ENTRY_FLAG_ACCESSED;
const PAGE_READ: usize = 0;
const PAGE_READ_EXEC: usize = 0;
const PAGE_WRITE: usize = 0;
const PAGE_WRITE_EXEC: usize = 0;
const PAGE_EXEC: usize = 0;
}
/// 获取保护标志的映射表
///
///
/// ## 返回值
/// - `[usize; 16]`: 长度为16的映射表
const fn protection_map() -> [EntryFlags<MMArch>; 16] {
let mut map = [unsafe { EntryFlags::from_data(0) }; 16];
unsafe {
map[VmFlags::VM_NONE.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE);
map[VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY);
map[VmFlags::VM_WRITE.bits()] = EntryFlags::from_data(MMArch::PAGE_COPY);
map[VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_COPY);
map[VmFlags::VM_EXEC.bits()] = EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
EntryFlags::from_data(MMArch::PAGE_COPY_EXEC);
map[VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_COPY_EXEC);
map[VmFlags::VM_SHARED.bits()] = EntryFlags::from_data(MMArch::PAGE_NONE);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits()] =
EntryFlags::from_data(MMArch::PAGE_SHARED);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_WRITE.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_SHARED);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_READ.bits()] =
EntryFlags::from_data(MMArch::PAGE_READONLY_EXEC);
map[VmFlags::VM_SHARED.bits() | VmFlags::VM_EXEC.bits() | VmFlags::VM_WRITE.bits()] =
EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC);
map[VmFlags::VM_SHARED.bits()
| VmFlags::VM_EXEC.bits()
| VmFlags::VM_WRITE.bits()
| VmFlags::VM_READ.bits()] = EntryFlags::from_data(MMArch::PAGE_SHARED_EXEC);
}
// if X86_64MMArch::is_xd_reserved() {
// map.iter_mut().for_each(|x| *x &= !Self::ENTRY_FLAG_NO_EXEC)
// }
map
}
impl X86_64MMArch {
@ -650,17 +737,17 @@ impl FrameAllocator for LockedFrameAllocator {
}
/// 获取内核地址默认的页面标志
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> PageFlags<A> {
pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> EntryFlags<A> {
let info: X86_64MMBootstrapInfo = BOOTSTRAP_MM_INFO.unwrap();
if virt.data() >= info.kernel_code_start && virt.data() < info.kernel_code_end {
// Remap kernel code execute
return PageFlags::new().set_execute(true).set_write(true);
return EntryFlags::new().set_execute(true).set_write(true);
} else if virt.data() >= info.kernel_data_end && virt.data() < info.kernel_rodata_end {
// Remap kernel rodata read only
return PageFlags::new().set_execute(true);
return EntryFlags::new().set_execute(true);
} else {
return PageFlags::new().set_write(true).set_execute(true);
return EntryFlags::new().set_write(true).set_execute(true);
}
}

View File

@ -16,8 +16,8 @@ const PKEY_MASK: usize = 1 << 32 | 1 << 33 | 1 << 34 | 1 << 35;
/// ## 返回值
/// - `u16`: vma的protection_key
pub fn vma_pkey(vma: Arc<LockedVMA>) -> u16 {
let guard = vma.lock();
((guard.vm_flags().bits() & PKEY_MASK as u64) >> VM_PKEY_SHIFT) as u16
let guard = vma.lock_irqsave();
((guard.vm_flags().bits() & PKEY_MASK) >> VM_PKEY_SHIFT) as u16
}
// TODO pkru实现参考https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/include/asm/pkru.h