Merge branch 'patch-add-file-mapping' into patch-fix-mmap

This commit is contained in:
MemoryShore
2024-05-28 17:17:54 +08:00
20 changed files with 396 additions and 117 deletions

View File

@ -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)
}

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

@ -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);
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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 {

View 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 {

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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);

View File

@ -610,7 +610,7 @@ pub trait MemoryManagementArch: Clone + Copy + Debug {
/// 创建页表项
///
/// 这是一个低阶api用于根据物理地址以及指定好的pageflags创建页表项
/// 这是一个低阶api用于根据物理地址以及指定好的EntryFlags创建页表项
///
/// ## 参数
///

View File

@ -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));

View File

@ -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)?;

View File

@ -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> {

View File

@ -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);