Skip to content

Commit a4a4658

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 a4a4658

File tree

4 files changed

+68
-78
lines changed

4 files changed

+68
-78
lines changed

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: 64 additions & 70 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,87 @@ 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 cow_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)) => {
588+
// Copy data from old memory area to new memory area.
589+
match self.pt.query(vaddr) {
590+
Ok((paddr, _, page_size)) => {
591+
#[cfg(not(feature = "cow"))]
592+
{
593+
let new_addr = match new_aspace.pt.query(vaddr) {
594+
Ok((paddr, _, _)) => paddr,
595+
// If the page is not mapped, try map it.
596+
Err(PagingError::NotMapped) => {
597+
if !area.backend().handle_page_fault(
598+
vaddr,
599+
area.flags(),
600+
&mut new_aspace.pt,
601+
) {
602+
return Err(AxError::NoMemory);
603+
}
604+
match new_aspace.pt.query(vaddr) {
605+
Ok((paddr, _, _)) => paddr,
606+
Err(_) => return Err(AxError::BadAddress),
607+
}
608+
}
609+
Err(_) => return Err(AxError::BadAddress),
610+
};
611+
unsafe {
612+
core::ptr::copy_nonoverlapping(
613+
phys_to_virt(paddr).as_ptr(),
614+
phys_to_virt(new_addr).as_mut_ptr(),
615+
page_size.into(),
616+
)
617+
};
618+
}
619+
620+
//If the page is mapped in the old page table:
621+
// - Update its permissions in the old page table using `flags`.
622+
// - Map the same physical page into the new page table at the same
623+
// virtual address, with the same page size and `flags`.
624+
#[cfg(feature = "cow")]
625+
{
602626
frame_table().inc_ref(paddr);
603627

604628
self.pt
605-
.protect(vaddr, flags)
629+
.protect(vaddr, cow_flags)
606630
.map(|(_, tlb)| tlb.flush())
607631
.expect("protect failed");
608632
new_aspace
609633
.pt
610-
.map(vaddr, paddr, page_size, flags)
634+
.map(vaddr, paddr, page_size, cow_flags)
611635
.map(|tlb| tlb.flush())
612636
.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-
}
619637

620-
// 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-
}
638+
continue;
640639
}
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-
}
640+
}
641+
// If the page is not mapped, skip it.
642+
Err(PagingError::NotMapped) => continue,
643+
Err(_) => return Err(AxError::BadAddress),
644+
};
651645
}
652646
}
653647
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)