From 05220ef673eff51daeeead27f9ff7dde8a5d042c Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sat, 18 Oct 2025 15:13:43 +0000 Subject: [PATCH 01/16] =?UTF-8?q?chore(arch-mm):=20mm=E4=B8=AD=E4=B8=8E?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=9E=B6=E6=9E=84=E7=9B=B8=E5=85=B3=E9=83=A8?= =?UTF-8?q?=E5=88=86=E7=9A=84=E5=9F=BA=E6=9C=AC=E6=96=87=E4=BB=B6=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/loongarch/mm/.gitkeep | 0 os/src/arch/riscv/mm/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 os/src/arch/loongarch/mm/.gitkeep create mode 100644 os/src/arch/riscv/mm/.gitkeep diff --git a/os/src/arch/loongarch/mm/.gitkeep b/os/src/arch/loongarch/mm/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/os/src/arch/riscv/mm/.gitkeep b/os/src/arch/riscv/mm/.gitkeep new file mode 100644 index 00000000..e69de29b From 5cc5b53fa6b3ea403c0ecc6550c936610f31423e Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sat, 18 Oct 2025 15:27:31 +0000 Subject: [PATCH 02/16] refactor(mm): rename allocation to frame_allocator --- os/src/mm/{allocation => frame_allocator}/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename os/src/mm/{allocation => frame_allocator}/.gitkeep (100%) diff --git a/os/src/mm/allocation/.gitkeep b/os/src/mm/frame_allocator/.gitkeep similarity index 100% rename from os/src/mm/allocation/.gitkeep rename to os/src/mm/frame_allocator/.gitkeep From 18f63711dd2698de3cfd0f4ab12b3eb03dde6f82 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 02:24:10 +0000 Subject: [PATCH 03/16] =?UTF-8?q?feat(arch-mm):=20=E5=AE=9E=E7=8E=B0arch?= =?UTF-8?q?=20specific=E7=9A=84=E6=AD=A3=E7=A1=AE=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/loongarch/mm/{.gitkeep => mod.rs} | 0 os/src/arch/loongarch/mod.rs | 1 + os/src/arch/mod.rs | 8 ++++++++ os/src/arch/riscv/mm/{.gitkeep => mod.rs} | 0 os/src/arch/riscv/mod.rs | 1 + os/src/main.rs | 1 + os/src/mm/frame_allocator/.gitkeep | 0 7 files changed, 11 insertions(+) rename os/src/arch/loongarch/mm/{.gitkeep => mod.rs} (100%) create mode 100644 os/src/arch/loongarch/mod.rs create mode 100644 os/src/arch/mod.rs rename os/src/arch/riscv/mm/{.gitkeep => mod.rs} (100%) create mode 100644 os/src/arch/riscv/mod.rs delete mode 100644 os/src/mm/frame_allocator/.gitkeep diff --git a/os/src/arch/loongarch/mm/.gitkeep b/os/src/arch/loongarch/mm/mod.rs similarity index 100% rename from os/src/arch/loongarch/mm/.gitkeep rename to os/src/arch/loongarch/mm/mod.rs diff --git a/os/src/arch/loongarch/mod.rs b/os/src/arch/loongarch/mod.rs new file mode 100644 index 00000000..81492b31 --- /dev/null +++ b/os/src/arch/loongarch/mod.rs @@ -0,0 +1 @@ +mod mm; \ No newline at end of file diff --git a/os/src/arch/mod.rs b/os/src/arch/mod.rs new file mode 100644 index 00000000..c8de4a8f --- /dev/null +++ b/os/src/arch/mod.rs @@ -0,0 +1,8 @@ +mod loongarch; +mod riscv; + +#[cfg(target_arch = "loongarch64")] +pub use self::loongarch::mm; + +#[cfg(target_arch = "riscv64")] +pub use self::riscv::mm; \ No newline at end of file diff --git a/os/src/arch/riscv/mm/.gitkeep b/os/src/arch/riscv/mm/mod.rs similarity index 100% rename from os/src/arch/riscv/mm/.gitkeep rename to os/src/arch/riscv/mm/mod.rs diff --git a/os/src/arch/riscv/mod.rs b/os/src/arch/riscv/mod.rs new file mode 100644 index 00000000..6d106477 --- /dev/null +++ b/os/src/arch/riscv/mod.rs @@ -0,0 +1 @@ +pub mod mm; diff --git a/os/src/main.rs b/os/src/main.rs index d0568ac8..aa701848 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -9,6 +9,7 @@ mod console; mod sbi; mod config; mod mm; +mod arch; use core::arch::global_asm; use core::panic::PanicInfo; diff --git a/os/src/mm/frame_allocator/.gitkeep b/os/src/mm/frame_allocator/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 2a33f5ff085e7d374a970debadd27bb5a4af2559 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 02:34:23 +0000 Subject: [PATCH 04/16] =?UTF-8?q?feat(arch-mm):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E5=9F=BA=E4=BA=8ESV39=E7=9A=84=E5=9C=B0=E5=9D=80=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/riscv/mm/mod.rs | 20 ++++++++++++++++++++ os/src/mm/address/address.rs | 35 +++++++++++++++++++++++++++++++---- os/src/mm/address/mod.rs | 4 +++- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/os/src/arch/riscv/mm/mod.rs b/os/src/arch/riscv/mm/mod.rs index e69de29b..379e9434 100644 --- a/os/src/arch/riscv/mm/mod.rs +++ b/os/src/arch/riscv/mm/mod.rs @@ -0,0 +1,20 @@ +// TODO: Complete the comments below +//! MemoryManagement module for RISC-V architecture +//! +//! This module provides RISC-V specific implementations for memory management, +//! using SV39 paging scheme. + +pub const VADDR_START: usize = 0xffff_ffc0_0000_0000; +pub const PADDR_MASK: usize = 0x0000_3fff_ffff_ffff; + +// MUST implemented in any arch-specific mm module +/// Convert virtual address to physical address +pub const fn vaddr_to_paddr(vaddr: usize) -> usize { + vaddr & PADDR_MASK +} + +// MUST implemented in any arch-specific mm module +/// Convert physical address to virtual address +pub const fn paddr_to_vaddr(paddr: usize) -> usize { + paddr | VADDR_START +} \ No newline at end of file diff --git a/os/src/mm/address/address.rs b/os/src/mm/address/address.rs index f39cab15..091b7088 100644 --- a/os/src/mm/address/address.rs +++ b/os/src/mm/address/address.rs @@ -110,18 +110,48 @@ macro_rules! impl_address { }; } +pub trait ConvertablePaddr { + fn is_valid_paddr(&self) -> bool; + fn to_vaddr(&self) -> Vaddr; +} + /// physical address #[repr(transparent)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Paddr(*const ()); impl_address!(Paddr); +impl ConvertablePaddr for Paddr { + fn is_valid_paddr(&self) -> bool { + self.as_usize() == crate::arch::mm::vaddr_to_paddr(self.as_usize()) + } + + fn to_vaddr(&self) -> Vaddr { + Vaddr::from_usize(crate::arch::mm::paddr_to_vaddr(self.as_usize())) + } +} + +pub trait ConvertableVaddr { + fn is_valid_vaddr(&self) -> bool; + fn to_paddr(&self) -> Paddr; +} + /// virtual address #[repr(transparent)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Vaddr(*const ()); impl_address!(Vaddr); +impl ConvertableVaddr for Vaddr { + fn is_valid_vaddr(&self) -> bool { + self.as_usize() == crate::arch::mm::paddr_to_vaddr(self.as_usize()) + } + + fn to_paddr(&self) -> Paddr { + Paddr::from_usize(crate::arch::mm::vaddr_to_paddr(self.as_usize())) + } +} + impl Vaddr { /// create a virtual address from a reference pub fn from_ref(r: &T) -> Self { @@ -177,10 +207,7 @@ where { /// create a new address range pub fn new(start: T, end: T) -> Self { - Self { - start, - end, - } + Self { start, end } } /// create an address range from a Range diff --git a/os/src/mm/address/mod.rs b/os/src/mm/address/mod.rs index a22d77a9..cef5c963 100644 --- a/os/src/mm/address/mod.rs +++ b/os/src/mm/address/mod.rs @@ -26,6 +26,8 @@ mod address; mod operations; mod page_num; -pub use address::{Address, AddressRange, Paddr, PaddrRange, Vaddr, VaddrRange}; +pub use address::{ + Address, AddressRange, ConvertablePaddr, ConvertableVaddr, Paddr, PaddrRange, Vaddr, VaddrRange, +}; pub use operations::{AlignOps, CalcOps, UsizeConvert}; pub use page_num::{PageNum, Ppn, Vpn}; From 342ea4c9d3261c7a16e581d2b00d858dab996343 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 22:15:11 +0800 Subject: [PATCH 05/16] =?UTF-8?q?feat(mm):=20=E6=B7=BB=E5=8A=A0=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E5=88=86=E9=85=8D=E5=99=A8=E7=9A=84=E5=8D=A0=E4=BD=8D?= =?UTF-8?q?=E7=AC=A6=EF=BC=8C=E4=BB=A5=E4=BE=BF=E4=BD=BF=E7=94=A8=20alloc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/main.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/os/src/main.rs b/os/src/main.rs index aa701848..7f0769f2 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -4,6 +4,27 @@ #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] +extern crate alloc; + +use core::alloc::{GlobalAlloc, Layout}; + +/// TODO: replace with proper heap allocator +/// Dummy allocator that always fails - placeholder until heap allocator is implemented +struct DummyAllocator; + +unsafe impl GlobalAlloc for DummyAllocator { + unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { + core::ptr::null_mut() + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { + panic!("dealloc called on DummyAllocator"); + } +} + +#[global_allocator] +static ALLOCATOR: DummyAllocator = DummyAllocator; + #[macro_use] mod console; mod sbi; From b967213a59fcee8a367120dc2fd7929565c801ec Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 22:16:03 +0800 Subject: [PATCH 06/16] =?UTF-8?q?feat(mm):=20=E4=B8=BA=20PageNumRange=20?= =?UTF-8?q?=E8=A1=A5=E5=85=85start=20=E5=92=8C=20end=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/address/mod.rs | 5 +++-- os/src/mm/address/page_num.rs | 11 +++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/os/src/mm/address/mod.rs b/os/src/mm/address/mod.rs index cef5c963..cb917459 100644 --- a/os/src/mm/address/mod.rs +++ b/os/src/mm/address/mod.rs @@ -27,7 +27,8 @@ mod operations; mod page_num; pub use address::{ - Address, AddressRange, ConvertablePaddr, ConvertableVaddr, Paddr, PaddrRange, Vaddr, VaddrRange, + Address, AddressRange, AddressRangeIterator, ConvertablePaddr, ConvertableVaddr, Paddr, + PaddrRange, Vaddr, VaddrRange, }; pub use operations::{AlignOps, CalcOps, UsizeConvert}; -pub use page_num::{PageNum, Ppn, Vpn}; +pub use page_num::{PageNum, PageNumRange, PageNumRangeIterator, Ppn, PpnRange, Vpn, VpnRange}; diff --git a/os/src/mm/address/page_num.rs b/os/src/mm/address/page_num.rs index ca30cc67..c6474d84 100644 --- a/os/src/mm/address/page_num.rs +++ b/os/src/mm/address/page_num.rs @@ -125,6 +125,14 @@ where } } + pub fn start(&self) -> T { + self.start + } + + pub fn end(&self) -> T { + self.end + } + /// get the length of the range pub fn len(&self) -> usize { debug_assert!(self.end.as_usize() >= self.start.as_usize()); @@ -196,3 +204,6 @@ where Some(result) } } + +pub type PpnRange = PageNumRange; +pub type VpnRange = PageNumRange; \ No newline at end of file From 850984a2f0416d430b9371fdf0fadf9f889b7ce6 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 14:18:38 +0000 Subject: [PATCH 07/16] =?UTF-8?q?docs(mm):=20=E4=B8=BA=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20API=20=E8=A1=A5=E4=B8=8A=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/address/page_num.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/os/src/mm/address/page_num.rs b/os/src/mm/address/page_num.rs index c6474d84..f095e629 100644 --- a/os/src/mm/address/page_num.rs +++ b/os/src/mm/address/page_num.rs @@ -125,10 +125,12 @@ where } } + /// get the start page number pub fn start(&self) -> T { self.start } + /// get the end page number pub fn end(&self) -> T { self.end } From e9c60c292f6547c297024c7fb88bed617aa24cec Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 14:21:09 +0000 Subject: [PATCH 08/16] =?UTF-8?q?feat(mm):=20=E5=AE=9E=E7=8E=B0=E5=B8=A7?= =?UTF-8?q?=E5=88=86=E9=85=8D=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/frame_allocator/frame_allocator.rs | 277 +++++++++++++++++++ os/src/mm/frame_allocator/mod.rs | 7 + os/src/mm/mod.rs | 3 +- 3 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 os/src/mm/frame_allocator/frame_allocator.rs create mode 100644 os/src/mm/frame_allocator/mod.rs diff --git a/os/src/mm/frame_allocator/frame_allocator.rs b/os/src/mm/frame_allocator/frame_allocator.rs new file mode 100644 index 00000000..9101fc65 --- /dev/null +++ b/os/src/mm/frame_allocator/frame_allocator.rs @@ -0,0 +1,277 @@ +use core::ptr::{addr_of_mut, addr_of}; +use core::usize; + +use crate::config::PAGE_SIZE; +use crate::mm::address::{ConvertablePaddr, Paddr, PageNum, Ppn, PpnRange, UsizeConvert}; +use alloc::vec::Vec; + +pub struct FrameTracker(Ppn); + +impl FrameTracker { + pub fn new(ppn: Ppn) -> Self { + clear_frame(ppn); + FrameTracker(ppn) + } + + pub fn ppn(&self) -> Ppn { + self.0 + } +} + +fn clear_frame(ppn: Ppn) { + unsafe { + let va = ppn.start_addr().to_vaddr().as_mut_ptr::(); + core::ptr::write_bytes(va, 0, PAGE_SIZE); + } +} + +impl Drop for FrameTracker { + fn drop(&mut self) { + dealloc_frame(self); + } +} + +pub struct FrameRangeTracker { + range: PpnRange, +} + +impl FrameRangeTracker { + pub fn new(range: PpnRange) -> Self { + for ppn in range.clone() { + clear_frame(ppn); + } + FrameRangeTracker { range } + } + + pub fn start_ppn(&self) -> Ppn { + self.range.start() + } + + pub fn end_ppn(&self) -> Ppn { + self.range.end() + } + + pub fn len(&self) -> usize { + self.range.len() + } + + pub fn range(&self) -> &PpnRange { + &self.range + } +} + +impl Drop for FrameRangeTracker { + fn drop(&mut self) { + dealloc_contig_frames(self); + } +} + +/// TODO: replace with proper synchronization primitive +/// +/// global frame allocator instance +/// +/// use static mut in single-core environment without multitasking +static mut FRAME_ALLOCATOR: Option = None; + +struct FrameAllocator { + start: Ppn, + end: Ppn, + cur: Ppn, + /// recycled frames stack + recycled: Vec, +} + +// TODO: implement FrameAllocator +/// lazy frame allocator +impl FrameAllocator { + pub fn new() -> Self { + FrameAllocator { + start: Ppn::from_usize(usize::MAX), + end: Ppn::from_usize(usize::MAX), + cur: Ppn::from_usize(usize::MAX), + recycled: Vec::new(), + } + } + + pub fn init(&mut self, start: Ppn, end: Ppn) { + self.start = start; + self.end = end; + self.cur = start; + } + + pub fn alloc_frame(&mut self) -> Option { + if let Some(ppn) = self.recycled.pop() { + Some(FrameTracker::new(ppn)) + } else if self.cur < self.end { + let ppn = self.cur; + self.cur.step(); + Some(FrameTracker::new(ppn)) + } else { + None + } + } + + pub fn alloc_frames(&mut self, num: usize) -> Option> { + let mut frames = Vec::with_capacity(num); + for _ in 0..num { + if let Some(frame) = self.alloc_frame() { + frames.push(frame); + } else { + // 分配失败,需要将已分配的帧回收 + // 由于 FrameTracker 实现了 Drop,这里直接 drop frames 即可 + return None; + } + } + Some(frames) + } + + pub fn alloc_contig_frames(&mut self, num: usize) -> Option { + if num == 0 { + return None; + } + + // 检查是否有足够的连续帧 + let required_end = self.cur + num; + if required_end <= self.end { + let start = self.cur; + self.cur = required_end; + let range = PpnRange::from_start_len(start, num); + Some(FrameRangeTracker::new(range)) + } else { + None + } + } + + pub fn dealloc_frame(&mut self, frame: &FrameTracker) { + // is valid + debug_assert!( + frame.ppn() >= self.start && frame.ppn() < self.end, + "dealloc_frame: frame out of range" + ); + // is allocated + debug_assert!( + frame.ppn() < self.cur && self.recycled.iter().all(|&ppn| ppn != frame.ppn()), + ); + + let ppn = frame.ppn(); + self.recycled.push(ppn); + self.recycled.sort_unstable(); + + if let Some(&last) = self.recycled.last() { + // 回收栈顶部的帧是当前分配指针前面的连续帧 + if last + 1 == self.cur { + // 回收连续帧 + let mut new_cur = last; + self.recycled.pop(); + while let Some(&top) = self.recycled.last() { + if top + 1 == new_cur { + new_cur = top; + self.recycled.pop(); + } else { + break; + } + } + self.cur = new_cur; + } + } + } + + pub fn dealloc_contig_frames(&mut self, frame_range: &FrameRangeTracker) { + let start = frame_range.start_ppn(); + let end = frame_range.end_ppn(); + // is valid + debug_assert!( + start >= self.start && end <= self.end, + "dealloc_contig_frames: frame range out of range" + ); + // is allocated + debug_assert!( + end < self.cur, + "dealloc_contig_frames: frame range not allocated" + ); + + for ppn in frame_range.range().into_iter() { + self.recycled.push(ppn); + } + self.recycled.sort_unstable(); + + if let Some(&last) = self.recycled.last() { + // 回收栈顶部的帧是当前分配指针前面的连续帧 + if last + 1 == self.cur { + // 回收连续帧 + let mut new_cur = last; + self.recycled.pop(); + while let Some(&top) = self.recycled.last() { + if top + 1 == new_cur { + new_cur = top; + self.recycled.pop(); + } else { + break; + } + } + self.cur = new_cur; + } + } + } +} + +/// TODO: replace with proper synchronization primitive +/// +/// initialize the global frame allocator while booting +pub fn init_frame_allocator(start_addr: usize, end_addr: usize) { + let start_ppn = Ppn::from_addr_ceil(Paddr::from_usize(start_addr)); + let end_ppn = Ppn::from_addr_floor(Paddr::from_usize(end_addr)); + + unsafe { + let allocator_ptr = addr_of_mut!(FRAME_ALLOCATOR); + if (*allocator_ptr).is_none() { + let mut allocator = FrameAllocator::new(); + allocator.init(start_ppn, end_ppn); + *allocator_ptr = Some(allocator); + } + } +} + +/// allocate a single frame +pub fn alloc_frame() -> Option { + unsafe { (*addr_of_mut!(FRAME_ALLOCATOR)).as_mut()?.alloc_frame() } +} + +/// allocate multiple frames (may not be contiguous) +pub fn alloc_frames(num: usize) -> Option> { + unsafe { (*addr_of_mut!(FRAME_ALLOCATOR)).as_mut()?.alloc_frames(num) } +} + +/// allocate contiguous frames +pub fn alloc_contig_frames(num: usize) -> Option { + unsafe { (*addr_of_mut!(FRAME_ALLOCATOR)).as_mut()?.alloc_contig_frames(num) } +} + +/// deallocate a single frame +fn dealloc_frame(frame: &FrameTracker) { + unsafe { + if let Some(allocator) = (*addr_of_mut!(FRAME_ALLOCATOR)).as_mut() { + allocator.dealloc_frame(frame); + } + } +} + +/// deallocate multiple frames (may not be contiguous) +fn dealloc_frames(frames: &[FrameTracker]) { + unsafe { + if let Some(allocator) = (*addr_of_mut!(FRAME_ALLOCATOR)).as_mut() { + for frame in frames { + allocator.dealloc_frame(frame); + } + } + } +} + +/// deallocate contiguous frames +fn dealloc_contig_frames(frame_range: &FrameRangeTracker) { + unsafe { + if let Some(allocator) = (*addr_of_mut!(FRAME_ALLOCATOR)).as_mut() { + allocator.dealloc_contig_frames(frame_range); + } + } +} diff --git a/os/src/mm/frame_allocator/mod.rs b/os/src/mm/frame_allocator/mod.rs new file mode 100644 index 00000000..35ccc10e --- /dev/null +++ b/os/src/mm/frame_allocator/mod.rs @@ -0,0 +1,7 @@ +mod frame_allocator; + +pub use frame_allocator::{FrameRangeTracker, FrameTracker}; + +pub fn init_frame_allocator(start_addr: usize, end_addr: usize) { + frame_allocator::init_frame_allocator(start_addr, end_addr); +} \ No newline at end of file diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 0fda4d55..3c88202c 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -1 +1,2 @@ -mod address; \ No newline at end of file +mod address; +mod frame_allocator; \ No newline at end of file From 3f25f314687d35accb02e6d813c5365ab2163386 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 14:22:34 +0000 Subject: [PATCH 09/16] =?UTF-8?q?style(mm):=20=E5=AF=B9=20frame=5Fallocato?= =?UTF-8?q?r.rs=20=E4=BD=BF=E7=94=A8=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/frame_allocator/frame_allocator.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/os/src/mm/frame_allocator/frame_allocator.rs b/os/src/mm/frame_allocator/frame_allocator.rs index 9101fc65..3a6386ba 100644 --- a/os/src/mm/frame_allocator/frame_allocator.rs +++ b/os/src/mm/frame_allocator/frame_allocator.rs @@ -1,4 +1,4 @@ -use core::ptr::{addr_of_mut, addr_of}; +use core::ptr::{addr_of, addr_of_mut}; use core::usize; use crate::config::PAGE_SIZE; @@ -244,7 +244,11 @@ pub fn alloc_frames(num: usize) -> Option> { /// allocate contiguous frames pub fn alloc_contig_frames(num: usize) -> Option { - unsafe { (*addr_of_mut!(FRAME_ALLOCATOR)).as_mut()?.alloc_contig_frames(num) } + unsafe { + (*addr_of_mut!(FRAME_ALLOCATOR)) + .as_mut()? + .alloc_contig_frames(num) + } } /// deallocate a single frame From 63e0373dfdf7e88a2b4a16280151eb9c7b478b2e Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 22:27:22 +0800 Subject: [PATCH 10/16] =?UTF-8?q?docs(arch-mm):=20=E4=B8=BA=20riscv=20?= =?UTF-8?q?=E8=A1=A5=E4=B8=8A=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/riscv/mm/mod.rs | 60 ++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/os/src/arch/riscv/mm/mod.rs b/os/src/arch/riscv/mm/mod.rs index 379e9434..aaee83f8 100644 --- a/os/src/arch/riscv/mm/mod.rs +++ b/os/src/arch/riscv/mm/mod.rs @@ -1,20 +1,64 @@ -// TODO: Complete the comments below -//! MemoryManagement module for RISC-V architecture -//! +//! RISC-V architecture memory management module +//! //! This module provides RISC-V specific implementations for memory management, -//! using SV39 paging scheme. +//! using the SV39 paging scheme. +//! +//! # SV39 Paging Scheme +//! +//! SV39 is a 39-bit virtual address paging scheme for RISC-V: +//! - Virtual address: 39 effective bits (bits 38-63 must match bit 38) +//! - Physical address: 56 bits (bits 0-55) +//! - Page size: 4 KiB +//! +//! # Address Translation +//! +//! This module uses direct mapping for address translation: +//! - Virtual address start: `0xffff_ffc0_0000_0000` +//! - Physical addresses are extracted using bitwise AND with `PADDR_MASK` +//! - Virtual addresses are created using bitwise OR with `VADDR_START` +/// starting address of the virtual address space in SV39 +/// +/// This constant defines the starting position of the kernel's high virtual address space. +/// In the SV39 paging scheme, this is a valid higher-half kernel address. pub const VADDR_START: usize = 0xffff_ffc0_0000_0000; + +/// physical address mask for extracting physical address from virtual address +/// +/// This mask preserves the lower 38 bits (bits 0-37), which corresponds to +/// the physical address space size in SV39. pub const PADDR_MASK: usize = 0x0000_3fff_ffff_ffff; -// MUST implemented in any arch-specific mm module -/// Convert virtual address to physical address +/// convert virtual address to physical address +/// +/// # Parameters +/// +/// * `vaddr` - virtual address +/// +/// # Returns +/// +/// The corresponding physical address +/// +/// # Note +/// +/// This function must be implemented in all architecture-specific mm modules. pub const fn vaddr_to_paddr(vaddr: usize) -> usize { vaddr & PADDR_MASK } -// MUST implemented in any arch-specific mm module -/// Convert physical address to virtual address +/// convert physical address to virtual address +/// +/// # Parameters +/// +/// * `paddr` - physical address +/// +/// # Returns +/// +/// The corresponding virtual address +/// +/// # Note +/// +/// This function must be implemented in all architecture-specific mm modules. pub const fn paddr_to_vaddr(paddr: usize) -> usize { paddr | VADDR_START } \ No newline at end of file From 45aa5a4db921d8311b106efe9dd8bb9e612d46ac Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 22:27:51 +0800 Subject: [PATCH 11/16] =?UTF-8?q?docs(arch-mm):=20=E4=B8=BA=20loongarch=20?= =?UTF-8?q?=E8=A1=A5=E4=B8=8A=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/loongarch/mm/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/os/src/arch/loongarch/mm/mod.rs b/os/src/arch/loongarch/mm/mod.rs index e69de29b..f74541b1 100644 --- a/os/src/arch/loongarch/mm/mod.rs +++ b/os/src/arch/loongarch/mm/mod.rs @@ -0,0 +1,11 @@ +//! LoongArch architecture memory management module +//! +//! This module provides LoongArch specific implementations for memory management. +//! +//! # TODO +//! +//! - [ ] define virtual address space start constant for LoongArch +//! - [ ] define physical address mask constant for LoongArch +//! - [ ] implement `vaddr_to_paddr` function +//! - [ ] implement `paddr_to_vaddr` function +//! - [ ] refine address translation logic based on LoongArch paging scheme From 281fb0867ac7bd69b38ee84377089d9b28d94f63 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 22:32:00 +0800 Subject: [PATCH 12/16] =?UTF-8?q?docs(mm):=20=E4=B8=BA=20address=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E8=A1=A5=E4=B8=8A=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/address/address.rs | 6 ++++++ os/src/mm/address/mod.rs | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/os/src/mm/address/address.rs b/os/src/mm/address/address.rs index 091b7088..f0bab1a2 100644 --- a/os/src/mm/address/address.rs +++ b/os/src/mm/address/address.rs @@ -110,8 +110,11 @@ macro_rules! impl_address { }; } +/// trait for converting physical addresses to virtual addresses pub trait ConvertablePaddr { + /// check if the address is a valid physical address fn is_valid_paddr(&self) -> bool; + /// convert physical address to virtual address fn to_vaddr(&self) -> Vaddr; } @@ -131,8 +134,11 @@ impl ConvertablePaddr for Paddr { } } +/// trait for converting virtual addresses to physical addresses pub trait ConvertableVaddr { + /// check if the address is a valid virtual address fn is_valid_vaddr(&self) -> bool; + /// convert virtual address to physical address fn to_paddr(&self) -> Paddr; } diff --git a/os/src/mm/address/mod.rs b/os/src/mm/address/mod.rs index cb917459..81771945 100644 --- a/os/src/mm/address/mod.rs +++ b/os/src/mm/address/mod.rs @@ -3,16 +3,33 @@ //! This module provides abstractions for working with physical and virtual addresses, //! as well as page numbers in a memory management system. //! -//! # Components +//! # Address Types //! //! - [`Address`]: Trait for representing memory addresses (physical or virtual) //! - [`Paddr`]: Physical address type //! - [`Vaddr`]: Virtual address type +//! - [`ConvertablePaddr`]: Trait for converting physical addresses to virtual addresses +//! - [`ConvertableVaddr`]: Trait for converting virtual addresses to physical addresses +//! +//! # Address Ranges +//! //! - [`AddressRange`]: Generic range of addresses +//! - [`PaddrRange`]: Type alias for physical address range +//! - [`VaddrRange`]: Type alias for virtual address range +//! - [`AddressRangeIterator`]: Iterator for address ranges +//! +//! # Page Numbers +//! //! - [`PageNum`]: Trait for representing page numbers //! - [`Ppn`]: Physical page number //! - [`Vpn`]: Virtual page number +//! +//! # Page Number Ranges +//! //! - [`PageNumRange`]: Generic range of page numbers +//! - [`PpnRange`]: Type alias for physical page number range +//! - [`VpnRange`]: Type alias for virtual page number range +//! - [`PageNumRangeIterator`]: Iterator for page number ranges //! //! # Operations //! From f5124a546721bf24465a2e9c711bcfc7ef9cd3a6 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 22:32:26 +0800 Subject: [PATCH 13/16] =?UTF-8?q?docs(mm):=20=E4=B8=BA=20frame=5Fallocator?= =?UTF-8?q?=20=E6=A8=A1=E5=9D=97=E8=A1=A5=E4=B8=8A=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/frame_allocator/mod.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/os/src/mm/frame_allocator/mod.rs b/os/src/mm/frame_allocator/mod.rs index 35ccc10e..80264337 100644 --- a/os/src/mm/frame_allocator/mod.rs +++ b/os/src/mm/frame_allocator/mod.rs @@ -1,7 +1,23 @@ +//! Frame allocator module +//! +//! This module provides physical memory frame allocation and tracking functionality. +//! +//! # Components +//! +//! - [`FrameTracker`]: RAII wrapper for single allocated frames +//! - [`FrameRangeTracker`]: RAII wrapper for ranges of allocated frames +//! - [`init_frame_allocator`]: Initialize the global frame allocator + mod frame_allocator; pub use frame_allocator::{FrameRangeTracker, FrameTracker}; +/// initialize the global frame allocator with the available physical memory range +/// +/// # Parameters +/// +/// * `start_addr` - start address of the available physical memory +/// * `end_addr` - end address of the available physical memory pub fn init_frame_allocator(start_addr: usize, end_addr: usize) { frame_allocator::init_frame_allocator(start_addr, end_addr); } \ No newline at end of file From 79309726ba643326240fc4c3d9fac193432ad43e Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 22:32:47 +0800 Subject: [PATCH 14/16] =?UTF-8?q?docs(mm):=20=E4=B8=BA=20mm=20=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E8=A1=A5=E4=B8=8A=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 3c88202c..8f2f29ea 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -1,2 +1,12 @@ +//! Memory management module +//! +//! This module provides architecture-independent memory management abstractions +//! and implementations for the kernel. +//! +//! # Components +//! +//! - [`address`]: Address and page number abstractions +//! - [`frame_allocator`]: Physical frame allocation + mod address; mod frame_allocator; \ No newline at end of file From c289de81696d3e3ed622e03bff10efe94e57ef20 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 14:44:49 +0000 Subject: [PATCH 15/16] =?UTF-8?q?docs(mm):=20=E7=A7=BB=E9=99=A4=E5=B7=B2?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=9A=84=20TODO=20=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/frame_allocator/frame_allocator.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/os/src/mm/frame_allocator/frame_allocator.rs b/os/src/mm/frame_allocator/frame_allocator.rs index 3a6386ba..3334eae4 100644 --- a/os/src/mm/frame_allocator/frame_allocator.rs +++ b/os/src/mm/frame_allocator/frame_allocator.rs @@ -81,7 +81,6 @@ struct FrameAllocator { recycled: Vec, } -// TODO: implement FrameAllocator /// lazy frame allocator impl FrameAllocator { pub fn new() -> Self { From bff71c1c2af609313572d902116b8659854a2fa0 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 19 Oct 2025 15:05:09 +0000 Subject: [PATCH 16/16] =?UTF-8?q?feat(mm):=20=E4=BF=AE=E6=94=B9=20frame=5F?= =?UTF-8?q?allocator=20=E6=A8=A1=E5=9D=97=E7=9A=84=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/frame_allocator/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/os/src/mm/frame_allocator/mod.rs b/os/src/mm/frame_allocator/mod.rs index 80264337..8e46a180 100644 --- a/os/src/mm/frame_allocator/mod.rs +++ b/os/src/mm/frame_allocator/mod.rs @@ -7,10 +7,13 @@ //! - [`FrameTracker`]: RAII wrapper for single allocated frames //! - [`FrameRangeTracker`]: RAII wrapper for ranges of allocated frames //! - [`init_frame_allocator`]: Initialize the global frame allocator +//! - [`alloc_frame`]: Allocate a single frame +//! - [`alloc_frames`]: Allocate multiple (non-contiguous) frames +//! - [`alloc_contig_frames`]: Allocate multiple contiguous frames mod frame_allocator; -pub use frame_allocator::{FrameRangeTracker, FrameTracker}; +pub use frame_allocator::{FrameRangeTracker, FrameTracker, alloc_frame, alloc_frames, alloc_contig_frames}; /// initialize the global frame allocator with the available physical memory range ///