Skip to content
This repository was archived by the owner on Nov 26, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion modules/axfs/src/fops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub type FilePerm = axfs_vfs::VfsNodePerm;
pub struct File {
node: WithCap<VfsNodeRef>,
is_append: bool,
is_direct: bool,
offset: u64,
}

Expand All @@ -46,6 +47,7 @@ pub struct OpenOptions {
create: bool,
create_new: bool,
directory: bool,
direct: bool,
// system-specific
_custom_flags: i32,
_mode: u32,
Expand All @@ -64,6 +66,7 @@ impl OpenOptions {
create: false,
create_new: false,
directory: false,
direct: false,
// system-specific
_custom_flags: 0,
_mode: 0o666,
Expand Down Expand Up @@ -101,6 +104,11 @@ impl OpenOptions {
pub fn directory(&mut self, directory: bool) {
self.directory = directory;
}
/// Sets the option to use page cache
pub fn direct(&mut self, direct: bool) {
self.direct = direct;
}

/// check whether contains directory.
pub fn has_directory(&self) -> bool {
self.directory
Expand Down Expand Up @@ -152,7 +160,6 @@ impl File {
}

fn _open_at(dir: Option<&VfsNodeRef>, path: &str, opts: &OpenOptions) -> AxResult<Self> {
debug!("open file: {} {:?}", path, opts);
if !opts.is_valid() {
return ax_err!(InvalidInput);
}
Expand Down Expand Up @@ -192,6 +199,7 @@ impl File {
Ok(Self {
node: WithCap::new(node, access_cap),
is_append: opts.append,
is_direct: opts.direct,
offset: 0,
})
}
Expand Down Expand Up @@ -279,6 +287,16 @@ impl File {
pub fn get_attr(&self) -> AxResult<FileAttr> {
self.access_node(Cap::empty())?.get_attr()
}

/// Gets the file offset
pub fn get_offset(&self) -> u64 {
self.offset
}

/// Check whether direct or not
pub fn is_direct(&self) -> bool {
self.is_direct
}
}

impl Directory {
Expand Down
71 changes: 69 additions & 2 deletions modules/axmm/src/aspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::fmt;

use axerrno::{AxError, AxResult, ax_err};
use axhal::mem::phys_to_virt;
use axhal::paging::{MappingFlags, PageTable, PagingError};
use axhal::paging::{MappingFlags, PageTable, PagingError, PageSize};
use memory_addr::{
MemoryAddr, PAGE_SIZE_4K, PageIter4K, PhysAddr, VirtAddr, VirtAddrRange, is_aligned_4k,
};
Expand Down Expand Up @@ -161,6 +161,58 @@ impl AddrSpace {
Ok(())
}

pub fn map_shm(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we don't need to add this function?

&mut self,
start: VirtAddr,
size: usize,
flags: MappingFlags,
populate: bool,
) -> AxResult {
panic!("Unimplement");
}

/// Add a new file mapping
pub fn map_file(
&mut self,
start: VirtAddr,
size: usize,
flags: MappingFlags,
fd: i32,
offset: usize,
shared: bool,
populate: bool,
) -> AxResult {
self.validate_region(start, size)?;
// warn!("map file flags: {}", flags.contains(MappingFlags::WRITE));
let area = MemoryArea::new(start, size, flags, Backend::new_file(fd, offset, shared, populate));
self.areas
.map(area, &mut self.pt, false)
.map_err(mapping_err_to_ax_err)?;
Ok(())
}

/// Forcely set the page table
pub fn force_map_page(
&mut self,
vaddr: VirtAddr,
paddr: PhysAddr,
access_flags: MappingFlags
) -> bool {
match self.areas.find(vaddr) {
Some(area) => {
if area.flags().contains(access_flags) {
self.pt.map(vaddr, paddr, PageSize::Size4K, area.flags())
.map(|_| true)
.unwrap_or_else(|_| panic!("FORCE MAP PAGE FAILED(PAGE TABLE FAILEDA): {:#x} => {:#x}!", vaddr, paddr));
} else {
panic!("FORCE MAP PAGE FAILED(ACCESS MOD): {:#x} => {:#x}!", vaddr, paddr);
}
},
_ => panic!("FORCE MAP PAGE FAILED(NO AREA): {:#x} => {:#x}!", vaddr, paddr),
};
true
}

/// Populates the area with physical frames, returning false if the area
/// contains unmapped area.
pub fn populate_area(&mut self, mut start: VirtAddr, size: usize) -> AxResult {
Expand Down Expand Up @@ -360,10 +412,25 @@ impl AddrSpace {
false
}

/// Returns (fd, offset, shared, popoulate, virtaddr_start)
pub fn get_file_metadata(&mut self, vaddr: VirtAddr) -> Option<(i32, usize, bool, bool, VirtAddr)> {
if !self.va_range.contains(vaddr) {
return None;
}
if let Some(area) = self.areas.find(vaddr) {
match area.backend() {
Backend::File { fd, offset, shared, populate }
=> return Some((*fd, *offset, *shared, *populate, area.start())),
_ => return None,
}
}
None
}

/// Handles a page fault at the given address.
///
/// `access_flags` indicates the access type that caused the page fault.
///
///
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line.

/// Returns `true` if the page fault is handled successfully (not a real
/// fault).
pub fn handle_page_fault(&mut self, vaddr: VirtAddr, access_flags: MappingFlags) -> bool {
Expand Down
8 changes: 8 additions & 0 deletions modules/axmm/src/backend/file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use super::Backend;

impl Backend {
/// Creates a new allocation mapping backend.
pub const fn new_file(fd: i32, offset: usize, populate: bool, shared: bool) -> Self {
Self::File { fd, offset, shared, populate}
}
}
13 changes: 12 additions & 1 deletion modules/axmm/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use memory_set::MappingBackend;

mod alloc;
mod linear;
mod file;

/// A unified enum type for different memory mapping backends.
///
Expand Down Expand Up @@ -36,6 +37,13 @@ pub enum Backend {
/// Whether to populate the physical frames when creating the mapping.
populate: bool,
},
/// File mapping backend.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't suggest to add a File Backend here, because Linear(linear mapping) and Alloc(dynamic mapping) are self-consistent enough to complete memory allocation related tasks, we do not want the module axmm in charge of memory to introduce file-related content.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A possible solution is to check whether there is a file mapping interval covering the missing address in the handle_page_fault part of starry(see here) after completing the physical page allocation for the missing page. If so, check whether the content of the file needs to be written to the newly allocated physical page.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A possible solution is to check whether there is a file mapping interval covering the missing address in the handle_page_fault part of starry(see here) after completing the physical page allocation for the missing page. If so, check whether the content of the file needs to be written to the newly allocated physical page.

If we don't create a mapping from MemoryArea to file in axmm, we need to maintain this mapping in starry. Will this cost be too much? My idea is to create a vm_area_struct like Linux and maintain the mapping to the file and offset in MemoryArea. When we get vma during handle_page_fault, we can directly get this mapping. But this will introduce the file of starry in axmm. Do you have any good suggestions?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A possible solution is to check whether there is a file mapping interval covering the missing address in the handle_page_fault part of starry(see here) after completing the physical page allocation for the missing page. If so, check whether the content of the file needs to be written to the newly allocated physical page.

If we don't create a mapping from MemoryArea to file in axmm, we need to maintain this mapping in starry. Will this cost be too much? My idea is to create a vm_area_struct like Linux and maintain the mapping to the file and offset in MemoryArea. When we get vma during handle_page_fault, we can directly get this mapping. But this will introduce the file of starry in axmm. Do you have any good suggestions?

One method we recommend is to maintain the mapping relationship between mmap area and file in ProcessData. For each process, it will consist of a batch of linear intervals, and there is no overlap between the intervals. Therefore, each time you query the file mapping relationship of the mmap area corresponding to a certain virtual address, you only need to traverse it linearly once. Its complexity is similar to find area

File {
fd: i32,
offset: usize,
shared: bool,
populate: bool,
},
}

impl MappingBackend for Backend {
Expand All @@ -46,13 +54,15 @@ impl MappingBackend for Backend {
match *self {
Self::Linear { pa_va_offset } => Self::map_linear(start, size, flags, pt, pa_va_offset),
Self::Alloc { populate } => Self::map_alloc(start, size, flags, pt, populate),
Self::File { .. } => true,
}
}

fn unmap(&self, start: VirtAddr, size: usize, pt: &mut PageTable) -> bool {
match *self {
Self::Linear { pa_va_offset } => Self::unmap_linear(start, size, pt, pa_va_offset),
Self::Alloc { populate } => Self::unmap_alloc(start, size, pt, populate),
Self::File { .. } => true,
}
}

Expand Down Expand Up @@ -81,7 +91,8 @@ impl Backend {
Self::Linear { .. } => false, // Linear mappings should not trigger page faults.
Self::Alloc { populate } => {
Self::handle_page_fault_alloc(vaddr, orig_flags, page_table, populate)
}
},
Self::File { .. } => false,
}
}
}
Loading