Skip to content
This repository was archived by the owner on Nov 26, 2025. It is now read-only.

Commit bdd0534

Browse files
committed
refactor: simplify COW handling and frame table initialization
- Consolidate COW fault handling logic - Replace LazyInit with lazy_static for frame table - Remove redundant frame table initialization - Clean up memory area copying logic
1 parent e9a3c03 commit bdd0534

4 files changed

Lines changed: 73 additions & 87 deletions

File tree

modules/axmm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ axhal = { workspace = true, features = ["paging"] }
1818
axalloc = { workspace = true }
1919
axconfig = { workspace = true }
2020

21+
lazy_static = { version = "1.5", features = ["spin_no_std"] }
2122
log = "=0.4.21"
2223
axerrno = "0.1"
2324
lazyinit = "0.2"

modules/axmm/src/aspace.rs

Lines changed: 69 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -506,20 +506,19 @@ impl AddrSpace {
506506
// - shared pages (If there is a shared page in the vma)
507507
// - cow
508508
#[cfg(feature = "cow")]
509-
if let Ok((paddr, _, page_size)) = self.pt.query(vaddr) {
510-
if !access_flags.contains(MappingFlags::WRITE) {
511-
return false;
509+
if access_flags.contains(MappingFlags::WRITE) {
510+
if let Ok((paddr, _, page_size)) = self.pt.query(vaddr) {
511+
// 1. page fault caused by write
512+
// 2. pte exists
513+
// 3. Not shared memory
514+
return Self::handle_cow_fault(
515+
vaddr,
516+
paddr,
517+
orig_flags,
518+
page_size,
519+
&mut self.pt,
520+
);
512521
}
513-
// 1. page fault caused by write
514-
// 2. pte exists
515-
// 3. Not shared memory
516-
return Self::handle_cow_fault(
517-
vaddr,
518-
paddr,
519-
orig_flags,
520-
page_size,
521-
&mut self.pt,
522-
);
523522
}
524523

525524
return area
@@ -562,92 +561,83 @@ impl AddrSpace {
562561
Backend::Alloc { populate: _, align } => {
563562
// Forcing `populate = false` is to prevent the subsequent `new_aspace.areas.map`
564563
// from mapping page table entries for the virtual addresses.
565-
&Backend::new_alloc(false, *align)
564+
Backend::new_alloc(false, *align)
566565
}
567-
other => other,
566+
other => other.clone(),
568567
};
569568

570569
// Remap the memory area in the new address space.
571-
let new_area =
572-
MemoryArea::new(area.start(), area.size(), area.flags(), backend.clone());
570+
let new_area = MemoryArea::new(area.start(), area.size(), area.flags(), backend);
573571
new_aspace
574572
.areas
575573
.map(new_area, &mut new_aspace.pt, false)
576574
.map_err(mapping_err_to_ax_err)?;
577575

578-
let align = match *backend {
579-
Backend::Alloc { align, .. } => align,
576+
let align = match area.backend() {
577+
Backend::Alloc { align, .. } => *align,
580578
// Linear-backed regions are usually allocated by the kernel and are shared
581579
Backend::Linear { .. } => continue,
582580
};
583581

584582
#[cfg(feature = "cow")]
585-
let flags = {
586-
let mut f = area.flags();
587-
f.remove(MappingFlags::WRITE);
588-
f
589-
};
583+
let flags = area.flags().clone() - MappingFlags::WRITE;
590584

591585
for vaddr in PageIterWrapper::new(area.start(), area.end(), align)
592586
.expect("Failed to create page iterator")
593587
{
594-
//If the page is mapped in the old page table:
595-
// - Update its permissions in the old page table using `flags`.
596-
// - Map the same physical page into the new page table at the same
597-
// virtual address, with the same page size and `flags`.
598-
#[cfg(feature = "cow")]
599-
{
600-
match self.pt.query(vaddr) {
601-
Ok((paddr, _, page_size)) => {
602-
frame_table().inc_ref(paddr);
603-
604-
self.pt
605-
.protect(vaddr, flags)
606-
.map(|(_, tlb)| tlb.flush())
607-
.expect("protect failed");
608-
new_aspace
609-
.pt
610-
.map(vaddr, paddr, page_size, flags)
611-
.map(|tlb| tlb.flush())
612-
.expect("map failed");
613-
}
614-
// If the page is not mapped, skip it.
615-
Err(PagingError::NotMapped) => continue,
616-
Err(_) => return Err(AxError::BadAddress),
617-
}
618-
}
619-
620588
// Copy data from old memory area to new memory area.
621-
#[cfg(not(feature = "cow"))]
622-
{
623-
let addr = match self.pt.query(vaddr) {
624-
Ok((paddr, _, _)) => paddr,
625-
// If the page is not mapped, skip it.
626-
Err(PagingError::NotMapped) => continue,
627-
Err(_) => return Err(AxError::BadAddress),
628-
};
629-
let new_addr = match new_aspace.pt.query(vaddr) {
630-
Ok((paddr, _, _)) => paddr,
631-
// If the page is not mapped, try map it.
632-
Err(PagingError::NotMapped) => {
633-
if !backend.handle_page_fault(vaddr, area.flags(), &mut new_aspace.pt) {
634-
return Err(AxError::NoMemory);
635-
}
636-
match new_aspace.pt.query(vaddr) {
637-
Ok((paddr, _, _)) => paddr,
638-
Err(_) => return Err(AxError::BadAddress),
639-
}
589+
let addr = match self.pt.query(vaddr) {
590+
#[cfg(not(feature = "cow"))]
591+
Ok((paddr, _, _)) => paddr,
592+
#[cfg(feature = "cow")]
593+
Ok((paddr, _, page_size)) => {
594+
//If the page is mapped in the old page table:
595+
// - Update its permissions in the old page table using `flags`.
596+
// - Map the same physical page into the new page table at the same
597+
// virtual address, with the same page size and `flags`.
598+
frame_table().inc_ref(paddr);
599+
600+
self.pt
601+
.protect(vaddr, flags)
602+
.map(|(_, tlb)| tlb.flush())
603+
.expect("protect failed");
604+
new_aspace
605+
.pt
606+
.map(vaddr, paddr, page_size, flags)
607+
.map(|tlb| tlb.flush())
608+
.expect("map failed");
609+
610+
continue;
611+
}
612+
// If the page is not mapped, skip it.
613+
Err(PagingError::NotMapped) => continue,
614+
Err(_) => return Err(AxError::BadAddress),
615+
};
616+
let new_addr = match new_aspace.pt.query(vaddr) {
617+
Ok((paddr, _, _)) => paddr,
618+
// If the page is not mapped, try map it.
619+
Err(PagingError::NotMapped) => {
620+
if !area.backend().handle_page_fault(
621+
vaddr,
622+
area.flags(),
623+
&mut new_aspace.pt,
624+
) {
625+
return Err(AxError::NoMemory);
640626
}
641-
Err(_) => return Err(AxError::BadAddress),
642-
};
643-
unsafe {
644-
core::ptr::copy_nonoverlapping(
645-
phys_to_virt(addr).as_ptr(),
646-
phys_to_virt(new_addr).as_mut_ptr(),
647-
PAGE_SIZE_4K,
648-
)
649-
};
650-
}
627+
match new_aspace.pt.query(vaddr) {
628+
Ok((paddr, _, _)) => paddr,
629+
Err(_) => return Err(AxError::BadAddress),
630+
}
631+
}
632+
Err(_) => return Err(AxError::BadAddress),
633+
};
634+
unsafe {
635+
core::ptr::copy_nonoverlapping(
636+
phys_to_virt(addr).as_ptr(),
637+
phys_to_virt(new_addr).as_mut_ptr(),
638+
PAGE_SIZE_4K,
639+
)
640+
};
651641
}
652642
}
653643
Ok(new_aspace)

modules/axmm/src/frameinfo.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,16 @@ use core::{
1313
};
1414

1515
use alloc::boxed::Box;
16+
use lazy_static::lazy_static;
1617
use lazyinit::LazyInit;
1718
use memory_addr::PhysAddr;
18-
1919
// 4 kb page
2020
const FRAME_SHIFT: usize = 12;
2121

2222
pub const MAX_FRAME_NUM: usize = axconfig::plat::PHYS_MEMORY_SIZE >> FRAME_SHIFT;
2323

24-
static FRAME_INFO_TABLE: LazyInit<FrameRefTable> = LazyInit::new();
25-
26-
pub fn init_frames() {
27-
let _ = FRAME_INFO_TABLE.init_once(FrameRefTable::default());
24+
lazy_static! {
25+
static ref FRAME_INFO_TABLE: FrameRefTable = FrameRefTable::default();
2826
}
2927

3028
pub(crate) fn frame_table() -> &'static FrameRefTable {

modules/axmm/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,6 @@ pub fn init_memory_management() {
7272
debug!("kernel address space init OK: {:#x?}", kernel_aspace);
7373
KERNEL_ASPACE.init_once(SpinNoIrq::new(kernel_aspace));
7474
axhal::paging::set_kernel_page_table_root(kernel_page_table_root());
75-
76-
#[cfg(feature = "cow")]
77-
frameinfo::init_frames();
7875
}
7976

8077
/// Initializes kernel paging for secondary CPUs.

0 commit comments

Comments
 (0)