mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-21 18:33:23 +00:00
Merge branch 'patch-add-file-mapping' into patch-fix-mmap
This commit is contained in:
@ -12,7 +12,7 @@ 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,
|
||||
},
|
||||
@ -270,8 +270,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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use crate::mm::kernel_mapper::KernelMapper;
|
||||
use crate::mm::page::{PageEntry, PageFlags, PAGE_1G_SHIFT};
|
||||
use crate::mm::page::{EntryFlags, PageEntry, PAGE_1G_SHIFT};
|
||||
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
|
||||
|
||||
use system_error::SystemError;
|
||||
@ -650,17 +650,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
|
||||
use crate::arch::MMArch;
|
||||
|
||||
use crate::mm::kernel_mapper::KernelMapper;
|
||||
use crate::mm::page::{page_manager_lock_irqsave, PageFlags};
|
||||
use crate::mm::page::{page_manager_lock_irqsave, EntryFlags};
|
||||
use crate::mm::{
|
||||
allocator::page_frame::{
|
||||
allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
|
||||
@ -25,7 +25,7 @@ pub fn dma_alloc(pages: usize) -> (usize, NonNull<u8>) {
|
||||
// 清空这块区域,防止出现脏数据
|
||||
core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);
|
||||
|
||||
let dma_flags: PageFlags<MMArch> = PageFlags::mmio_flags();
|
||||
let dma_flags: EntryFlags<MMArch> = EntryFlags::mmio_flags();
|
||||
|
||||
let mut kernel_mapper = KernelMapper::lock();
|
||||
let kernel_mapper = kernel_mapper.as_mut().unwrap();
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
spinlock::SpinLock,
|
||||
},
|
||||
mm::{
|
||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::PageFlags,
|
||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, page::EntryFlags,
|
||||
MemoryManagementArch,
|
||||
},
|
||||
time::timer::{Timer, TimerFunction},
|
||||
@ -95,7 +95,7 @@ impl VideoRefreshManager {
|
||||
let count = PageFrameCount::new(
|
||||
page_align_up(frame_buffer_info_guard.buf_size()) / MMArch::PAGE_SIZE,
|
||||
);
|
||||
let page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
|
||||
let page_flags: EntryFlags<MMArch> = EntryFlags::new().set_execute(true).set_write(true);
|
||||
|
||||
let mut kernel_mapper = KernelMapper::lock();
|
||||
let mut kernel_mapper = kernel_mapper.as_mut();
|
||||
|
@ -3,7 +3,7 @@ use crate::arch::mm::kernel_page_flags;
|
||||
use crate::arch::MMArch;
|
||||
|
||||
use crate::mm::kernel_mapper::KernelMapper;
|
||||
use crate::mm::page::{page_manager_lock_irqsave, PageFlags};
|
||||
use crate::mm::page::{page_manager_lock_irqsave, EntryFlags};
|
||||
use crate::mm::{
|
||||
allocator::page_frame::{
|
||||
allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
|
||||
@ -32,7 +32,7 @@ unsafe impl Hal for HalImpl {
|
||||
// 清空这块区域,防止出现脏数据
|
||||
core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);
|
||||
|
||||
let dma_flags: PageFlags<MMArch> = PageFlags::mmio_flags();
|
||||
let dma_flags: EntryFlags<MMArch> = EntryFlags::mmio_flags();
|
||||
|
||||
let mut kernel_mapper = KernelMapper::lock();
|
||||
let kernel_mapper = kernel_mapper.as_mut().unwrap();
|
||||
|
@ -5,6 +5,7 @@ use alloc::{
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use log::error;
|
||||
use system_error::SystemError;
|
||||
|
||||
@ -16,6 +17,7 @@ use crate::{
|
||||
filesystem::procfs::ProcfsFilePrivateData,
|
||||
ipc::pipe::{LockedPipeInode, PipeFsPrivateData},
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
mm::page::Page,
|
||||
net::{
|
||||
event_poll::{EPollItem, EPollPrivateData, EventPoll},
|
||||
socket::SocketInode,
|
||||
@ -118,6 +120,45 @@ impl FileMode {
|
||||
return self.bits() & FileMode::O_ACCMODE.bits();
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct PageCache {
|
||||
inode_ref: Weak<dyn IndexNode>,
|
||||
map: HashMap<usize, Arc<Page>>,
|
||||
}
|
||||
|
||||
impl PageCache {
|
||||
pub fn new(inode_ref: Weak<dyn IndexNode>) -> PageCache {
|
||||
Self {
|
||||
inode_ref,
|
||||
map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_page(&mut self, offset: usize, page: Arc<Page>) {
|
||||
self.map.insert(offset, page);
|
||||
}
|
||||
|
||||
pub fn get_page(&self, offset: usize) -> Option<Arc<Page>> {
|
||||
self.map.get(&offset).cloned()
|
||||
}
|
||||
|
||||
// pub fn get_pages(&self, start_pgoff: usize, end_pgoff: usize) -> Vec<Arc<Page>> {
|
||||
// let mut vec = Vec::new();
|
||||
// for pgoff in start_pgoff..=end_pgoff {
|
||||
// if let Some(page) = self.map.get(&pgoff) {
|
||||
// vec.push(page.clone());
|
||||
// }
|
||||
// }
|
||||
// vec
|
||||
// }
|
||||
}
|
||||
|
||||
pub trait PageCacheOperations: IndexNode {
|
||||
fn write_page(&self, page: Page);
|
||||
fn read_ahead(&self);
|
||||
}
|
||||
|
||||
/// @brief 抽象文件结构体
|
||||
#[derive(Debug)]
|
||||
pub struct File {
|
||||
|
@ -23,7 +23,12 @@ use crate::{
|
||||
time::PosixTimeSpec,
|
||||
};
|
||||
|
||||
use self::{core::generate_inode_id, file::FileMode, syscall::ModeType, utils::DName};
|
||||
use self::{
|
||||
core::generate_inode_id,
|
||||
file::{FileMode, PageCache},
|
||||
syscall::ModeType,
|
||||
utils::DName,
|
||||
};
|
||||
pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS};
|
||||
|
||||
/// vfs容许的最大的路径名称长度
|
||||
@ -548,6 +553,10 @@ pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync {
|
||||
fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> {
|
||||
return self.find("..");
|
||||
}
|
||||
|
||||
fn page_cache(&self) -> Option<PageCache> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl DowncastArc for dyn IndexNode {
|
||||
|
@ -165,7 +165,7 @@ impl ShmManager {
|
||||
let mut page_manager_guard = page_manager_lock_irqsave();
|
||||
let mut cur_phys = PhysPageFrame::new(phys_page.0);
|
||||
for _ in 0..page_count.data() {
|
||||
let mut page = Page::new(true);
|
||||
let mut page = Page::new(true, cur_phys);
|
||||
page.set_shm_id(shm_id);
|
||||
let paddr = cur_phys.phys_address();
|
||||
page_manager_guard.insert(paddr, page);
|
||||
|
@ -20,7 +20,7 @@ use crate::{
|
||||
libs::spinlock::SpinLock,
|
||||
mm::{
|
||||
allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame},
|
||||
page::{page_manager_lock_irqsave, PageFlags, PageFlushAll},
|
||||
page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll},
|
||||
syscall::ProtFlags,
|
||||
ucontext::{AddressSpace, VMA},
|
||||
VirtAddr, VmFlags,
|
||||
@ -324,8 +324,8 @@ impl Syscall {
|
||||
.ok_or(SystemError::EINVAL)?;
|
||||
let vm_flags = VmFlags::from(shmflg);
|
||||
let destination = VirtPageFrame::new(region.start());
|
||||
let page_flags: PageFlags<MMArch> =
|
||||
PageFlags::from_prot_flags(ProtFlags::from(vm_flags), true);
|
||||
let page_flags: EntryFlags<MMArch> =
|
||||
EntryFlags::from_prot_flags(ProtFlags::from(vm_flags), true);
|
||||
let flusher: PageFlushAll<MMArch> = PageFlushAll::new();
|
||||
|
||||
// 将共享内存映射到对应虚拟区域
|
||||
@ -358,7 +358,7 @@ impl Syscall {
|
||||
// 验证用户虚拟内存区域是否有效
|
||||
let _ = UserBufferReader::new(vaddr.data() as *const u8, size, true)?;
|
||||
|
||||
// 必须在取消映射前获取到PageFlags
|
||||
// 必须在取消映射前获取到EntryFlags
|
||||
let page_flags = address_write_guard
|
||||
.user_mapper
|
||||
.utable
|
||||
|
@ -15,7 +15,7 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
allocator::page_frame::PageFrameCount, kernel_mapper::KernelMapper, mmio_buddy::mmio_pool,
|
||||
no_init::pseudo_map_phys, page::PageFlags, MemoryManagementArch, PhysAddr, VirtAddr,
|
||||
no_init::pseudo_map_phys, page::EntryFlags, MemoryManagementArch, PhysAddr, VirtAddr,
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
@ -40,7 +40,7 @@ pub unsafe extern "C" fn rs_map_phys(vaddr: usize, paddr: usize, size: usize, fl
|
||||
let count = PageFrameCount::new(page_align_up(size) / MMArch::PAGE_SIZE);
|
||||
// debug!("rs_map_phys: vaddr: {vaddr:?}, paddr: {paddr:?}, count: {count:?}, flags: {flags:?}");
|
||||
|
||||
let mut page_flags: PageFlags<MMArch> = PageFlags::new().set_execute(true).set_write(true);
|
||||
let mut page_flags: EntryFlags<MMArch> = EntryFlags::new().set_execute(true).set_write(true);
|
||||
if flags & PAGE_U_S as usize != 0 {
|
||||
page_flags = page_flags.set_user(true);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
use core::{alloc::Layout, intrinsics::unlikely, panic};
|
||||
use core::{alloc::Layout, cmp::min, intrinsics::unlikely, panic};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
arch::{mm::PageMapper, MMArch},
|
||||
mm::{
|
||||
page::{page_manager_lock_irqsave, PageFlags},
|
||||
page::{page_manager_lock_irqsave, EntryFlags},
|
||||
ucontext::LockedVMA,
|
||||
VirtAddr, VmFaultReason, VmFlags,
|
||||
},
|
||||
@ -14,21 +14,27 @@ use crate::{
|
||||
|
||||
use crate::mm::MemoryManagementArch;
|
||||
|
||||
use super::{
|
||||
allocator::page_frame::{FrameAllocator, PhysPageFrame},
|
||||
page::{Page, PageFlags},
|
||||
phys_2_virt,
|
||||
};
|
||||
|
||||
bitflags! {
|
||||
pub struct FaultFlags: u64{
|
||||
const FAULT_FLAG_WRITE = 1 << 0;
|
||||
const FAULT_FLAG_MKWRITE = 1 << 1;
|
||||
const FAULT_FLAG_ALLOW_RETRY = 1 << 2;
|
||||
const FAULT_FLAG_RETRY_NOWAIT = 1 << 3;
|
||||
const FAULT_FLAG_KILLABLE = 1 << 4;
|
||||
const FAULT_FLAG_TRIED = 1 << 5;
|
||||
const FAULT_FLAG_USER = 1 << 6;
|
||||
const FAULT_FLAG_REMOTE = 1 << 7;
|
||||
const FAULT_FLAG_INSTRUCTION = 1 << 8;
|
||||
const FAULT_FLAG_INTERRUPTIBLE =1 << 9;
|
||||
const FAULT_FLAG_UNSHARE = 1 << 10;
|
||||
const FAULT_FLAG_ORIG_PTE_VALID = 1 << 11;
|
||||
const FAULT_FLAG_VMA_LOCK = 1 << 12;
|
||||
const FAULT_FLAG_WRITE = 1 << 0;
|
||||
const FAULT_FLAG_MKWRITE = 1 << 1;
|
||||
const FAULT_FLAG_ALLOW_RETRY = 1 << 2;
|
||||
const FAULT_FLAG_RETRY_NOWAIT = 1 << 3;
|
||||
const FAULT_FLAG_KILLABLE = 1 << 4;
|
||||
const FAULT_FLAG_TRIED = 1 << 5;
|
||||
const FAULT_FLAG_USER = 1 << 6;
|
||||
const FAULT_FLAG_REMOTE = 1 << 7;
|
||||
const FAULT_FLAG_INSTRUCTION = 1 << 8;
|
||||
const FAULT_FLAG_INTERRUPTIBLE =1 << 9;
|
||||
const FAULT_FLAG_UNSHARE = 1 << 10;
|
||||
const FAULT_FLAG_ORIG_PTE_VALID = 1 << 11;
|
||||
const FAULT_FLAG_VMA_LOCK = 1 << 12;
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,9 +42,14 @@ bitflags! {
|
||||
/// 包含了页面错误处理的相关信息,例如出错的地址、VMA等
|
||||
#[derive(Debug)]
|
||||
pub struct PageFaultMessage {
|
||||
/// 产生缺页的VMA结构体
|
||||
vma: Arc<LockedVMA>,
|
||||
/// 缺页地址
|
||||
address: VirtAddr,
|
||||
/// 异常处理标志
|
||||
flags: FaultFlags,
|
||||
/// 缺页的文件页在文件中的偏移量
|
||||
file_pgoff: usize,
|
||||
}
|
||||
|
||||
impl PageFaultMessage {
|
||||
@ -47,6 +58,8 @@ impl PageFaultMessage {
|
||||
vma: vma.clone(),
|
||||
address,
|
||||
flags,
|
||||
file_pgoff: ((address - vma.lock().region().start()) >> MMArch::PAGE_SHIFT)
|
||||
+ vma.lock().file_page_offset().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,8 +71,8 @@ impl PageFaultMessage {
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(dead_code)]
|
||||
pub fn address(&self) -> VirtAddr {
|
||||
self.address
|
||||
pub fn address(&self) -> &VirtAddr {
|
||||
&self.address
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -70,8 +83,8 @@ impl PageFaultMessage {
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(dead_code)]
|
||||
pub fn flags(&self) -> FaultFlags {
|
||||
self.flags
|
||||
pub fn flags(&self) -> &FaultFlags {
|
||||
&self.flags
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +94,7 @@ impl Clone for PageFaultMessage {
|
||||
vma: self.vma.clone(),
|
||||
address: self.address,
|
||||
flags: self.flags,
|
||||
file_pgoff: self.file_pgoff,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,7 +203,7 @@ impl PageFaultHandler {
|
||||
if !entry.write() {
|
||||
ret = Self::do_wp_page(pfm.clone(), mapper);
|
||||
} else {
|
||||
entry.set_flags(PageFlags::from_data(MMArch::ENTRY_FLAG_DIRTY));
|
||||
entry.set_flags(EntryFlags::from_data(MMArch::ENTRY_FLAG_DIRTY));
|
||||
}
|
||||
}
|
||||
} else if vma.is_anonymous() {
|
||||
@ -248,14 +262,22 @@ impl PageFaultHandler {
|
||||
/// - VmFaultReason: 页面错误处理信息标志
|
||||
#[allow(unused_variables)]
|
||||
pub unsafe fn do_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
|
||||
panic!(
|
||||
"do_fault has not yet been implemented,
|
||||
fault message: {:?},
|
||||
pid: {}\n",
|
||||
pfm,
|
||||
crate::process::ProcessManager::current_pid().data()
|
||||
);
|
||||
// panic!(
|
||||
// "do_fault has not yet been implemented,
|
||||
// fault message: {:?},
|
||||
// pid: {}\n",
|
||||
// pfm,
|
||||
// crate::process::ProcessManager::current_pid().data()
|
||||
// );
|
||||
// TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_fault
|
||||
|
||||
if !pfm.flags().contains(FaultFlags::FAULT_FLAG_WRITE) {
|
||||
return Self::do_read_fault(pfm, mapper);
|
||||
} else if !pfm.vma().lock().vm_flags().contains(VmFlags::VM_SHARED) {
|
||||
return Self::do_cow_fault(pfm, mapper);
|
||||
} else {
|
||||
return Self::do_shared_fault(pfm, mapper);
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理私有文件映射的写时复制
|
||||
@ -288,14 +310,20 @@ impl PageFaultHandler {
|
||||
/// - VmFaultReason: 页面错误处理信息标志
|
||||
#[allow(dead_code, unused_variables)]
|
||||
pub unsafe fn do_read_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
|
||||
panic!(
|
||||
"do_read_fault has not yet been implemented,
|
||||
fault message: {:?},
|
||||
pid: {}\n",
|
||||
pfm,
|
||||
crate::process::ProcessManager::current_pid().data()
|
||||
);
|
||||
// panic!(
|
||||
// "do_read_fault has not yet been implemented,
|
||||
// fault message: {:?},
|
||||
// pid: {}\n",
|
||||
// pfm,
|
||||
// crate::process::ProcessManager::current_pid().data()
|
||||
// );
|
||||
|
||||
// TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_read_fault
|
||||
let ret = Self::do_fault_around(pfm.clone(), mapper);
|
||||
if !ret.is_empty() {
|
||||
return ret;
|
||||
}
|
||||
return Self::filemap_fault(pfm.clone(), mapper);
|
||||
}
|
||||
|
||||
/// 处理对共享文件映射区写入引起的缺页
|
||||
@ -405,4 +433,144 @@ impl PageFaultHandler {
|
||||
VmFaultReason::VM_FAULT_OOM
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn do_fault_around(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
|
||||
if mapper.get_table(*pfm.address(), 0).is_none() {
|
||||
mapper
|
||||
.allocate_table(*pfm.address(), 0)
|
||||
.expect("failed to allocate pte table");
|
||||
}
|
||||
let vma = pfm.vma();
|
||||
let vma_guard = vma.lock();
|
||||
let vma_region = vma_guard.region();
|
||||
// 缺页在VMA中的偏移量
|
||||
let vm_pgoff = (*pfm.address() - vma_region.start()) >> MMArch::PAGE_SHIFT;
|
||||
|
||||
// 缺页在PTE中的偏移量
|
||||
let pte_pgoff =
|
||||
(pfm.address().data() >> MMArch::PAGE_SHIFT) & (1 << MMArch::PAGE_ENTRY_SHIFT);
|
||||
|
||||
let vma_pages_count = (vma_region.end() - vma_region.start()) >> MMArch::PAGE_SHIFT;
|
||||
|
||||
// 开始位置不能超出当前pte和vma头部
|
||||
let from_pte = pte_pgoff - min(vm_pgoff, pte_pgoff);
|
||||
|
||||
let fault_around_page_number = 16;
|
||||
|
||||
// pte结束位置不能超过:
|
||||
// 1.最大预读上限(默认16)
|
||||
// 2.最大pte(512)
|
||||
// 3.vma结束位置(pte_pgoff + (vma_pages_count - vm_pgoff)计算出vma结束页号对当前pte开头的偏移)
|
||||
let to_pte = min(
|
||||
from_pte + fault_around_page_number,
|
||||
min(
|
||||
1 << MMArch::PAGE_SHIFT,
|
||||
pte_pgoff + (vma_pages_count - vm_pgoff),
|
||||
),
|
||||
);
|
||||
|
||||
// 预先分配pte页表(如果不存在)
|
||||
if mapper.get_table(*pfm.address(), 0).is_none()
|
||||
&& mapper.allocate_table(*pfm.address(), 0).is_none()
|
||||
{
|
||||
return VmFaultReason::VM_FAULT_OOM;
|
||||
}
|
||||
|
||||
// from_pte - pte_pgoff得出预读起始pte相对缺失页的偏移,加上pfm.file_pgoff(缺失页在文件中的偏移)得出起始页在文件中的偏移,结束pte同理
|
||||
Self::filemap_map_pages(
|
||||
pfm.clone(),
|
||||
mapper,
|
||||
pfm.file_pgoff + (from_pte - pte_pgoff),
|
||||
pfm.file_pgoff + (to_pte - pte_pgoff),
|
||||
);
|
||||
|
||||
VmFaultReason::empty()
|
||||
}
|
||||
|
||||
pub unsafe fn filemap_map_pages(
|
||||
pfm: PageFaultMessage,
|
||||
mapper: &mut PageMapper,
|
||||
start_pgoff: usize,
|
||||
end_pgoff: usize,
|
||||
) -> VmFaultReason {
|
||||
let vma = pfm.vma();
|
||||
let vma_guard = vma.lock();
|
||||
let file = vma_guard.vm_file().expect("no vm_file in vma");
|
||||
let page_cache = file.inode().page_cache().unwrap();
|
||||
|
||||
// 起始页地址
|
||||
let addr = vma_guard.region().start
|
||||
+ ((start_pgoff
|
||||
- vma_guard
|
||||
.file_page_offset()
|
||||
.expect("file_page_offset is none"))
|
||||
<< MMArch::PAGE_SHIFT);
|
||||
// let pages = page_cache.get_pages(start_pgoff, end_pgoff);
|
||||
// let uptodate_pages = pages
|
||||
// .iter()
|
||||
// .filter(|page| page.flags().contains(PageFlags::PG_UPTODATE));
|
||||
for pgoff in start_pgoff..=end_pgoff {
|
||||
if let Some(page) = page_cache.get_page(pgoff) {
|
||||
if page.flags().contains(PageFlags::PG_UPTODATE) {
|
||||
let phys = page.phys_frame().phys_address();
|
||||
let virt = phys_2_virt(phys.data());
|
||||
|
||||
let address =
|
||||
VirtAddr::new(addr.data() + ((pgoff - start_pgoff) << MMArch::PAGE_SHIFT));
|
||||
mapper.map(address, vma_guard.flags()).unwrap().flush();
|
||||
let frame = virt as *mut u8;
|
||||
let new_frame =
|
||||
phys_2_virt(mapper.translate(address).unwrap().0.data()) as *mut u8;
|
||||
new_frame.copy_from_nonoverlapping(frame, MMArch::PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
VmFaultReason::empty()
|
||||
}
|
||||
|
||||
pub unsafe fn filemap_fault(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
|
||||
let vma = pfm.vma();
|
||||
let vma_guard = vma.lock();
|
||||
let file = vma_guard.vm_file().expect("no vm_file in vma");
|
||||
let mut page_cache = file.inode().page_cache().unwrap();
|
||||
|
||||
if let Some(page) = page_cache.get_page(pfm.file_pgoff) {
|
||||
// TODO 异步从磁盘中预读页面进PageCache
|
||||
let address = vma_guard.region().start
|
||||
+ ((pfm.file_pgoff
|
||||
- vma_guard
|
||||
.file_page_offset()
|
||||
.expect("file_page_offset is none"))
|
||||
<< MMArch::PAGE_SHIFT);
|
||||
mapper.map(address, vma_guard.flags()).unwrap().flush();
|
||||
let frame = phys_2_virt(page.phys_frame().phys_address().data()) as *mut u8;
|
||||
let new_frame = phys_2_virt(mapper.translate(address).unwrap().0.data()) as *mut u8;
|
||||
new_frame.copy_from_nonoverlapping(frame, MMArch::PAGE_SIZE);
|
||||
} else {
|
||||
// TODO 同步预读
|
||||
let mut buf: Vec<u8> = vec![0; MMArch::PAGE_SIZE];
|
||||
file.pread(
|
||||
pfm.file_pgoff * MMArch::PAGE_SIZE,
|
||||
MMArch::PAGE_SIZE,
|
||||
&mut buf[..],
|
||||
)
|
||||
.unwrap();
|
||||
let allocator = mapper.allocator_mut();
|
||||
|
||||
// 分配一个物理页面作为加入PageCache的新页
|
||||
let new_cache_page = allocator.allocate_one().unwrap();
|
||||
(phys_2_virt(new_cache_page.data()) as *mut u8)
|
||||
.copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE);
|
||||
page_cache.add_page(
|
||||
pfm.file_pgoff,
|
||||
Arc::new(Page::new(false, PhysPageFrame::new(new_cache_page))),
|
||||
);
|
||||
|
||||
// 分配空白页并映射到缺页地址
|
||||
mapper.map(pfm.address, vma_guard.flags()).unwrap().flush();
|
||||
let new_frame = phys_2_virt(mapper.translate(pfm.address).unwrap().0.data());
|
||||
(new_frame as *mut u8).copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE);
|
||||
}
|
||||
VmFaultReason::VM_FAULT_COMPLETED
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::{page::PageFlags, PageTableKind, PhysAddr, VirtAddr};
|
||||
use super::{page::EntryFlags, PageTableKind, PhysAddr, VirtAddr};
|
||||
use crate::{
|
||||
arch::{
|
||||
mm::{LockedFrameAllocator, PageMapper},
|
||||
@ -104,7 +104,7 @@ impl KernelMapper {
|
||||
mut vaddr: VirtAddr,
|
||||
mut paddr: PhysAddr,
|
||||
size: usize,
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
flush: bool,
|
||||
) -> Result<(), SystemError> {
|
||||
if self.readonly {
|
||||
|
@ -12,7 +12,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use log::{debug, error, info, warn};
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::page::{PageFlags, PAGE_4K_SIZE};
|
||||
use super::page::{EntryFlags, PAGE_4K_SIZE};
|
||||
use super::{PhysAddr, VirtAddr};
|
||||
|
||||
// 最大的伙伴块的幂
|
||||
@ -549,7 +549,7 @@ impl MmioBuddyMemPool {
|
||||
unsafe {
|
||||
let x: Option<(
|
||||
PhysAddr,
|
||||
PageFlags<MMArch>,
|
||||
EntryFlags<MMArch>,
|
||||
crate::mm::page::PageFlush<MMArch>,
|
||||
)> = kernel_mapper
|
||||
.as_mut()
|
||||
@ -674,7 +674,7 @@ impl MMIOSpaceGuard {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let flags = PageFlags::mmio_flags();
|
||||
let flags = EntryFlags::mmio_flags();
|
||||
|
||||
let mut kernel_mapper = KernelMapper::lock();
|
||||
let r = kernel_mapper.map_phys_with_size(self.vaddr, paddr, length, flags, true);
|
||||
|
@ -610,7 +610,7 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
|
||||
|
||||
/// 创建页表项
|
||||
///
|
||||
/// 这是一个低阶api,用于根据物理地址以及指定好的pageflags,创建页表项
|
||||
/// 这是一个低阶api,用于根据物理地址以及指定好的EntryFlags,创建页表项
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
|
@ -19,7 +19,7 @@ use core::marker::PhantomData;
|
||||
|
||||
use super::{
|
||||
allocator::page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage},
|
||||
page::PageFlags,
|
||||
page::EntryFlags,
|
||||
PageTableKind, VirtAddr,
|
||||
};
|
||||
|
||||
@ -141,7 +141,7 @@ impl<MMA: MemoryManagementArch> FrameAllocator for PseudoAllocator<MMA> {
|
||||
/// 并且,内核引导文件必须以4K页为粒度,填写了前100M的内存映射关系。(具体以本文件开头的注释为准)
|
||||
#[inline(never)]
|
||||
pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
|
||||
let flags: PageFlags<MMArch> = PageFlags::new().set_write(true);
|
||||
let flags: EntryFlags<MMArch> = EntryFlags::new().set_write(true);
|
||||
|
||||
pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
|
||||
}
|
||||
@ -150,7 +150,7 @@ pub unsafe fn pseudo_map_phys(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrame
|
||||
/// with READ_ONLY and EXECUTE flags.
|
||||
#[inline(never)]
|
||||
pub unsafe fn pseudo_map_phys_ro(vaddr: VirtAddr, paddr: PhysAddr, count: PageFrameCount) {
|
||||
let flags: PageFlags<MMArch> = PageFlags::new().set_write(false).set_execute(true);
|
||||
let flags: EntryFlags<MMArch> = EntryFlags::new().set_write(false).set_execute(true);
|
||||
|
||||
pseudo_map_phys_with_flags(vaddr, paddr, count, flags);
|
||||
}
|
||||
@ -160,7 +160,7 @@ pub unsafe fn pseudo_map_phys_with_flags(
|
||||
vaddr: VirtAddr,
|
||||
paddr: PhysAddr,
|
||||
count: PageFrameCount,
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
) {
|
||||
assert!(vaddr.check_aligned(MMArch::PAGE_SIZE));
|
||||
assert!(paddr.check_aligned(MMArch::PAGE_SIZE));
|
||||
|
@ -18,7 +18,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
allocator::page_frame::{FrameAllocator, PageFrameCount},
|
||||
allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
|
||||
syscall::ProtFlags,
|
||||
ucontext::LockedVMA,
|
||||
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
|
||||
@ -86,6 +86,27 @@ impl PageManager {
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct PageFlags: u64 {
|
||||
const PG_LOCKED = 1 << 0;
|
||||
const PG_WRITEBACK = 1 << 1;
|
||||
const PG_REFERENCED = 1 << 2;
|
||||
const PG_UPTODATE = 1 << 3;
|
||||
const PG_DIRTY = 1 << 4;
|
||||
const PG_LRU = 1 << 5;
|
||||
const PG_HEAD = 1 << 6;
|
||||
const PG_WAITERS = 1 << 7;
|
||||
const PG_ACTIVE = 1 << 8;
|
||||
const PG_WORKINGSET = 1 << 9;
|
||||
const PG_ERROR = 1 << 10;
|
||||
const PG_SLAB = 1 << 11;
|
||||
const PG_RESERVED = 1 << 14;
|
||||
const PG_PRIVATE = 1 << 15;
|
||||
const PG_RECLAIM = 1 << 18;
|
||||
const PG_SWAPBACKED = 1 << 19;
|
||||
}
|
||||
}
|
||||
|
||||
/// 物理页面信息
|
||||
pub struct Page {
|
||||
/// 映射计数
|
||||
@ -98,10 +119,14 @@ pub struct Page {
|
||||
shm_id: Option<ShmId>,
|
||||
/// 映射到当前page的VMA
|
||||
anon_vma: HashSet<Arc<LockedVMA>>,
|
||||
/// 标志
|
||||
flags: PageFlags,
|
||||
/// 页所在的物理页帧号
|
||||
phys_frame: PhysPageFrame,
|
||||
}
|
||||
|
||||
impl Page {
|
||||
pub fn new(shared: bool) -> Self {
|
||||
pub fn new(shared: bool, phys_frame: PhysPageFrame) -> Self {
|
||||
let dealloc_when_zero = !shared;
|
||||
Self {
|
||||
map_count: 0,
|
||||
@ -109,6 +134,8 @@ impl Page {
|
||||
free_when_zero: dealloc_when_zero,
|
||||
shm_id: None,
|
||||
anon_vma: HashSet::new(),
|
||||
flags: PageFlags::empty(),
|
||||
phys_frame,
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +181,16 @@ impl Page {
|
||||
pub fn map_count(&self) -> usize {
|
||||
self.map_count
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn flags(&self) -> &PageFlags {
|
||||
&self.flags
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn phys_frame(&self) -> &PhysPageFrame {
|
||||
&self.phys_frame
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -330,7 +367,7 @@ impl<Arch: MemoryManagementArch> PageTable<Arch> {
|
||||
} else {
|
||||
let phys = allocator.allocate_one()?;
|
||||
let mut anon_vma_guard = page_manager_lock_irqsave();
|
||||
anon_vma_guard.insert(phys, Page::new(false));
|
||||
anon_vma_guard.insert(phys, Page::new(false, PhysPageFrame::new(phys)));
|
||||
let old_phys = entry.address().unwrap();
|
||||
let frame = MMArch::phys_2_virt(phys).unwrap().data() as *mut u8;
|
||||
frame.copy_from_nonoverlapping(
|
||||
@ -372,7 +409,7 @@ impl<Arch> Debug for PageEntry<Arch> {
|
||||
|
||||
impl<Arch: MemoryManagementArch> PageEntry<Arch> {
|
||||
#[inline(always)]
|
||||
pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> Self {
|
||||
pub fn new(paddr: PhysAddr, flags: EntryFlags<Arch>) -> Self {
|
||||
Self {
|
||||
data: MMArch::make_entry(paddr, flags.data()),
|
||||
phantom: PhantomData,
|
||||
@ -420,12 +457,12 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn flags(&self) -> PageFlags<Arch> {
|
||||
unsafe { PageFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
|
||||
pub fn flags(&self) -> EntryFlags<Arch> {
|
||||
unsafe { EntryFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_flags(&mut self, flags: PageFlags<Arch>) {
|
||||
pub fn set_flags(&mut self, flags: EntryFlags<Arch>) {
|
||||
self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data();
|
||||
}
|
||||
|
||||
@ -453,13 +490,19 @@ impl<Arch: MemoryManagementArch> PageEntry<Arch> {
|
||||
|
||||
/// 页表项的标志位
|
||||
#[derive(Copy, Clone, Hash)]
|
||||
pub struct PageFlags<Arch> {
|
||||
pub struct EntryFlags<Arch> {
|
||||
data: usize,
|
||||
phantom: PhantomData<Arch>,
|
||||
}
|
||||
|
||||
impl<Arch: MemoryManagementArch> Default for EntryFlags<Arch> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
||||
impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
|
||||
#[inline(always)]
|
||||
pub fn new() -> Self {
|
||||
let mut r = unsafe {
|
||||
@ -480,14 +523,14 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
||||
return r;
|
||||
}
|
||||
|
||||
/// 根据ProtFlags生成PageFlags
|
||||
/// 根据ProtFlags生成EntryFlags
|
||||
///
|
||||
/// ## 参数
|
||||
///
|
||||
/// - prot_flags: 页的保护标志
|
||||
/// - user: 用户空间是否可访问
|
||||
pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> {
|
||||
let flags: PageFlags<Arch> = PageFlags::new()
|
||||
pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> EntryFlags<Arch> {
|
||||
let flags: EntryFlags<Arch> = EntryFlags::new()
|
||||
.set_user(user)
|
||||
.set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
|
||||
.set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
|
||||
@ -757,9 +800,9 @@ impl<Arch: MemoryManagementArch> PageFlags<Arch> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> {
|
||||
impl<Arch: MemoryManagementArch> fmt::Debug for EntryFlags<Arch> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PageFlags")
|
||||
f.debug_struct("EntryFlags")
|
||||
.field("bits", &format_args!("{:#0x}", self.data))
|
||||
.field("present", &self.present())
|
||||
.field("has_write", &self.has_write())
|
||||
@ -855,7 +898,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
pub unsafe fn map(
|
||||
&mut self,
|
||||
virt: VirtAddr,
|
||||
flags: PageFlags<Arch>,
|
||||
flags: EntryFlags<Arch>,
|
||||
) -> Option<PageFlush<Arch>> {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
let phys: PhysAddr = self.frame_allocator.allocate_one()?;
|
||||
@ -869,7 +912,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
let mut page_manager_guard: SpinLockGuard<'static, PageManager> =
|
||||
page_manager_lock_irqsave();
|
||||
if !page_manager_guard.contains(&phys) {
|
||||
page_manager_guard.insert(phys, Page::new(false))
|
||||
page_manager_guard.insert(phys, Page::new(false, PhysPageFrame::new(phys)))
|
||||
}
|
||||
|
||||
return self.map_phys(virt, phys, flags);
|
||||
@ -880,7 +923,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
&mut self,
|
||||
virt: VirtAddr,
|
||||
phys: PhysAddr,
|
||||
flags: PageFlags<Arch>,
|
||||
flags: EntryFlags<Arch>,
|
||||
) -> Option<PageFlush<Arch>> {
|
||||
// 验证虚拟地址和物理地址是否对齐
|
||||
if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
|
||||
@ -920,8 +963,8 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
// 清空这个页帧
|
||||
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
|
||||
// 设置页表项的flags
|
||||
let flags: PageFlags<Arch> =
|
||||
PageFlags::new_page_table(virt.kind() == PageTableKind::User);
|
||||
let flags: EntryFlags<Arch> =
|
||||
EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
|
||||
|
||||
// 把新分配的页表映射到当前页表
|
||||
table.set_entry(i, PageEntry::new(frame, flags));
|
||||
@ -937,7 +980,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
pub unsafe fn map_huge_page(
|
||||
&mut self,
|
||||
virt: VirtAddr,
|
||||
flags: PageFlags<Arch>,
|
||||
flags: EntryFlags<Arch>,
|
||||
) -> Option<PageFlush<Arch>> {
|
||||
// 验证虚拟地址是否对齐
|
||||
if !(virt.check_aligned(Arch::PAGE_SIZE)) {
|
||||
@ -1003,7 +1046,8 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
|
||||
|
||||
// 设置页表项的flags
|
||||
let flags: PageFlags<Arch> = PageFlags::new_page_table(virt.kind() == PageTableKind::User);
|
||||
let flags: EntryFlags<Arch> =
|
||||
EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
|
||||
|
||||
table.set_entry(i, PageEntry::new(frame, flags));
|
||||
table.next_level_table(i)
|
||||
@ -1105,7 +1149,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
pub unsafe fn map_linearly(
|
||||
&mut self,
|
||||
phys: PhysAddr,
|
||||
flags: PageFlags<Arch>,
|
||||
flags: EntryFlags<Arch>,
|
||||
) -> Option<(VirtAddr, PageFlush<Arch>)> {
|
||||
let virt: VirtAddr = Arch::phys_2_virt(phys)?;
|
||||
return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
|
||||
@ -1125,7 +1169,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
pub unsafe fn remap(
|
||||
&mut self,
|
||||
virt: VirtAddr,
|
||||
flags: PageFlags<Arch>,
|
||||
flags: EntryFlags<Arch>,
|
||||
) -> Option<PageFlush<Arch>> {
|
||||
return self
|
||||
.visit(virt, |p1, i| {
|
||||
@ -1147,7 +1191,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
/// ## 返回值
|
||||
///
|
||||
/// 如果查找成功,返回物理地址和页表项的flags,否则返回None
|
||||
pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> {
|
||||
pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)> {
|
||||
let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
|
||||
let paddr = entry.address().ok()?;
|
||||
let flags = entry.flags();
|
||||
@ -1186,7 +1230,7 @@ impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
|
||||
&mut self,
|
||||
virt: VirtAddr,
|
||||
unmap_parents: bool,
|
||||
) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> {
|
||||
) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> {
|
||||
if !virt.check_aligned(Arch::PAGE_SIZE) {
|
||||
error!("Try to unmap unaligned page: virt={:?}", virt);
|
||||
return None;
|
||||
@ -1234,7 +1278,7 @@ unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
|
||||
table: &PageTable<Arch>,
|
||||
unmap_parents: bool,
|
||||
allocator: &mut impl FrameAllocator,
|
||||
) -> Option<(PhysAddr, PageFlags<Arch>)> {
|
||||
) -> Option<(PhysAddr, EntryFlags<Arch>)> {
|
||||
// 获取页表项的索引
|
||||
let i = table.index_of(vaddr)?;
|
||||
|
||||
|
@ -20,6 +20,7 @@ use system_error::SystemError;
|
||||
use crate::{
|
||||
arch::{mm::PageMapper, CurrentIrqArch, MMArch},
|
||||
exception::InterruptArch,
|
||||
filesystem::vfs::file::File,
|
||||
libs::{
|
||||
align::page_align_up,
|
||||
rwlock::RwLock,
|
||||
@ -34,7 +35,7 @@ use super::{
|
||||
allocator::page_frame::{
|
||||
deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter,
|
||||
},
|
||||
page::{Flusher, InactiveFlusher, PageFlags, PageFlushAll},
|
||||
page::{EntryFlags, Flusher, InactiveFlusher, PageFlushAll},
|
||||
syscall::{MadvFlags, MapFlags, MremapFlags, ProtFlags},
|
||||
MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, VmFlags,
|
||||
};
|
||||
@ -333,7 +334,7 @@ impl InnerAddressSpace {
|
||||
F: FnOnce(
|
||||
VirtPageFrame,
|
||||
PageFrameCount,
|
||||
PageFlags<MMArch>,
|
||||
EntryFlags<MMArch>,
|
||||
&mut PageMapper,
|
||||
&mut dyn Flusher<MMArch>,
|
||||
) -> Result<Arc<LockedVMA>, SystemError>,
|
||||
@ -380,7 +381,7 @@ impl InnerAddressSpace {
|
||||
self.mappings.insert_vma(map_func(
|
||||
page,
|
||||
page_count,
|
||||
PageFlags::from_prot_flags(prot_flags, true),
|
||||
EntryFlags::from_prot_flags(prot_flags, true),
|
||||
&mut self.user_mapper.utable,
|
||||
flusher,
|
||||
)?);
|
||||
@ -556,7 +557,7 @@ impl InnerAddressSpace {
|
||||
return Err(SystemError::EACCES);
|
||||
}
|
||||
|
||||
let new_flags: PageFlags<MMArch> = r_guard
|
||||
let new_flags: EntryFlags<MMArch> = r_guard
|
||||
.flags()
|
||||
.set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
|
||||
.set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
|
||||
@ -1022,7 +1023,7 @@ impl LockedVMA {
|
||||
///
|
||||
pub fn remap(
|
||||
&self,
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
mapper: &mut PageMapper,
|
||||
mut flusher: impl Flusher<MMArch>,
|
||||
) -> Result<(), SystemError> {
|
||||
@ -1233,13 +1234,17 @@ pub struct VMA {
|
||||
/// 虚拟内存区域标志
|
||||
vm_flags: VmFlags,
|
||||
/// VMA内的页帧的标志
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
/// VMA内的页帧是否已经映射到页表
|
||||
mapped: bool,
|
||||
/// VMA所属的用户地址空间
|
||||
user_address_space: Option<Weak<AddressSpace>>,
|
||||
self_ref: Weak<LockedVMA>,
|
||||
|
||||
vm_file: Option<Arc<File>>,
|
||||
/// VMA映射的文件部分相对于整个文件的偏移页数
|
||||
file_pgoff: Option<usize>,
|
||||
|
||||
provider: Provider,
|
||||
}
|
||||
|
||||
@ -1262,7 +1267,7 @@ impl VMA {
|
||||
pub fn new(
|
||||
region: VirtRegion,
|
||||
vm_flags: VmFlags,
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
mapped: bool,
|
||||
) -> Self {
|
||||
VMA {
|
||||
@ -1273,6 +1278,8 @@ impl VMA {
|
||||
user_address_space: None,
|
||||
self_ref: Weak::default(),
|
||||
provider: Provider::Allocated,
|
||||
file_pgoff: None,
|
||||
vm_file: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1284,6 +1291,10 @@ impl VMA {
|
||||
return &self.vm_flags;
|
||||
}
|
||||
|
||||
pub fn vm_file(&self) -> Option<Arc<File>> {
|
||||
return self.vm_file.clone();
|
||||
}
|
||||
|
||||
pub fn set_vm_flags(&mut self, vm_flags: VmFlags) {
|
||||
self.vm_flags = vm_flags;
|
||||
}
|
||||
@ -1310,6 +1321,8 @@ impl VMA {
|
||||
user_address_space: self.user_address_space.clone(),
|
||||
self_ref: self.self_ref.clone(),
|
||||
provider: Provider::Allocated,
|
||||
file_pgoff: self.file_pgoff,
|
||||
vm_file: self.vm_file.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1322,14 +1335,21 @@ impl VMA {
|
||||
user_address_space: None,
|
||||
self_ref: Weak::default(),
|
||||
provider: Provider::Allocated,
|
||||
file_pgoff: self.file_pgoff,
|
||||
vm_file: self.vm_file.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn flags(&self) -> PageFlags<MMArch> {
|
||||
pub fn flags(&self) -> EntryFlags<MMArch> {
|
||||
return self.flags;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn file_page_offset(&self) -> Option<usize> {
|
||||
return self.file_pgoff;
|
||||
}
|
||||
|
||||
pub fn pages(&self) -> VirtPageFrameIter {
|
||||
return VirtPageFrameIter::new(
|
||||
VirtPageFrame::new(self.region.start()),
|
||||
@ -1339,7 +1359,7 @@ impl VMA {
|
||||
|
||||
pub fn remap(
|
||||
&mut self,
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
mapper: &mut PageMapper,
|
||||
mut flusher: impl Flusher<MMArch>,
|
||||
) -> Result<(), SystemError> {
|
||||
@ -1392,7 +1412,7 @@ impl VMA {
|
||||
destination: VirtPageFrame,
|
||||
count: PageFrameCount,
|
||||
vm_flags: VmFlags,
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
mapper: &mut PageMapper,
|
||||
mut flusher: impl Flusher<MMArch>,
|
||||
) -> Result<Arc<LockedVMA>, SystemError> {
|
||||
@ -1414,15 +1434,12 @@ impl VMA {
|
||||
cur_dest = cur_dest.next();
|
||||
}
|
||||
|
||||
let r: Arc<LockedVMA> = LockedVMA::new(VMA {
|
||||
region: VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
|
||||
let r: Arc<LockedVMA> = LockedVMA::new(VMA::new(
|
||||
VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
|
||||
vm_flags,
|
||||
flags,
|
||||
mapped: true,
|
||||
user_address_space: None,
|
||||
self_ref: Weak::default(),
|
||||
provider: Provider::Allocated,
|
||||
});
|
||||
true,
|
||||
));
|
||||
|
||||
// 将VMA加入到anon_vma中
|
||||
let mut page_manager_guard = page_manager_lock_irqsave();
|
||||
@ -1450,7 +1467,7 @@ impl VMA {
|
||||
destination: VirtPageFrame,
|
||||
page_count: PageFrameCount,
|
||||
vm_flags: VmFlags,
|
||||
flags: PageFlags<MMArch>,
|
||||
flags: EntryFlags<MMArch>,
|
||||
mapper: &mut PageMapper,
|
||||
mut flusher: impl Flusher<MMArch>,
|
||||
) -> Result<Arc<LockedVMA>, SystemError> {
|
||||
|
@ -2,7 +2,7 @@ use log::debug;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::{vcpu::Vcpu, vm};
|
||||
use crate::mm::{kernel_mapper::KernelMapper, page::PageFlags, VirtAddr};
|
||||
use crate::mm::{kernel_mapper::KernelMapper, page::EntryFlags, VirtAddr};
|
||||
|
||||
/*
|
||||
* Address types:
|
||||
@ -152,7 +152,7 @@ fn hva_to_pfn(addr: u64, _atomic: bool, _writable: &mut bool) -> Result<u64, Sys
|
||||
return Ok(hpa.data() as u64 >> PAGE_SHIFT);
|
||||
}
|
||||
unsafe {
|
||||
mapper.map(hva, PageFlags::mmio_flags());
|
||||
mapper.map(hva, EntryFlags::mmio_flags());
|
||||
}
|
||||
let (hpa, _) = mapper.translate(hva).unwrap();
|
||||
return Ok(hpa.data() as u64 >> PAGE_SHIFT);
|
||||
|
Reference in New Issue
Block a user