From ff25a007a586404648cf6b9e381cc0e8283f79c8 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Mon, 20 Oct 2025 05:35:57 +0000 Subject: [PATCH 01/10] refactor(mm): rename pagetable/ to page_table/ --- os/src/mm/{pagetable/.gitkeep => page_table/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename os/src/mm/{pagetable/.gitkeep => page_table/mod.rs} (100%) diff --git a/os/src/mm/pagetable/.gitkeep b/os/src/mm/page_table/mod.rs similarity index 100% rename from os/src/mm/pagetable/.gitkeep rename to os/src/mm/page_table/mod.rs From 5f099755858ad0254b206b75b7a9c3efafe6bdd5 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Tue, 21 Oct 2025 12:37:52 +0800 Subject: [PATCH 02/10] =?UTF-8?q?feat(mm):=20=E5=88=9B=E5=BB=BA=E9=A1=B5?= =?UTF-8?q?=E8=A1=A8=E5=92=8C=E9=A1=B5=E8=A1=A8=E9=A1=B9=20trait?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/riscv/mm/mod.rs | 6 ++++++ os/src/arch/riscv/mm/page_table.rs | 5 +++++ os/src/arch/riscv/mm/page_table_entry.rs | 5 +++++ os/src/main.rs | 4 ++-- os/src/mm/mod.rs | 4 +++- os/src/mm/page_table/mod.rs | 6 ++++++ os/src/mm/page_table/page_table.rs | 3 +++ os/src/mm/page_table/page_table_entry.rs | 5 +++++ 8 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 os/src/arch/riscv/mm/page_table.rs create mode 100644 os/src/arch/riscv/mm/page_table_entry.rs create mode 100644 os/src/mm/page_table/page_table.rs create mode 100644 os/src/mm/page_table/page_table_entry.rs diff --git a/os/src/arch/riscv/mm/mod.rs b/os/src/arch/riscv/mm/mod.rs index aaee83f8..562b9903 100644 --- a/os/src/arch/riscv/mm/mod.rs +++ b/os/src/arch/riscv/mm/mod.rs @@ -17,6 +17,12 @@ //! - Physical addresses are extracted using bitwise AND with `PADDR_MASK` //! - Virtual addresses are created using bitwise OR with `VADDR_START` +mod page_table; +mod page_table_entry; + +pub use page_table::PageTable; +pub use page_table_entry::PageTableEntry; + /// starting address of the virtual address space in SV39 /// /// This constant defines the starting position of the kernel's high virtual address space. diff --git a/os/src/arch/riscv/mm/page_table.rs b/os/src/arch/riscv/mm/page_table.rs new file mode 100644 index 00000000..67c21e0a --- /dev/null +++ b/os/src/arch/riscv/mm/page_table.rs @@ -0,0 +1,5 @@ +use crate::mm::page_table::PageTable as PageTableTrait; + +pub struct PageTable { + +} \ No newline at end of file diff --git a/os/src/arch/riscv/mm/page_table_entry.rs b/os/src/arch/riscv/mm/page_table_entry.rs new file mode 100644 index 00000000..36f24e82 --- /dev/null +++ b/os/src/arch/riscv/mm/page_table_entry.rs @@ -0,0 +1,5 @@ +use crate::mm::page_table::PageTableEntry as PageTableEntryTrait; + +pub struct PageTableEntry { + +} \ No newline at end of file diff --git a/os/src/main.rs b/os/src/main.rs index 3ec6e173..464b2ee2 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -10,8 +10,8 @@ extern crate alloc; mod console; mod sbi; mod config; -mod mm; -mod arch; +pub mod mm; +pub mod arch; mod sync; use core::arch::global_asm; diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 68f43816..8904ef9b 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -8,10 +8,12 @@ //! - [`address`]: Address and page number abstractions //! - [`frame_allocator`]: Physical frame allocation //! - [`global_allocator`]: Global heap allocator +//! - [`page_table`]: Page table abstractions and implementations(arch-independent) mod address; mod frame_allocator; mod global_allocator; +pub mod page_table; pub use frame_allocator::init_frame_allocator; -pub use global_allocator::init_heap; \ No newline at end of file +pub use global_allocator::init_heap; diff --git a/os/src/mm/page_table/mod.rs b/os/src/mm/page_table/mod.rs index e69de29b..56d29e37 100644 --- a/os/src/mm/page_table/mod.rs +++ b/os/src/mm/page_table/mod.rs @@ -0,0 +1,6 @@ +mod page_table; +mod page_table_entry; + +pub use page_table::PageTable; +pub use page_table_entry::PageTableEntry; + diff --git a/os/src/mm/page_table/page_table.rs b/os/src/mm/page_table/page_table.rs new file mode 100644 index 00000000..a3c99385 --- /dev/null +++ b/os/src/mm/page_table/page_table.rs @@ -0,0 +1,3 @@ +pub trait PageTable { + +} \ No newline at end of file diff --git a/os/src/mm/page_table/page_table_entry.rs b/os/src/mm/page_table/page_table_entry.rs new file mode 100644 index 00000000..dcc30504 --- /dev/null +++ b/os/src/mm/page_table/page_table_entry.rs @@ -0,0 +1,5 @@ +use crate::mm::address::Paddr; + +pub trait PageTableEntry { + +} From e843400576a69d5b8678b9f5f0fc2c08a28f336d Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Tue, 21 Oct 2025 04:40:30 +0000 Subject: [PATCH 03/10] =?UTF-8?q?feat(mm):=20=E5=88=9B=E5=BB=BA=20Universa?= =?UTF-8?q?lPTEFlag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/Cargo.lock | 7 +++++++ os/Cargo.toml | 1 + os/src/mm/page_table/page_table_entry.rs | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/os/Cargo.lock b/os/Cargo.lock index 866197f2..4a33af91 100644 --- a/os/Cargo.lock +++ b/os/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "critical-section" version = "1.2.0" @@ -27,6 +33,7 @@ dependencies = [ name = "os" version = "0.1.0" dependencies = [ + "bitflags", "lock_api", "riscv", "sbi-rt", diff --git a/os/Cargo.toml b/os/Cargo.toml index da6b057b..c95d43ef 100644 --- a/os/Cargo.toml +++ b/os/Cargo.toml @@ -8,3 +8,4 @@ sbi-rt = { version = "0.0.2", features = ["legacy"] } riscv = "0.15.0" talc = { version = "4" } lock_api = "0.4" +bitflags = {version = "1.2.1"} diff --git a/os/src/mm/page_table/page_table_entry.rs b/os/src/mm/page_table/page_table_entry.rs index dcc30504..29ba5bd2 100644 --- a/os/src/mm/page_table/page_table_entry.rs +++ b/os/src/mm/page_table/page_table_entry.rs @@ -1,5 +1,25 @@ use crate::mm::address::Paddr; +bitflags::bitflags! { + /// Designs a universal set of page table entry flags that can be mapped to various architectures. + /// Be same to Risc-V SV39 for templarity.(add more flag-bit if needed for other archs) + pub struct UniversalPTEFlag: usize { + const Valid = 1 << 0; // Indicates whether the entry is valid + const Readable = 1 << 1; // Indicates whether the page is readable + const Writeable = 1 << 2; // Indicates whether the page is writeable + const Executable = 1 << 3; // Indicates whether the page is executable + const UserAccessible = 1 << 4; // Indicates whether the page is accessible from user mode + const Global = 1 << 5; // Indicates whether the page is global + const Accessed = 1 << 6; // Indicates whether the page has been accessed + const Dirty = 1 << 7; // Indicates whether the page has been written to + } +} + +pub trait UniversalConvertableFlag { + fn from_universal(flag: UniversalPTEFlag) -> Self; + fn to_universal(&self) -> UniversalPTEFlag; +} + pub trait PageTableEntry { } From 2823613efbed87e6d08d544fb48df77553fa774b Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Tue, 21 Oct 2025 04:41:24 +0000 Subject: [PATCH 04/10] =?UTF-8?q?feat(mm):=20=E5=AE=9A=E4=B9=89=20PTE=20tr?= =?UTF-8?q?ait=20=E6=89=80=E9=9C=80=E7=9A=84=E6=8E=A5=E5=8F=A3=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/page_table/page_table_entry.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/os/src/mm/page_table/page_table_entry.rs b/os/src/mm/page_table/page_table_entry.rs index 29ba5bd2..073b7f1b 100644 --- a/os/src/mm/page_table/page_table_entry.rs +++ b/os/src/mm/page_table/page_table_entry.rs @@ -21,5 +21,24 @@ pub trait UniversalConvertableFlag { } pub trait PageTableEntry { + type Bits; + fn from_bits(bits: Self::Bits) -> Self; + fn to_bits(&self) -> Self::Bits; + fn empty() -> Self; + fn new_leaf(paddr: Paddr, flags: UniversalPTEFlag) -> Self; + fn new_table(paddr: Paddr) -> Self; + + fn is_valid(&self) -> bool; + fn is_huge(&self) -> bool; + fn is_empty(&self) -> bool; + + fn paddr(&self) -> Paddr; + fn flags(&self) -> UniversalPTEFlag; + + fn set_paddr(&mut self, paddr: Paddr); + fn set_flags(&mut self, flags: UniversalPTEFlag); + fn clear(&mut self); + fn remove_flags(&mut self, flags: UniversalPTEFlag); + fn add_flags(&mut self, flags: UniversalPTEFlag); } From a3df55b2e3c1fbe5b623ca3d85113ab5dca0151d Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Tue, 21 Oct 2025 18:21:22 +0000 Subject: [PATCH 05/10] =?UTF-8?q?feat(mm):=20=E5=88=9B=E5=BB=BA=20PageTabl?= =?UTF-8?q?eInner=20trait?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/riscv/mm/mod.rs | 2 +- os/src/arch/riscv/mm/page_table.rs | 8 ++- os/src/mm/page_table/mod.rs | 32 +++++++++++- os/src/mm/page_table/page_table.rs | 81 +++++++++++++++++++++++++++++- 4 files changed, 116 insertions(+), 7 deletions(-) diff --git a/os/src/arch/riscv/mm/mod.rs b/os/src/arch/riscv/mm/mod.rs index 562b9903..fd23b6c7 100644 --- a/os/src/arch/riscv/mm/mod.rs +++ b/os/src/arch/riscv/mm/mod.rs @@ -20,7 +20,7 @@ mod page_table; mod page_table_entry; -pub use page_table::PageTable; +pub use page_table::PageTableInner; pub use page_table_entry::PageTableEntry; /// starting address of the virtual address space in SV39 diff --git a/os/src/arch/riscv/mm/page_table.rs b/os/src/arch/riscv/mm/page_table.rs index 67c21e0a..c8471dab 100644 --- a/os/src/arch/riscv/mm/page_table.rs +++ b/os/src/arch/riscv/mm/page_table.rs @@ -1,5 +1,9 @@ -use crate::mm::page_table::PageTable as PageTableTrait; +use crate::mm::page_table::PageTableInner as PageTableInnerTrait; -pub struct PageTable { +pub struct PageTableInner { + +} + +impl PageTableInnerTrait for PageTableInner { } \ No newline at end of file diff --git a/os/src/mm/page_table/mod.rs b/os/src/mm/page_table/mod.rs index 56d29e37..09fb59c5 100644 --- a/os/src/mm/page_table/mod.rs +++ b/os/src/mm/page_table/mod.rs @@ -1,6 +1,34 @@ mod page_table; mod page_table_entry; -pub use page_table::PageTable; -pub use page_table_entry::PageTableEntry; +pub use page_table::*; +pub use page_table_entry::*; + +pub type ActivePageTableInner = crate::arch::mm::PageTableInner; + +/// Supported page sizes +pub enum PageSize { + Size4K = 0x1000, + Size2M = 0x20_0000, + Size1G = 0x4000_0000, + // ban bigger sizes for now +} + +/// Errors that can occur during paging operations +pub enum PagingError { + /// The virtual address is not mapped + NotMapped, + /// The virtual address is already mapped + AlreadyMapped, + /// Invalid address provided + InvalidAddress, + /// The operation failed due to a conflict with an existing huge page mapping. + HugePageConflict, + /// Invalid Flags provided + InvalidFlags, + /// Failed to alloc frame + FrameAllocFailed, +} + +pub type PageResult = Result; diff --git a/os/src/mm/page_table/page_table.rs b/os/src/mm/page_table/page_table.rs index a3c99385..ae2f7751 100644 --- a/os/src/mm/page_table/page_table.rs +++ b/os/src/mm/page_table/page_table.rs @@ -1,3 +1,80 @@ -pub trait PageTable { +use super::{ActivePageTableInner, PageResult, PageSize, PageTableEntry, UniversalPTEFlag}; +use crate::mm::address::{Paddr, PaddrRange, Vaddr, VaddrRange}; -} \ No newline at end of file +pub trait PageTableInner +where + T: PageTableEntry, +{ + const LEVELS: usize; + const MAX_VA_BITS: usize; + const MAX_PA_BITS: usize; + + fn tlb_flush(vaddr: Vaddr); + fn tlb_flush_range(start_vaddr: Vaddr, size: usize); + fn tlb_flush_all(); + + fn is_user_table() -> bool; + + fn activate(paddr: Paddr); + fn activating_table_paddr() -> Paddr; + + fn new() -> Self; + fn from_paddr(paddr: Paddr) -> Self; + fn new_as_kernel_table() -> Self; + + fn root_paddr(&self) -> Paddr; + + fn get_entry(&self, vaddr: Vaddr, level: usize) -> Option<(T, PageSize)>; + + fn translate(&self, vaddr: Vaddr) -> Option; + + fn map( + &mut self, + vaddr: Vaddr, + paddr: Paddr, + page_size: PageSize, + flags: UniversalPTEFlag, + ) -> PageResult<()>; + + fn unmap(&mut self, vaddr: Vaddr) -> PageResult<(Paddr, PageSize)>; + + fn mvmap( + &mut self, + vaddr: Vaddr, + target_paddr: Paddr, + page_size: PageSize, + flags: UniversalPTEFlag, + ) -> PageResult<(Paddr, PageSize)>; + + fn update_flags(&mut self, vaddr: Vaddr, flags: UniversalPTEFlag) -> PageResult<()>; + + fn map_range( + &mut self, + vaddr_range: VaddrRange, + paddr_range: PaddrRange, + flags: UniversalPTEFlag, + ) -> PageResult<()>; + + fn unmap_range(&mut self, vaddr_range: VaddrRange) -> PageResult; + + fn mvmap_range( + &mut self, + vaddr_range: VaddrRange, + target_paddr_range: PaddrRange, + flags: UniversalPTEFlag, + ) -> PageResult; + + fn update_flags_range( + &mut self, + vaddr_range: VaddrRange, + flags: UniversalPTEFlag, + ) -> PageResult<()>; + + fn walk(&self, vaddr: Vaddr) -> PageResult<(Paddr, PageSize, UniversalPTEFlag)>; +} + +pub struct PageTable { + inner: ActivePageTableInner, + // TODO: + tracker: (), +} From 3802381616ae579392d5eed44705465bfe1e05b0 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Tue, 21 Oct 2025 19:33:41 +0000 Subject: [PATCH 06/10] =?UTF-8?q?feat(mm):=20=E5=AE=9E=E7=8E=B0=E5=9F=BA?= =?UTF-8?q?=E4=BA=8ESV39=E7=9A=84PTE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/riscv/mm/page_table_entry.rs | 128 ++++++++++++++++++++++- os/src/mm/mod.rs | 2 +- os/src/mm/page_table/page_table.rs | 4 +- os/src/mm/page_table/page_table_entry.rs | 15 ++- 4 files changed, 141 insertions(+), 8 deletions(-) diff --git a/os/src/arch/riscv/mm/page_table_entry.rs b/os/src/arch/riscv/mm/page_table_entry.rs index 36f24e82..017519d3 100644 --- a/os/src/arch/riscv/mm/page_table_entry.rs +++ b/os/src/arch/riscv/mm/page_table_entry.rs @@ -1,5 +1,129 @@ +use crate::mm::address::{Paddr, UsizeConvert}; use crate::mm::page_table::PageTableEntry as PageTableEntryTrait; +use crate::mm::page_table::{UniversalConvertableFlag, UniversalPTEFlag}; -pub struct PageTableEntry { +bitflags::bitflags! { + pub struct SV39PTEFlags: usize { + const VALID = 1 << 0; // Indicates whether the entry is valid + const READ = 1 << 1; // Indicates whether the page is readable + const WRITE = 1 << 2; // Indicates whether the page is writeable + const EXECUTE = 1 << 3; // Indicates whether the page is executable + const USER = 1 << 4; // Indicates whether the page is accessible from user mode + const GLOBAL = 1 << 5; // Indicates whether the page is global + const ACCESSED = 1 << 6; // Indicates whether the page has been accessed + const DIRTY = 1 << 7; // Indicates whether the page has been written to + const _RESERVED = 1 << 8; // Reserved for future use (according to SV39 spec) + } +} -} \ No newline at end of file + + +/* + * SV39 Page Table Entry (PTE) format: + * ------------------------------------------------ + * | Bits | Description | + * ------------------------------------------------ + * | 0-7 | Flags (Valid, Read, Write, Execute, | + * | | User, Global, Accessed, Dirty) | + * ------------------------------------------------ + * | 8-9 | Reserved (must be zero) | + * ------------------------------------------------ + * | 10-53 | Physical Page Number (PPN) | + * ------------------------------------------------ + * | 54-63 | Reserved (must be zero) | + * ------------------------------------------------ + */ + +const SV39_PTE_FLAG_MASK: usize = 0xff; // Lower 8 bits for SV39 PTE flags +const SV39_PTE_PPN_OFFSET: usize = 10; // PPN starts from bit 10 +const SV39_PTE_PPN_MASK: u64 = 0x000f_ffff_ffff_c00; // Bits 10-53 for PPN + +impl UniversalConvertableFlag for SV39PTEFlags { + fn from_universal(flag: UniversalPTEFlag) -> Self { + Self::from_bits(flag.bits() & SV39_PTE_FLAG_MASK).unwrap() + } + + fn to_universal(&self) -> UniversalPTEFlag { + UniversalPTEFlag::from_bits(self.bits() & SV39_PTE_FLAG_MASK).unwrap() + } +} + +pub struct PageTableEntry(u64); + +impl PageTableEntryTrait for PageTableEntry { + type Bits = u64; + + fn from_bits(bits: Self::Bits) -> Self { + PageTableEntry(bits) + } + + fn to_bits(&self) -> Self::Bits { + self.0 + } + + fn empty() -> Self { + PageTableEntry(0) + } + + fn new_leaf(paddr: Paddr, flags: UniversalPTEFlag) -> Self { + let ppn: u64 = ((paddr.as_usize() as u64) >> 12) & 0x000f_ffff_ffff; // Extract PPN from physical address + let sv39_flags = SV39PTEFlags::from_universal(flags); + PageTableEntry((ppn << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64)) + } + + fn new_table(paddr: Paddr) -> Self { + let ppn: u64 = ((paddr.as_usize() as u64) >> 12) & 0x000f_ffff_ffff; // Extract PPN from physical address + let sv39_flags = SV39PTEFlags::VALID; // Table entries must be valid + PageTableEntry((ppn << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64)) + } + + fn is_valid(&self) -> bool { + (self.0 & SV39PTEFlags::VALID.bits() as u64) != 0 + } + + fn is_huge(&self) -> bool { + // In SV39, we can't directly determine huge pages from the PTE alone. + let sv39_flags = SV39PTEFlags::from_bits((self.0 & SV39_PTE_FLAG_MASK as u64) as usize).unwrap(); + sv39_flags.intersects(SV39PTEFlags::union(SV39PTEFlags::READ, SV39PTEFlags::EXECUTE)) + } + + fn is_empty(&self) -> bool { + self.0 == 0 + } + + fn paddr(&self) -> Paddr { + let ppn = (self.0 & SV39_PTE_PPN_MASK) >> SV39_PTE_PPN_OFFSET; + Paddr::from_usize((ppn << 12) as usize) + } + + fn flags(&self) -> UniversalPTEFlag { + let sv39_flags = SV39PTEFlags::from_bits((self.0 & SV39_PTE_FLAG_MASK as u64) as usize).unwrap(); + sv39_flags.to_universal() + } + + fn set_paddr(&mut self, paddr: Paddr) { + let ppn = ((paddr.as_usize() as u64) >> 12) & 0x000f_ffff_ffff; + self.0 = (self.0 & !SV39_PTE_PPN_MASK) | (ppn << SV39_PTE_PPN_OFFSET); + } + + fn set_flags(&mut self, flags: UniversalPTEFlag) { + let sv39_flags = SV39PTEFlags::from_universal(flags); + self.0 = (self.0 & !(SV39_PTE_FLAG_MASK as u64)) | (sv39_flags.bits() as u64); + } + + fn clear(&mut self) { + self.0 = 0; + } + + // current_flags & !flags + fn remove_flags(&mut self, flags: UniversalPTEFlag) { + let current_flags = self.flags(); + let new_flags = current_flags & !flags; + self.set_flags(new_flags); + } + + // current_flags | flags + fn add_flags(&mut self, flags: UniversalPTEFlag) { + self.set_flags(self.flags() | flags); + } +} diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 8904ef9b..2da2073f 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -10,7 +10,7 @@ //! - [`global_allocator`]: Global heap allocator //! - [`page_table`]: Page table abstractions and implementations(arch-independent) -mod address; +pub mod address; mod frame_allocator; mod global_allocator; pub mod page_table; diff --git a/os/src/mm/page_table/page_table.rs b/os/src/mm/page_table/page_table.rs index ae2f7751..f93347de 100644 --- a/os/src/mm/page_table/page_table.rs +++ b/os/src/mm/page_table/page_table.rs @@ -13,7 +13,7 @@ where fn tlb_flush_range(start_vaddr: Vaddr, size: usize); fn tlb_flush_all(); - fn is_user_table() -> bool; + fn is_user_table(&self) -> bool; fn activate(paddr: Paddr); fn activating_table_paddr() -> Paddr; @@ -75,6 +75,6 @@ where pub struct PageTable { inner: ActivePageTableInner, - // TODO: + // TODO: tracker: (), } diff --git a/os/src/mm/page_table/page_table_entry.rs b/os/src/mm/page_table/page_table_entry.rs index 073b7f1b..2b735103 100644 --- a/os/src/mm/page_table/page_table_entry.rs +++ b/os/src/mm/page_table/page_table_entry.rs @@ -2,8 +2,10 @@ use crate::mm::address::Paddr; bitflags::bitflags! { /// Designs a universal set of page table entry flags that can be mapped to various architectures. - /// Be same to Risc-V SV39 for templarity.(add more flag-bit if needed for other archs) + /// Be same to Risc-V SV39 in lower 8 bits.(add more flag-bit if needed for other archs) pub struct UniversalPTEFlag: usize { + + // ---- RISC-V SV39 compatible flags ---- const Valid = 1 << 0; // Indicates whether the entry is valid const Readable = 1 << 1; // Indicates whether the page is readable const Writeable = 1 << 2; // Indicates whether the page is writeable @@ -12,6 +14,9 @@ bitflags::bitflags! { const Global = 1 << 5; // Indicates whether the page is global const Accessed = 1 << 6; // Indicates whether the page has been accessed const Dirty = 1 << 7; // Indicates whether the page has been written to + + // ---- Additional universal flags ---- + const Huge = 1 << 8; // Indicates whether the page is a huge page () } } @@ -22,7 +27,7 @@ pub trait UniversalConvertableFlag { pub trait PageTableEntry { type Bits; - + fn from_bits(bits: Self::Bits) -> Self; fn to_bits(&self) -> Self::Bits; fn empty() -> Self; @@ -32,13 +37,17 @@ pub trait PageTableEntry { fn is_valid(&self) -> bool; fn is_huge(&self) -> bool; fn is_empty(&self) -> bool; - + fn paddr(&self) -> Paddr; fn flags(&self) -> UniversalPTEFlag; fn set_paddr(&mut self, paddr: Paddr); fn set_flags(&mut self, flags: UniversalPTEFlag); fn clear(&mut self); + + // current_flags & !flags fn remove_flags(&mut self, flags: UniversalPTEFlag); + + // current_flags | flags fn add_flags(&mut self, flags: UniversalPTEFlag); } From e9d9c23c3f4d4d8b025902a63b208978d983cbe5 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Tue, 21 Oct 2025 20:21:14 +0000 Subject: [PATCH 07/10] refactor: rename `PageError` to `PagingError` --- os/src/mm/page_table/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/os/src/mm/page_table/mod.rs b/os/src/mm/page_table/mod.rs index 09fb59c5..b8dcc5b4 100644 --- a/os/src/mm/page_table/mod.rs +++ b/os/src/mm/page_table/mod.rs @@ -30,5 +30,5 @@ pub enum PagingError { FrameAllocFailed, } -pub type PageResult = Result; +pub type PagingResult = Result; From 9eac8b5304e679fbd8d383be5fd7b04b0f0608ea Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Tue, 21 Oct 2025 20:22:29 +0000 Subject: [PATCH 08/10] =?UTF-8?q?refactor:=20=E5=B0=86=20=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=20=E6=9B=BF=E6=8D=A2=E4=B8=BA=20=E9=A1=B5=E5=8F=B7?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E6=8E=89=E8=BD=AC=E6=8D=A2=E5=BC=80?= =?UTF-8?q?=E9=94=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/riscv/mm/page_table_entry.rs | 24 +++++----- os/src/mm/page_table/page_table.rs | 56 ++++++++++++------------ os/src/mm/page_table/page_table_entry.rs | 12 ++--- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/os/src/arch/riscv/mm/page_table_entry.rs b/os/src/arch/riscv/mm/page_table_entry.rs index 017519d3..7f2767b6 100644 --- a/os/src/arch/riscv/mm/page_table_entry.rs +++ b/os/src/arch/riscv/mm/page_table_entry.rs @@ -1,4 +1,4 @@ -use crate::mm::address::{Paddr, UsizeConvert}; +use crate::mm::address::{Ppn, UsizeConvert}; use crate::mm::page_table::PageTableEntry as PageTableEntryTrait; use crate::mm::page_table::{UniversalConvertableFlag, UniversalPTEFlag}; @@ -65,16 +65,16 @@ impl PageTableEntryTrait for PageTableEntry { PageTableEntry(0) } - fn new_leaf(paddr: Paddr, flags: UniversalPTEFlag) -> Self { - let ppn: u64 = ((paddr.as_usize() as u64) >> 12) & 0x000f_ffff_ffff; // Extract PPN from physical address + fn new_leaf(ppn: Ppn, flags: UniversalPTEFlag) -> Self { + let ppn_bits: u64 = ppn.as_usize() as u64; let sv39_flags = SV39PTEFlags::from_universal(flags); - PageTableEntry((ppn << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64)) + PageTableEntry((ppn_bits << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64)) } - fn new_table(paddr: Paddr) -> Self { - let ppn: u64 = ((paddr.as_usize() as u64) >> 12) & 0x000f_ffff_ffff; // Extract PPN from physical address + fn new_table(ppn: Ppn) -> Self { + let ppn_bits: u64 = ppn.as_usize() as u64; let sv39_flags = SV39PTEFlags::VALID; // Table entries must be valid - PageTableEntry((ppn << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64)) + PageTableEntry((ppn_bits << SV39_PTE_PPN_OFFSET) | (sv39_flags.bits() as u64)) } fn is_valid(&self) -> bool { @@ -91,9 +91,9 @@ impl PageTableEntryTrait for PageTableEntry { self.0 == 0 } - fn paddr(&self) -> Paddr { + fn ppn(&self) -> Ppn { let ppn = (self.0 & SV39_PTE_PPN_MASK) >> SV39_PTE_PPN_OFFSET; - Paddr::from_usize((ppn << 12) as usize) + Ppn::from_usize(ppn as usize) } fn flags(&self) -> UniversalPTEFlag { @@ -101,9 +101,9 @@ impl PageTableEntryTrait for PageTableEntry { sv39_flags.to_universal() } - fn set_paddr(&mut self, paddr: Paddr) { - let ppn = ((paddr.as_usize() as u64) >> 12) & 0x000f_ffff_ffff; - self.0 = (self.0 & !SV39_PTE_PPN_MASK) | (ppn << SV39_PTE_PPN_OFFSET); + fn set_ppn(&mut self, ppn: Ppn) { + let ppn_bits = ppn.as_usize() as u64; + self.0 = (self.0 & !SV39_PTE_PPN_MASK) | (ppn_bits << SV39_PTE_PPN_OFFSET); } fn set_flags(&mut self, flags: UniversalPTEFlag) { diff --git a/os/src/mm/page_table/page_table.rs b/os/src/mm/page_table/page_table.rs index f93347de..7ca1ee7b 100644 --- a/os/src/mm/page_table/page_table.rs +++ b/os/src/mm/page_table/page_table.rs @@ -1,5 +1,5 @@ -use super::{ActivePageTableInner, PageResult, PageSize, PageTableEntry, UniversalPTEFlag}; -use crate::mm::address::{Paddr, PaddrRange, Vaddr, VaddrRange}; +use super::{ActivePageTableInner, PagingResult, PageSize, PageTableEntry, UniversalPTEFlag}; +use crate::mm::address::{Ppn, PpnRange, Vpn, VpnRange}; pub trait PageTableInner where @@ -9,68 +9,68 @@ where const MAX_VA_BITS: usize; const MAX_PA_BITS: usize; - fn tlb_flush(vaddr: Vaddr); - fn tlb_flush_range(start_vaddr: Vaddr, size: usize); + fn tlb_flush(vpn: Vpn); + fn tlb_flush_vpn_range(vpn_range: VpnRange) -> PagingResult<()>; fn tlb_flush_all(); fn is_user_table(&self) -> bool; - fn activate(paddr: Paddr); - fn activating_table_paddr() -> Paddr; + fn activate(ppn: Ppn); + fn activating_table_ppn() -> Ppn; fn new() -> Self; - fn from_paddr(paddr: Paddr) -> Self; + fn from_ppn(ppn: Ppn) -> Self; fn new_as_kernel_table() -> Self; - fn root_paddr(&self) -> Paddr; + fn root_ppn(&self) -> Ppn; - fn get_entry(&self, vaddr: Vaddr, level: usize) -> Option<(T, PageSize)>; + fn get_entry(&self, vpn: Vpn, level: usize) -> Option<(T, PageSize)>; - fn translate(&self, vaddr: Vaddr) -> Option; + fn translate(&self, vpn: Vpn) -> Option; fn map( &mut self, - vaddr: Vaddr, - paddr: Paddr, + vpn: Vpn, + ppn: Ppn, page_size: PageSize, flags: UniversalPTEFlag, - ) -> PageResult<()>; + ) -> PagingResult<()>; - fn unmap(&mut self, vaddr: Vaddr) -> PageResult<(Paddr, PageSize)>; + fn unmap(&mut self, vpn: Vpn) -> PagingResult<(Ppn, PageSize)>; fn mvmap( &mut self, - vaddr: Vaddr, - target_paddr: Paddr, + vpn: Vpn, + target_ppn: Ppn, page_size: PageSize, flags: UniversalPTEFlag, - ) -> PageResult<(Paddr, PageSize)>; + ) -> PagingResult<(Ppn, PageSize)>; - fn update_flags(&mut self, vaddr: Vaddr, flags: UniversalPTEFlag) -> PageResult<()>; + fn update_flags(&mut self, vpn: Vpn, flags: UniversalPTEFlag) -> PagingResult<()>; fn map_range( &mut self, - vaddr_range: VaddrRange, - paddr_range: PaddrRange, + vpn_range: VpnRange, + ppn_range: PpnRange, flags: UniversalPTEFlag, - ) -> PageResult<()>; + ) -> PagingResult<()>; - fn unmap_range(&mut self, vaddr_range: VaddrRange) -> PageResult; + fn unmap_range(&mut self, vpn_range: VpnRange) -> PagingResult; fn mvmap_range( &mut self, - vaddr_range: VaddrRange, - target_paddr_range: PaddrRange, + vpn_range: VpnRange, + target_ppn_range: PpnRange, flags: UniversalPTEFlag, - ) -> PageResult; + ) -> PagingResult; fn update_flags_range( &mut self, - vaddr_range: VaddrRange, + vpn_range: VpnRange, flags: UniversalPTEFlag, - ) -> PageResult<()>; + ) -> PagingResult<()>; - fn walk(&self, vaddr: Vaddr) -> PageResult<(Paddr, PageSize, UniversalPTEFlag)>; + fn walk(&self, vpn: Vpn) -> PagingResult<(Ppn, PageSize, UniversalPTEFlag)>; } pub struct PageTable { diff --git a/os/src/mm/page_table/page_table_entry.rs b/os/src/mm/page_table/page_table_entry.rs index 2b735103..39e6be7e 100644 --- a/os/src/mm/page_table/page_table_entry.rs +++ b/os/src/mm/page_table/page_table_entry.rs @@ -1,4 +1,4 @@ -use crate::mm::address::Paddr; +use crate::mm::address::Ppn; bitflags::bitflags! { /// Designs a universal set of page table entry flags that can be mapped to various architectures. @@ -27,21 +27,21 @@ pub trait UniversalConvertableFlag { pub trait PageTableEntry { type Bits; - + fn from_bits(bits: Self::Bits) -> Self; fn to_bits(&self) -> Self::Bits; fn empty() -> Self; - fn new_leaf(paddr: Paddr, flags: UniversalPTEFlag) -> Self; - fn new_table(paddr: Paddr) -> Self; + fn new_leaf(ppn: Ppn, flags: UniversalPTEFlag) -> Self; + fn new_table(ppn: Ppn) -> Self; fn is_valid(&self) -> bool; fn is_huge(&self) -> bool; fn is_empty(&self) -> bool; - fn paddr(&self) -> Paddr; + fn ppn(&self) -> Ppn; fn flags(&self) -> UniversalPTEFlag; - fn set_paddr(&mut self, paddr: Paddr); + fn set_ppn(&mut self, ppn: Ppn); fn set_flags(&mut self, flags: UniversalPTEFlag); fn clear(&mut self); From 6fed3d3d5f14504c2601cd9c915309d729d0756d Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Wed, 22 Oct 2025 08:59:29 +0000 Subject: [PATCH 09/10] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=9F=BA?= =?UTF-8?q?=E4=BA=8ESV39=E7=9A=84PageTableInner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/arch/riscv/mm/page_table.rs | 343 ++++++++++++++++++++++- os/src/arch/riscv/mm/page_table_entry.rs | 3 +- os/src/mm/mod.rs | 4 +- os/src/mm/page_table/page_table.rs | 33 +-- 4 files changed, 348 insertions(+), 35 deletions(-) diff --git a/os/src/arch/riscv/mm/page_table.rs b/os/src/arch/riscv/mm/page_table.rs index c8471dab..447d3a48 100644 --- a/os/src/arch/riscv/mm/page_table.rs +++ b/os/src/arch/riscv/mm/page_table.rs @@ -1,9 +1,344 @@ -use crate::mm::page_table::PageTableInner as PageTableInnerTrait; +use super::PageTableEntry; +use crate::mm::address::{AlignOps, PageNum, Ppn, PpnRange, UsizeConvert, Vaddr, Vpn, VpnRange, Paddr, ConvertablePaddr}; +use crate::mm::frame_allocator::FrameTracker; +use crate::mm::page_table::{ + PageSize, PageTableInner as PageTableInnerTrait, PagingError, PagingResult, UniversalPTEFlag, PageTableEntry as PageTableEntryTrait +}; +use alloc::vec::Vec; pub struct PageTableInner { - + root: Ppn, + // only store middle-level frames here + frames: Vec, + is_user: bool, } impl PageTableInnerTrait for PageTableInner { - -} \ No newline at end of file + const LEVELS: usize = 3; + const MAX_VA_BITS: usize = 39; + const MAX_PA_BITS: usize = 56; + + fn tlb_flush(vpn: Vpn) { + let vaddr = vpn.start_addr(); + unsafe { + core::arch::asm!( + "sfence.vma {0} {1}", + in(reg) vaddr.as_usize(), + in(reg) 0usize + ) + } + } + + fn tlb_flush_all() { + unsafe { core::arch::asm!("sfence.vma") } + } + + fn is_user_table(&self) -> bool { + self.is_user + } + + fn activate(ppn: Ppn) { + let satp_value = ppn_to_satp(ppn); + unsafe { + core::arch::asm!( + "csrw satp, {0}", + "sfence.vma", + in(reg) satp_value + ) + } + } + + fn activating_table_ppn() -> Ppn { + let satp_value: usize; + unsafe { + core::arch::asm!("csrr {0}, satp", out(reg) satp_value); + } + let ppn = satp_value & ((1usize << 44) - 1); // lower 44 bits for PPN in SV39 + Ppn::from_usize(ppn) + } + + fn new() -> Self { + let frame = crate::mm::frame_allocator::alloc_frame().unwrap(); + Self { + root: frame.ppn(), + frames: alloc::vec![frame], + is_user: true, + } + } + fn from_ppn(ppn: Ppn) -> Self { + Self { + root: ppn, + frames: Vec::new(), + is_user: true, + } + } + fn new_as_kernel_table() -> Self { + let frame = crate::mm::frame_allocator::alloc_frame().unwrap(); + Self { + root: frame.ppn(), + frames: alloc::vec![frame], + is_user: false, + } + } + + fn root_ppn(&self) -> Ppn { + self.root + } + + fn get_entry(&self, vpn: Vpn, level: usize) -> Option<(super::PageTableEntry, PageSize)> { + if level >= Self::LEVELS { + return None; + } + + let mut ppn = self.root; + let vpn_value = vpn.as_usize(); + + // Walk through page table levels from root to the target level + for current_level in (level..Self::LEVELS).rev() { + let idx = (vpn_value >> (9 * current_level)) & 0x1ff; + let pte_array = unsafe { + core::slice::from_raw_parts( + ppn.start_addr().to_vaddr().as_usize() as *const super::PageTableEntry, + 512, + ) + }; + let pte = &pte_array[idx]; + + if !pte.is_valid() { + return None; + } + + if current_level == level { + let page_size = match level { + 2 => PageSize::Size1G, + 1 => PageSize::Size2M, + 0 => PageSize::Size4K, + _ => unreachable!(), + }; + return Some((*pte, page_size)); + } + + ppn = pte.ppn(); + } + + None + } + + fn translate(&self, vaddr: Vaddr) -> Option { + let vpn = Vpn::from_addr_ceil(vaddr); + let offset = vaddr.as_usize() & 0xfff; // Lower 12 bits for page offset + + match self.walk(vpn) { + Ok((ppn, page_size, _flags)) => { + let paddr_base = match page_size { + PageSize::Size4K => ppn.start_addr().as_usize(), + PageSize::Size2M => { + // For 2M pages, preserve the lower 21 bits from vaddr + let offset_2m = vaddr.as_usize() & 0x1f_ffff; + ppn.start_addr().as_usize() + offset_2m - offset + } + PageSize::Size1G => { + // For 1G pages, preserve the lower 30 bits from vaddr + let offset_1g = vaddr.as_usize() & 0x3fff_ffff; + ppn.start_addr().as_usize() + offset_1g - offset + } + }; + Some(Paddr::from_usize(paddr_base + offset)) + } + Err(_) => None, + } + } + + fn map( + &mut self, + vpn: Vpn, + ppn: Ppn, + page_size: PageSize, + flags: UniversalPTEFlag, + ) -> PagingResult<()> { + // Validate flags: leaf pages must have at least one of R/W/X set + if !flags.intersects( + UniversalPTEFlag::Readable + | UniversalPTEFlag::Writeable + | UniversalPTEFlag::Executable, + ) { + return Err(PagingError::InvalidFlags); + } + + // Determine the target level based on page size + let target_level = match page_size { + PageSize::Size1G => 2, + PageSize::Size2M => 1, + PageSize::Size4K => 0, + }; + + let mut current_ppn = self.root; + let vpn_value = vpn.as_usize(); + + // Walk through page table levels from root to target level + for level in (target_level..Self::LEVELS).rev() { + let idx = (vpn_value >> (9 * level)) & 0x1ff; + let pte_array = unsafe { + core::slice::from_raw_parts_mut( + current_ppn.start_addr().to_vaddr().as_usize() as *mut super::PageTableEntry, + 512, + ) + }; + let pte = &mut pte_array[idx]; + + if level == target_level { + // We've reached the target level, create leaf entry + if pte.is_valid() { + return Err(PagingError::AlreadyMapped); + } + *pte = super::PageTableEntry::new_leaf(ppn, flags | UniversalPTEFlag::Valid); + return Ok(()); + } else { + // Intermediate level - need to continue walking + if !pte.is_valid() { + // Allocate a new page table for this level + let new_frame = crate::mm::frame_allocator::alloc_frame() + .ok_or(PagingError::FrameAllocFailed)?; + let new_ppn = new_frame.ppn(); + + // Clear the new page table + let new_table = unsafe { + core::slice::from_raw_parts_mut( + new_ppn.start_addr().to_vaddr().as_usize() + as *mut super::PageTableEntry, + 512, + ) + }; + for entry in new_table.iter_mut() { + *entry = super::PageTableEntry::empty(); + } + + *pte = super::PageTableEntry::new_table(new_ppn); + self.frames.push(new_frame); + } else if pte.is_huge() { + // There's already a huge page mapping here + return Err(PagingError::HugePageConflict); + } + + current_ppn = pte.ppn(); + } + } + + Err(PagingError::InvalidAddress) + } + + fn unmap(&mut self, vpn: Vpn) -> PagingResult<()> { + let mut current_ppn = self.root; + let vpn_value = vpn.as_usize(); + + // Walk through page table to find the leaf entry + for level in (0..Self::LEVELS).rev() { + let idx = (vpn_value >> (9 * level)) & 0x1ff; + let pte_array = unsafe { + core::slice::from_raw_parts_mut( + current_ppn.start_addr().to_vaddr().as_usize() as *mut super::PageTableEntry, + 512, + ) + }; + let pte = &mut pte_array[idx]; + + if !pte.is_valid() { + return Err(PagingError::NotMapped); + } + + // Check if this is a leaf entry (has R/W/X permissions or is level 0) + if pte.is_huge() || level == 0 { + Self::tlb_flush(vpn); + return Ok(()); + } + + current_ppn = pte.ppn(); + } + + Err(PagingError::NotMapped) + } + + fn mvmap( + &mut self, + vpn: Vpn, + target_ppn: Ppn, + page_size: PageSize, + flags: UniversalPTEFlag, + ) -> PagingResult<()> { + // First unmap the old mapping + self.unmap(vpn)?; + // Then map to the new physical page + self.map(vpn, target_ppn, page_size, flags) + } + + fn update_flags(&mut self, vpn: Vpn, flags: UniversalPTEFlag) -> PagingResult<()> { + let mut current_ppn = self.root; + let vpn_value = vpn.as_usize(); + + // Walk through page table to find the leaf entry + for level in (0..Self::LEVELS).rev() { + let idx = (vpn_value >> (9 * level)) & 0x1ff; + let pte_array = unsafe { + core::slice::from_raw_parts_mut( + current_ppn.start_addr().to_vaddr().as_usize() as *mut super::PageTableEntry, + 512, + ) + }; + let pte = &mut pte_array[idx]; + + if !pte.is_valid() { + return Err(PagingError::NotMapped); + } + + // Check if this is a leaf entry (has R/W/X permissions or is level 0) + if pte.is_huge() || level == 0 { + pte.set_flags(flags | UniversalPTEFlag::Valid); + Self::tlb_flush(vpn); + return Ok(()); + } + + current_ppn = pte.ppn(); + } + + Err(PagingError::NotMapped) + } + + fn walk(&self, vpn: Vpn) -> PagingResult<(Ppn, PageSize, UniversalPTEFlag)> { + let mut ppn = self.root; + let vpn_value = vpn.as_usize(); + + // SV39: VPN[2] = bits[38:30], VPN[1] = bits[29:21], VPN[0] = bits[20:12] + for level in (0..Self::LEVELS).rev() { + let idx = (vpn_value >> (9 * level)) & 0x1ff; + let pte_array = unsafe { + core::slice::from_raw_parts( + ppn.start_addr().to_vaddr().as_usize() as *const super::PageTableEntry, + 512, + ) + }; + let pte = &pte_array[idx]; + + if !pte.is_valid() { + return Err(PagingError::NotMapped); + } + + if pte.is_huge() || level == 0 { + let page_size = match level { + 2 => PageSize::Size1G, + 1 => PageSize::Size2M, + 0 => PageSize::Size4K, + _ => unreachable!(), + }; + return Ok((pte.ppn(), page_size, pte.flags())); + } + + ppn = pte.ppn(); + } + + Err(PagingError::NotMapped) + } +} + +fn ppn_to_satp(ppn: Ppn) -> usize { + ppn.as_usize() | (8usize << 60) // MODE=8 for SV39 +} diff --git a/os/src/arch/riscv/mm/page_table_entry.rs b/os/src/arch/riscv/mm/page_table_entry.rs index 7f2767b6..892e2699 100644 --- a/os/src/arch/riscv/mm/page_table_entry.rs +++ b/os/src/arch/riscv/mm/page_table_entry.rs @@ -48,6 +48,7 @@ impl UniversalConvertableFlag for SV39PTEFlags { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct PageTableEntry(u64); impl PageTableEntryTrait for PageTableEntry { @@ -84,7 +85,7 @@ impl PageTableEntryTrait for PageTableEntry { fn is_huge(&self) -> bool { // In SV39, we can't directly determine huge pages from the PTE alone. let sv39_flags = SV39PTEFlags::from_bits((self.0 & SV39_PTE_FLAG_MASK as u64) as usize).unwrap(); - sv39_flags.intersects(SV39PTEFlags::union(SV39PTEFlags::READ, SV39PTEFlags::EXECUTE)) + sv39_flags.intersects(SV39PTEFlags::union(SV39PTEFlags::READ, SV39PTEFlags::EXECUTE).union(SV39PTEFlags::WRITE)) } fn is_empty(&self) -> bool { diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 2da2073f..d8aba2b2 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -11,8 +11,8 @@ //! - [`page_table`]: Page table abstractions and implementations(arch-independent) pub mod address; -mod frame_allocator; -mod global_allocator; +pub mod frame_allocator; +pub mod global_allocator; pub mod page_table; pub use frame_allocator::init_frame_allocator; diff --git a/os/src/mm/page_table/page_table.rs b/os/src/mm/page_table/page_table.rs index 7ca1ee7b..dbcb57b4 100644 --- a/os/src/mm/page_table/page_table.rs +++ b/os/src/mm/page_table/page_table.rs @@ -1,5 +1,5 @@ -use super::{ActivePageTableInner, PagingResult, PageSize, PageTableEntry, UniversalPTEFlag}; -use crate::mm::address::{Ppn, PpnRange, Vpn, VpnRange}; +use super::{ActivePageTableInner, PageSize, PageTableEntry, PagingResult, UniversalPTEFlag}; +use crate::mm::address::{Paddr, Ppn, PpnRange, Vaddr, Vpn, VpnRange}; pub trait PageTableInner where @@ -10,7 +10,6 @@ where const MAX_PA_BITS: usize; fn tlb_flush(vpn: Vpn); - fn tlb_flush_vpn_range(vpn_range: VpnRange) -> PagingResult<()>; fn tlb_flush_all(); fn is_user_table(&self) -> bool; @@ -26,7 +25,7 @@ where fn get_entry(&self, vpn: Vpn, level: usize) -> Option<(T, PageSize)>; - fn translate(&self, vpn: Vpn) -> Option; + fn translate(&self, vaddr: Vaddr) -> Option; fn map( &mut self, @@ -36,7 +35,7 @@ where flags: UniversalPTEFlag, ) -> PagingResult<()>; - fn unmap(&mut self, vpn: Vpn) -> PagingResult<(Ppn, PageSize)>; + fn unmap(&mut self, vpn: Vpn) -> PagingResult<()>; fn mvmap( &mut self, @@ -44,31 +43,9 @@ where target_ppn: Ppn, page_size: PageSize, flags: UniversalPTEFlag, - ) -> PagingResult<(Ppn, PageSize)>; - - fn update_flags(&mut self, vpn: Vpn, flags: UniversalPTEFlag) -> PagingResult<()>; - - fn map_range( - &mut self, - vpn_range: VpnRange, - ppn_range: PpnRange, - flags: UniversalPTEFlag, ) -> PagingResult<()>; - fn unmap_range(&mut self, vpn_range: VpnRange) -> PagingResult; - - fn mvmap_range( - &mut self, - vpn_range: VpnRange, - target_ppn_range: PpnRange, - flags: UniversalPTEFlag, - ) -> PagingResult; - - fn update_flags_range( - &mut self, - vpn_range: VpnRange, - flags: UniversalPTEFlag, - ) -> PagingResult<()>; + fn update_flags(&mut self, vpn: Vpn, flags: UniversalPTEFlag) -> PagingResult<()>; fn walk(&self, vpn: Vpn) -> PagingResult<(Ppn, PageSize, UniversalPTEFlag)>; } From 08da1e940746e72f7aec5c6041b43737c0434a19 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Wed, 22 Oct 2025 18:17:32 +0800 Subject: [PATCH 10/10] =?UTF-8?q?refactor:=20=E6=9A=82=E6=97=B6=E6=94=BE?= =?UTF-8?q?=E5=BC=83=20pagetable=20=E5=A4=96=E5=B1=82=E5=8C=85=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- os/src/mm/page_table/page_table.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/os/src/mm/page_table/page_table.rs b/os/src/mm/page_table/page_table.rs index dbcb57b4..ae93c5d6 100644 --- a/os/src/mm/page_table/page_table.rs +++ b/os/src/mm/page_table/page_table.rs @@ -49,9 +49,3 @@ where fn walk(&self, vpn: Vpn) -> PagingResult<(Ppn, PageSize, UniversalPTEFlag)>; } - -pub struct PageTable { - inner: ActivePageTableInner, - // TODO: - tracker: (), -}