mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-22 19:33:26 +00:00
20240527 0010
This commit is contained in:
@ -12,7 +12,7 @@ use crate::{
|
||||
page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
|
||||
},
|
||||
kernel_mapper::KernelMapper,
|
||||
page::{PageEntry, EntryFlags, PAGE_1G_SHIFT},
|
||||
page::{EntryFlags, PageEntry, PAGE_1G_SHIFT},
|
||||
ucontext::UserMapper,
|
||||
MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
|
||||
},
|
||||
|
@ -27,7 +27,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use crate::mm::kernel_mapper::KernelMapper;
|
||||
use crate::mm::page::{PageEntry, EntryFlags, PAGE_1G_SHIFT};
|
||||
use crate::mm::page::{EntryFlags, PageEntry, PAGE_1G_SHIFT};
|
||||
use crate::mm::{MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr};
|
||||
use crate::{kdebug, kinfo, kwarn};
|
||||
use system_error::SystemError;
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
base::{block::SeekFrom, device::DevicePrivateData},
|
||||
tty::tty_device::TtyFilePrivateData,
|
||||
},
|
||||
filesystem::{fat::fs::LockedFATInode, procfs::ProcfsFilePrivateData},
|
||||
filesystem::procfs::ProcfsFilePrivateData,
|
||||
ipc::pipe::{LockedPipeInode, PipeFsPrivateData},
|
||||
kerror,
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
@ -25,7 +25,7 @@ use crate::{
|
||||
process::ProcessManager,
|
||||
};
|
||||
|
||||
use super::{mount::MountFSInode, Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
|
||||
use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
|
||||
|
||||
/// 文件私有信息的枚举类型
|
||||
#[derive(Debug, Clone)]
|
||||
@ -121,6 +121,7 @@ impl FileMode {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct PageCache {
|
||||
inode_ref: Weak<dyn IndexNode>,
|
||||
map: HashMap<usize, Arc<Page>>,
|
||||
@ -134,12 +135,12 @@ impl PageCache {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_page(&mut self, offset: usize, page: Arc<Page>) {
|
||||
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).map(|page| page.clone())
|
||||
self.map.get(&offset).cloned()
|
||||
}
|
||||
|
||||
// pub fn get_pages(&self, start_pgoff: usize, end_pgoff: usize) -> Vec<Arc<Page>> {
|
||||
@ -158,16 +159,6 @@ pub trait PageCacheOperations: IndexNode {
|
||||
fn read_ahead(&self);
|
||||
}
|
||||
|
||||
impl PageCacheOperations for LockedFATInode {
|
||||
fn write_page(&self, page: Page) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn read_ahead(&self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief 抽象文件结构体
|
||||
#[derive(Debug)]
|
||||
pub struct File {
|
||||
|
@ -1,6 +1,6 @@
|
||||
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},
|
||||
@ -15,7 +15,8 @@ use crate::{
|
||||
use crate::mm::MemoryManagementArch;
|
||||
|
||||
use super::{
|
||||
page::{self, PageFlags},
|
||||
allocator::page_frame::{FrameAllocator, PhysPageFrame},
|
||||
page::{Page, PageFlags},
|
||||
phys_2_virt,
|
||||
};
|
||||
|
||||
@ -309,19 +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 mut ret = VmFaultReason::empty();
|
||||
ret = Self::do_fault_around(pfm, mapper);
|
||||
ret = Self::filemap_fault(pfm, mapper);
|
||||
return ret;
|
||||
let ret = Self::do_fault_around(pfm.clone(), mapper);
|
||||
if !ret.is_empty() {
|
||||
return ret;
|
||||
}
|
||||
return Self::filemap_fault(pfm.clone(), mapper);
|
||||
}
|
||||
|
||||
/// 处理对共享文件映射区写入引起的缺页
|
||||
@ -433,20 +435,24 @@ impl PageFaultHandler {
|
||||
}
|
||||
|
||||
pub unsafe fn do_fault_around(pfm: PageFaultMessage, mapper: &mut PageMapper) -> VmFaultReason {
|
||||
mapper
|
||||
.allocate_table(*pfm.address(), 0)
|
||||
.expect("failed to allocate pte table");
|
||||
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_SIZE);
|
||||
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头部的最小值
|
||||
// 开始位置不能超出当前pte和vma头部
|
||||
let from_pte = pte_pgoff - min(vm_pgoff, pte_pgoff);
|
||||
|
||||
let fault_around_page_number = 16;
|
||||
@ -464,11 +470,11 @@ impl PageFaultHandler {
|
||||
);
|
||||
|
||||
// 预先分配pte页表(如果不存在)
|
||||
if mapper.get_table(*pfm.address(), 0).is_none() {
|
||||
if mapper.allocate_table(*pfm.address(), 0).is_none() {
|
||||
return VmFaultReason::VM_FAULT_OOM;
|
||||
}
|
||||
};
|
||||
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(
|
||||
@ -515,7 +521,7 @@ impl PageFaultHandler {
|
||||
let frame = virt as *mut u8;
|
||||
let new_frame =
|
||||
phys_2_virt(mapper.translate(address).unwrap().0.data()) as *mut u8;
|
||||
frame.copy_from_nonoverlapping(new_frame, MMArch::PAGE_SIZE);
|
||||
new_frame.copy_from_nonoverlapping(frame, MMArch::PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -526,22 +532,44 @@ impl PageFaultHandler {
|
||||
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 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
|
||||
+ ((pfm.file_pgoff
|
||||
- vma_guard
|
||||
.file_page_offset()
|
||||
.expect("file_page_offset is none")
|
||||
.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;
|
||||
frame.copy_from_nonoverlapping(new_frame, MMArch::PAGE_SIZE);
|
||||
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
|
||||
}
|
||||
|
@ -495,6 +495,12 @@ pub struct EntryFlags<Arch> {
|
||||
phantom: PhantomData<Arch>,
|
||||
}
|
||||
|
||||
impl<Arch: MemoryManagementArch> Default for EntryFlags<Arch> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
|
||||
#[inline(always)]
|
||||
|
Reference in New Issue
Block a user