From d4d79d39cef67c946af1198f7099297fcc1723ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Fri, 21 Nov 2025 18:29:07 +0800 Subject: [PATCH 1/6] feat: add `all` feature for doc and test --- .github/workflows/ci.yml | 6 +- Cargo.lock | 25 -------- page_table_entry/Cargo.toml | 9 ++- page_table_entry/README.md | 1 - page_table_entry/src/arch/aarch64.rs | 25 ++++---- page_table_entry/src/arch/mod.rs | 8 +-- page_table_entry/src/arch/x86_64.rs | 69 ++++++++++++++++++++++- page_table_multiarch/Cargo.toml | 12 ++-- page_table_multiarch/src/arch/mod.rs | 8 +-- page_table_multiarch/src/arch/riscv.rs | 18 +++--- page_table_multiarch/src/arch/x86_64.rs | 3 + page_table_multiarch/tests/alloc_tests.rs | 4 ++ 12 files changed, 116 insertions(+), 72 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b336bc..faef829 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,9 +27,7 @@ jobs: run: cargo build --target ${{ matrix.targets }} --all-features - name: Unit test if: ${{ matrix.targets == 'x86_64-unknown-linux-gnu' }} - env: - RUSTFLAGS: --cfg doc - run: cargo test --target ${{ matrix.targets }} -- --nocapture + run: cargo test --target ${{ matrix.targets }} --all-features -- --nocapture doc: runs-on: ubuntu-latest @@ -39,13 +37,11 @@ jobs: contents: write env: default-branch: ${{ format('refs/heads/{0}', github.event.repository.default_branch) }} - RUSTFLAGS: --cfg doc RUSTDOCFLAGS: -Zunstable-options --enable-index-page -D rustdoc::broken_intra_doc_links -D missing-docs steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - name: Build docs - continue-on-error: ${{ github.ref != env.default-branch && github.event_name != 'pull_request' }} run: cargo doc --no-deps --all-features - name: Deploy to Github Pages if: ${{ github.ref == env.default-branch }} diff --git a/Cargo.lock b/Cargo.lock index 8cdedf7..81e92d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,7 +66,6 @@ dependencies = [ "aarch64-cpu", "bitflags 2.9.1", "memory_addr", - "x86_64", ] [[package]] @@ -130,24 +129,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" -[[package]] -name = "rustversion" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - [[package]] name = "tock-registers" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b9e2fdb3a1e862c0661768b7ed25390811df1947a8acbfbefe09b47078d93c4" -[[package]] -name = "volatile" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" - [[package]] name = "x86" version = "0.52.0" @@ -158,15 +145,3 @@ dependencies = [ "bitflags 1.3.2", "raw-cpuid", ] - -[[package]] -name = "x86_64" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae" -dependencies = [ - "bit_field", - "bitflags 2.9.1", - "rustversion", - "volatile", -] diff --git a/page_table_entry/Cargo.toml b/page_table_entry/Cargo.toml index 3f2f780..094f134 100644 --- a/page_table_entry/Cargo.toml +++ b/page_table_entry/Cargo.toml @@ -15,15 +15,14 @@ rust-version.workspace = true [features] arm-el2 = [] +all = [] + [dependencies] bitflags = "2.9" memory_addr.workspace = true -[target.'cfg(any(target_arch = "aarch64", doc))'.dependencies] +[dev-dependencies] aarch64-cpu = "10.0" -[target.'cfg(any(target_arch = "x86_64", doc))'.dependencies] -x86_64 = "0.15.2" - [package.metadata.docs.rs] -rustc-args = ["--cfg", "doc"] +all-features = true diff --git a/page_table_entry/README.md b/page_table_entry/README.md index 8caad66..871b009 100644 --- a/page_table_entry/README.md +++ b/page_table_entry/README.md @@ -27,7 +27,6 @@ methods for manipulating various page table entries. ```rust use memory_addr::PhysAddr; -use x86_64::structures::paging::page_table::PageTableFlags; use page_table_entry::{GenericPTE, MappingFlags, x86_64::X64PTE}; let paddr = PhysAddr::from(0x233000); diff --git a/page_table_entry/src/arch/aarch64.rs b/page_table_entry/src/arch/aarch64.rs index 9d2ba04..ad2ec5e 100644 --- a/page_table_entry/src/arch/aarch64.rs +++ b/page_table_entry/src/arch/aarch64.rs @@ -1,6 +1,5 @@ //! AArch64 VMSAv8-64 translation table format descriptors. -use aarch64_cpu::registers::MAIR_EL1; use core::fmt; use memory_addr::PhysAddr; @@ -99,16 +98,20 @@ impl DescriptorAttr { impl MemAttr { /// The MAIR_ELx register should be set to this value to match the memory /// attributes in the descriptors. - pub const MAIR_VALUE: u64 = { - // Device-nGnRE memory - let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_EarlyWriteAck.value; - // Normal memory - let attr1 = MAIR_EL1::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value - | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value; - let attr2 = MAIR_EL1::Attr2_Normal_Inner::NonCacheable.value - + MAIR_EL1::Attr2_Normal_Outer::NonCacheable.value; - attr0 | attr1 | attr2 // 0x44_ff_04 - }; + /// + /// ``` + /// # use aarch64_cpu::registers::MAIR_EL1; + /// # use page_table_entry::aarch64::MemAttr; + /// // Device-nGnRE memory + /// let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_EarlyWriteAck.value; + /// // Normal memory + /// let attr1 = MAIR_EL1::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value + /// | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value; + /// let attr2 = MAIR_EL1::Attr2_Normal_Inner::NonCacheable.value + /// + MAIR_EL1::Attr2_Normal_Outer::NonCacheable.value; + /// assert_eq!(MemAttr::MAIR_VALUE, attr0 | attr1 | attr2); + /// ``` + pub const MAIR_VALUE: u64 = 0x44_ff_04; } impl From for MappingFlags { diff --git a/page_table_entry/src/arch/mod.rs b/page_table_entry/src/arch/mod.rs index 1925eab..eeaab3f 100644 --- a/page_table_entry/src/arch/mod.rs +++ b/page_table_entry/src/arch/mod.rs @@ -1,11 +1,11 @@ -#[cfg(any(target_arch = "x86_64", doc))] +#[cfg(any(target_arch = "x86_64", feature = "all"))] pub mod x86_64; -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", doc))] +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", feature = "all"))] pub mod riscv; -#[cfg(any(target_arch = "aarch64", doc))] +#[cfg(any(target_arch = "aarch64", feature = "all"))] pub mod aarch64; -#[cfg(any(target_arch = "loongarch64", doc))] +#[cfg(any(target_arch = "loongarch64", feature = "all"))] pub mod loongarch64; diff --git a/page_table_entry/src/arch/x86_64.rs b/page_table_entry/src/arch/x86_64.rs index 8c720a7..b3df624 100644 --- a/page_table_entry/src/arch/x86_64.rs +++ b/page_table_entry/src/arch/x86_64.rs @@ -3,10 +3,75 @@ use core::fmt; use memory_addr::PhysAddr; -pub use x86_64::structures::paging::page_table::PageTableFlags as PTF; - use crate::{GenericPTE, MappingFlags}; +bitflags::bitflags! { + /// Possible flags for a page table entry. + /// + /// Reference: https://docs.rs/crate/x86_64/0.15.2/source/src/structures/paging/page_table.rs + #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] + pub struct PTF: u64 { + /// Specifies whether the mapped frame or page table is loaded in memory. + const PRESENT = 1; + /// Controls whether writes to the mapped frames are allowed. + /// + /// If this bit is unset in a level 1 page table entry, the mapped frame is read-only. + /// If this bit is unset in a higher level page table entry the complete range of mapped + /// pages is read-only. + const WRITABLE = 1 << 1; + /// Controls whether accesses from userspace (i.e. ring 3) are permitted. + const USER_ACCESSIBLE = 1 << 2; + /// If this bit is set, a “write-through” policy is used for the cache, else a “write-back” + /// policy is used. + const WRITE_THROUGH = 1 << 3; + /// Disables caching for the pointed entry is cacheable. + const NO_CACHE = 1 << 4; + /// Set by the CPU when the mapped frame or page table is accessed. + const ACCESSED = 1 << 5; + /// Set by the CPU on a write to the mapped frame. + const DIRTY = 1 << 6; + /// Specifies that the entry maps a huge frame instead of a page table. Only allowed in + /// P2 or P3 tables. + const HUGE_PAGE = 1 << 7; + /// Indicates that the mapping is present in all address spaces, so it isn't flushed from + /// the TLB on an address space switch. + const GLOBAL = 1 << 8; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_9 = 1 << 9; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_10 = 1 << 10; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_11 = 1 << 11; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_52 = 1 << 52; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_53 = 1 << 53; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_54 = 1 << 54; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_55 = 1 << 55; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_56 = 1 << 56; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_57 = 1 << 57; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_58 = 1 << 58; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_59 = 1 << 59; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_60 = 1 << 60; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_61 = 1 << 61; + /// Available to the OS, can be used to store additional data, e.g. custom flags. + const BIT_62 = 1 << 62; + /// Forbid code execution from the mapped frames. + /// + /// Can be only used when the no-execute page protection feature is enabled in the EFER + /// register. + const NO_EXECUTE = 1 << 63; + } +} + impl From for MappingFlags { fn from(f: PTF) -> Self { if !f.contains(PTF::PRESENT) { diff --git a/page_table_multiarch/Cargo.toml b/page_table_multiarch/Cargo.toml index 6d47fd1..2ce6d32 100644 --- a/page_table_multiarch/Cargo.toml +++ b/page_table_multiarch/Cargo.toml @@ -16,20 +16,22 @@ rust-version.workspace = true default = [] copy-from = ["dep:bitmaps"] +all = ["page_table_entry/all"] + [dependencies] log = "0.4" memory_addr.workspace = true page_table_entry.workspace = true bitmaps = { version = "3.2", default-features = false, optional = true } -[target.'cfg(any(target_arch = "x86_64", doc))'.dependencies] +[target.'cfg(target_arch = "x86_64")'.dependencies] x86 = "0.52" -[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64", doc))'.dependencies] +[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies] riscv = { version = "0.14", default-features = false } -[package.metadata.docs.rs] -rustc-args = ["--cfg", "doc"] - [dev-dependencies] rand = { version = "0.9.1", default-features = false, features = ["small_rng"] } + +[package.metadata.docs.rs] +all-features = true diff --git a/page_table_multiarch/src/arch/mod.rs b/page_table_multiarch/src/arch/mod.rs index 1925eab..eeaab3f 100644 --- a/page_table_multiarch/src/arch/mod.rs +++ b/page_table_multiarch/src/arch/mod.rs @@ -1,11 +1,11 @@ -#[cfg(any(target_arch = "x86_64", doc))] +#[cfg(any(target_arch = "x86_64", feature = "all"))] pub mod x86_64; -#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", doc))] +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", feature = "all"))] pub mod riscv; -#[cfg(any(target_arch = "aarch64", doc))] +#[cfg(any(target_arch = "aarch64", feature = "all"))] pub mod aarch64; -#[cfg(any(target_arch = "loongarch64", doc))] +#[cfg(any(target_arch = "loongarch64", feature = "all"))] pub mod loongarch64; diff --git a/page_table_multiarch/src/arch/riscv.rs b/page_table_multiarch/src/arch/riscv.rs index 8674ea4..8bf6dbc 100644 --- a/page_table_multiarch/src/arch/riscv.rs +++ b/page_table_multiarch/src/arch/riscv.rs @@ -3,15 +3,6 @@ use crate::{PageTable64, PagingMetaData}; use page_table_entry::riscv::Rv64PTE; -#[inline] -fn riscv_flush_tlb(vaddr: Option) { - if let Some(vaddr) = vaddr { - riscv::asm::sfence_vma(0, vaddr.as_usize()) - } else { - riscv::asm::sfence_vma_all(); - } -} - /// A virtual address that can be used in RISC-V Sv39 and Sv48 page tables. pub trait SvVirtAddr: memory_addr::MemoryAddr + Send + Sync { /// Flush the TLB. @@ -21,7 +12,14 @@ pub trait SvVirtAddr: memory_addr::MemoryAddr + Send + Sync { impl SvVirtAddr for memory_addr::VirtAddr { #[inline] fn flush_tlb(vaddr: Option) { - riscv_flush_tlb(vaddr.map(|vaddr| vaddr.into())) + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] + if let Some(vaddr) = vaddr { + riscv::asm::sfence_vma(0, vaddr.as_usize()) + } else { + riscv::asm::sfence_vma_all(); + } + #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] + let _ = vaddr; } } diff --git a/page_table_multiarch/src/arch/x86_64.rs b/page_table_multiarch/src/arch/x86_64.rs index 6f9c37d..8b8c551 100644 --- a/page_table_multiarch/src/arch/x86_64.rs +++ b/page_table_multiarch/src/arch/x86_64.rs @@ -14,6 +14,7 @@ impl PagingMetaData for X64PagingMetaData { #[inline] fn flush_tlb(vaddr: Option) { + #[cfg(target_arch = "x86_64")] unsafe { if let Some(vaddr) = vaddr { x86::tlb::flush(vaddr.into()); @@ -21,6 +22,8 @@ impl PagingMetaData for X64PagingMetaData { x86::tlb::flush_all(); } } + #[cfg(not(target_arch = "x86_64"))] + let _ = vaddr; } } diff --git a/page_table_multiarch/tests/alloc_tests.rs b/page_table_multiarch/tests/alloc_tests.rs index 8feae47..115c9f7 100644 --- a/page_table_multiarch/tests/alloc_tests.rs +++ b/page_table_multiarch/tests/alloc_tests.rs @@ -91,6 +91,7 @@ fn run_test_for, PTE: GenericPTE>() -> Pa } #[test] +#[cfg(any(target_arch = "x86_64", feature = "all"))] fn test_dealloc_x86() -> PagingResult<()> { run_test_for::< page_table_multiarch::x86_64::X64PagingMetaData, @@ -100,6 +101,7 @@ fn test_dealloc_x86() -> PagingResult<()> { } #[test] +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", feature = "all"))] fn test_dealloc_riscv() -> PagingResult<()> { run_test_for::< page_table_multiarch::riscv::Sv39MetaData, @@ -113,6 +115,7 @@ fn test_dealloc_riscv() -> PagingResult<()> { } #[test] +#[cfg(any(target_arch = "aarch64", feature = "all"))] fn test_dealloc_aarch64() -> PagingResult<()> { run_test_for::< page_table_multiarch::aarch64::A64PagingMetaData, @@ -122,6 +125,7 @@ fn test_dealloc_aarch64() -> PagingResult<()> { } #[test] +#[cfg(any(target_arch = "loongarch64", feature = "all"))] fn test_dealloc_loongarch64() -> PagingResult<()> { run_test_for::< page_table_multiarch::loongarch64::LA64MetaData, From 34e078e167cc3f6219193b1fddd21d5fe6e4c09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Fri, 21 Nov 2025 20:55:46 +0800 Subject: [PATCH 2/6] fix: restore target specific dependencies --- Cargo.lock | 50 ++++++++++-------- page_table_entry/Cargo.toml | 11 +++- page_table_entry/src/arch/aarch64.rs | 25 ++++----- page_table_entry/src/arch/x86_64.rs | 68 +------------------------ page_table_multiarch/Cargo.toml | 8 ++- page_table_multiarch/src/arch/riscv.rs | 3 -- page_table_multiarch/src/arch/x86_64.rs | 13 ++--- 7 files changed, 59 insertions(+), 119 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81e92d3..ac2bf4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,12 +17,6 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.9.1" @@ -35,6 +29,12 @@ version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" +[[package]] +name = "const_fn" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e" + [[package]] name = "critical-section" version = "1.2.0" @@ -64,8 +64,9 @@ name = "page_table_entry" version = "0.5.6" dependencies = [ "aarch64-cpu", - "bitflags 2.9.1", + "bitflags", "memory_addr", + "x86_64", ] [[package]] @@ -78,7 +79,7 @@ dependencies = [ "page_table_entry", "rand", "riscv", - "x86", + "x86_64", ] [[package]] @@ -102,15 +103,6 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -[[package]] -name = "raw-cpuid" -version = "10.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "riscv" version = "0.14.0" @@ -129,6 +121,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "tock-registers" version = "0.9.0" @@ -136,12 +134,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b9e2fdb3a1e862c0661768b7ed25390811df1947a8acbfbefe09b47078d93c4" [[package]] -name = "x86" -version = "0.52.0" +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "x86_64" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +checksum = "575f620d283cb63500b96c4bcaa12523c6a278d89b85ea35c97ad43ba754fd1e" dependencies = [ "bit_field", - "bitflags 1.3.2", - "raw-cpuid", + "bitflags", + "const_fn", + "rustversion", + "volatile", ] diff --git a/page_table_entry/Cargo.toml b/page_table_entry/Cargo.toml index 094f134..c0cd85b 100644 --- a/page_table_entry/Cargo.toml +++ b/page_table_entry/Cargo.toml @@ -15,14 +15,21 @@ rust-version.workspace = true [features] arm-el2 = [] -all = [] +all = ["dep:aarch64-cpu", "dep:x86_64"] [dependencies] bitflags = "2.9" memory_addr.workspace = true -[dev-dependencies] +# Target-specific dependencies +aarch64-cpu = { version = "10.0", optional = true } +x86_64 = { version = "0.15", optional = true } + +[target.'cfg(target_arch = "aarch64")'.dependencies] aarch64-cpu = "10.0" +[target.'cfg(target_arch = "x86_64")'.dependencies] +x86_64 = "0.15" + [package.metadata.docs.rs] all-features = true diff --git a/page_table_entry/src/arch/aarch64.rs b/page_table_entry/src/arch/aarch64.rs index ad2ec5e..f814f50 100644 --- a/page_table_entry/src/arch/aarch64.rs +++ b/page_table_entry/src/arch/aarch64.rs @@ -98,20 +98,17 @@ impl DescriptorAttr { impl MemAttr { /// The MAIR_ELx register should be set to this value to match the memory /// attributes in the descriptors. - /// - /// ``` - /// # use aarch64_cpu::registers::MAIR_EL1; - /// # use page_table_entry::aarch64::MemAttr; - /// // Device-nGnRE memory - /// let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_EarlyWriteAck.value; - /// // Normal memory - /// let attr1 = MAIR_EL1::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value - /// | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value; - /// let attr2 = MAIR_EL1::Attr2_Normal_Inner::NonCacheable.value - /// + MAIR_EL1::Attr2_Normal_Outer::NonCacheable.value; - /// assert_eq!(MemAttr::MAIR_VALUE, attr0 | attr1 | attr2); - /// ``` - pub const MAIR_VALUE: u64 = 0x44_ff_04; + pub const MAIR_VALUE: u64 = { + use aarch64_cpu::registers::MAIR_EL1; + // Device-nGnRE memory + let attr0 = MAIR_EL1::Attr0_Device::nonGathering_nonReordering_EarlyWriteAck.value; + // Normal memory + let attr1 = MAIR_EL1::Attr1_Normal_Inner::WriteBack_NonTransient_ReadWriteAlloc.value + | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value; + let attr2 = MAIR_EL1::Attr2_Normal_Inner::NonCacheable.value + + MAIR_EL1::Attr2_Normal_Outer::NonCacheable.value; + attr0 | attr1 | attr2 + }; } impl From for MappingFlags { diff --git a/page_table_entry/src/arch/x86_64.rs b/page_table_entry/src/arch/x86_64.rs index b3df624..851a040 100644 --- a/page_table_entry/src/arch/x86_64.rs +++ b/page_table_entry/src/arch/x86_64.rs @@ -2,76 +2,10 @@ use core::fmt; use memory_addr::PhysAddr; +use x86_64::structures::paging::page_table::PageTableFlags as PTF; use crate::{GenericPTE, MappingFlags}; -bitflags::bitflags! { - /// Possible flags for a page table entry. - /// - /// Reference: https://docs.rs/crate/x86_64/0.15.2/source/src/structures/paging/page_table.rs - #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)] - pub struct PTF: u64 { - /// Specifies whether the mapped frame or page table is loaded in memory. - const PRESENT = 1; - /// Controls whether writes to the mapped frames are allowed. - /// - /// If this bit is unset in a level 1 page table entry, the mapped frame is read-only. - /// If this bit is unset in a higher level page table entry the complete range of mapped - /// pages is read-only. - const WRITABLE = 1 << 1; - /// Controls whether accesses from userspace (i.e. ring 3) are permitted. - const USER_ACCESSIBLE = 1 << 2; - /// If this bit is set, a “write-through” policy is used for the cache, else a “write-back” - /// policy is used. - const WRITE_THROUGH = 1 << 3; - /// Disables caching for the pointed entry is cacheable. - const NO_CACHE = 1 << 4; - /// Set by the CPU when the mapped frame or page table is accessed. - const ACCESSED = 1 << 5; - /// Set by the CPU on a write to the mapped frame. - const DIRTY = 1 << 6; - /// Specifies that the entry maps a huge frame instead of a page table. Only allowed in - /// P2 or P3 tables. - const HUGE_PAGE = 1 << 7; - /// Indicates that the mapping is present in all address spaces, so it isn't flushed from - /// the TLB on an address space switch. - const GLOBAL = 1 << 8; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_9 = 1 << 9; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_10 = 1 << 10; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_11 = 1 << 11; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_52 = 1 << 52; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_53 = 1 << 53; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_54 = 1 << 54; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_55 = 1 << 55; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_56 = 1 << 56; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_57 = 1 << 57; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_58 = 1 << 58; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_59 = 1 << 59; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_60 = 1 << 60; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_61 = 1 << 61; - /// Available to the OS, can be used to store additional data, e.g. custom flags. - const BIT_62 = 1 << 62; - /// Forbid code execution from the mapped frames. - /// - /// Can be only used when the no-execute page protection feature is enabled in the EFER - /// register. - const NO_EXECUTE = 1 << 63; - } -} - impl From for MappingFlags { fn from(f: PTF) -> Self { if !f.contains(PTF::PRESENT) { diff --git a/page_table_multiarch/Cargo.toml b/page_table_multiarch/Cargo.toml index 2ce6d32..a3f64b9 100644 --- a/page_table_multiarch/Cargo.toml +++ b/page_table_multiarch/Cargo.toml @@ -16,7 +16,7 @@ rust-version.workspace = true default = [] copy-from = ["dep:bitmaps"] -all = ["page_table_entry/all"] +all = ["page_table_entry/all", "dep:riscv", "dep:x86_64"] [dependencies] log = "0.4" @@ -24,8 +24,12 @@ memory_addr.workspace = true page_table_entry.workspace = true bitmaps = { version = "3.2", default-features = false, optional = true } +# Target-specific dependencies +riscv = { version = "0.14", default-features = false, optional = true } +x86_64 = { version = "0.15", optional = true } + [target.'cfg(target_arch = "x86_64")'.dependencies] -x86 = "0.52" +x86_64 = "0.15" [target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies] riscv = { version = "0.14", default-features = false } diff --git a/page_table_multiarch/src/arch/riscv.rs b/page_table_multiarch/src/arch/riscv.rs index 8bf6dbc..d0ca096 100644 --- a/page_table_multiarch/src/arch/riscv.rs +++ b/page_table_multiarch/src/arch/riscv.rs @@ -12,14 +12,11 @@ pub trait SvVirtAddr: memory_addr::MemoryAddr + Send + Sync { impl SvVirtAddr for memory_addr::VirtAddr { #[inline] fn flush_tlb(vaddr: Option) { - #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] if let Some(vaddr) = vaddr { riscv::asm::sfence_vma(0, vaddr.as_usize()) } else { riscv::asm::sfence_vma_all(); } - #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - let _ = vaddr; } } diff --git a/page_table_multiarch/src/arch/x86_64.rs b/page_table_multiarch/src/arch/x86_64.rs index 8b8c551..48e7c58 100644 --- a/page_table_multiarch/src/arch/x86_64.rs +++ b/page_table_multiarch/src/arch/x86_64.rs @@ -14,16 +14,11 @@ impl PagingMetaData for X64PagingMetaData { #[inline] fn flush_tlb(vaddr: Option) { - #[cfg(target_arch = "x86_64")] - unsafe { - if let Some(vaddr) = vaddr { - x86::tlb::flush(vaddr.into()); - } else { - x86::tlb::flush_all(); - } + if let Some(vaddr) = vaddr { + x86_64::instructions::tlb::flush(x86_64::VirtAddr::new(vaddr.as_usize() as u64)); + } else { + x86_64::instructions::tlb::flush_all(); } - #[cfg(not(target_arch = "x86_64"))] - let _ = vaddr; } } From e3294fbf0e30b45694257424f55c1772989cadb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Fri, 21 Nov 2025 20:56:51 +0800 Subject: [PATCH 3/6] fix: re-export x86_64 PTF --- page_table_entry/src/arch/x86_64.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/page_table_entry/src/arch/x86_64.rs b/page_table_entry/src/arch/x86_64.rs index 851a040..8c720a7 100644 --- a/page_table_entry/src/arch/x86_64.rs +++ b/page_table_entry/src/arch/x86_64.rs @@ -2,7 +2,8 @@ use core::fmt; use memory_addr::PhysAddr; -use x86_64::structures::paging::page_table::PageTableFlags as PTF; + +pub use x86_64::structures::paging::page_table::PageTableFlags as PTF; use crate::{GenericPTE, MappingFlags}; From a93513119e27bbf98aa779bd0fa70c80442fb961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Fri, 21 Nov 2025 21:11:25 +0800 Subject: [PATCH 4/6] fix: remove target-specific crates for page_table_multiarch/all --- page_table_entry/Cargo.toml | 4 ++-- page_table_multiarch/Cargo.toml | 9 ++++----- page_table_multiarch/src/arch/riscv.rs | 3 +++ page_table_multiarch/src/arch/x86_64.rs | 3 +++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/page_table_entry/Cargo.toml b/page_table_entry/Cargo.toml index c0cd85b..fc05293 100644 --- a/page_table_entry/Cargo.toml +++ b/page_table_entry/Cargo.toml @@ -23,13 +23,13 @@ memory_addr.workspace = true # Target-specific dependencies aarch64-cpu = { version = "10.0", optional = true } -x86_64 = { version = "0.15", optional = true } +x86_64 = { version = "0.15", default-features = false, optional = true } [target.'cfg(target_arch = "aarch64")'.dependencies] aarch64-cpu = "10.0" [target.'cfg(target_arch = "x86_64")'.dependencies] -x86_64 = "0.15" +x86_64 = { version = "0.15", default-features = false } [package.metadata.docs.rs] all-features = true diff --git a/page_table_multiarch/Cargo.toml b/page_table_multiarch/Cargo.toml index a3f64b9..3864776 100644 --- a/page_table_multiarch/Cargo.toml +++ b/page_table_multiarch/Cargo.toml @@ -16,7 +16,7 @@ rust-version.workspace = true default = [] copy-from = ["dep:bitmaps"] -all = ["page_table_entry/all", "dep:riscv", "dep:x86_64"] +all = ["page_table_entry/all"] [dependencies] log = "0.4" @@ -25,11 +25,10 @@ page_table_entry.workspace = true bitmaps = { version = "3.2", default-features = false, optional = true } # Target-specific dependencies -riscv = { version = "0.14", default-features = false, optional = true } -x86_64 = { version = "0.15", optional = true } - [target.'cfg(target_arch = "x86_64")'.dependencies] -x86_64 = "0.15" +x86_64 = { version = "0.15", default-features = false, features = [ + "instructions", +] } [target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies] riscv = { version = "0.14", default-features = false } diff --git a/page_table_multiarch/src/arch/riscv.rs b/page_table_multiarch/src/arch/riscv.rs index d0ca096..8bf6dbc 100644 --- a/page_table_multiarch/src/arch/riscv.rs +++ b/page_table_multiarch/src/arch/riscv.rs @@ -12,11 +12,14 @@ pub trait SvVirtAddr: memory_addr::MemoryAddr + Send + Sync { impl SvVirtAddr for memory_addr::VirtAddr { #[inline] fn flush_tlb(vaddr: Option) { + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] if let Some(vaddr) = vaddr { riscv::asm::sfence_vma(0, vaddr.as_usize()) } else { riscv::asm::sfence_vma_all(); } + #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] + let _ = vaddr; } } diff --git a/page_table_multiarch/src/arch/x86_64.rs b/page_table_multiarch/src/arch/x86_64.rs index 48e7c58..e71f8ce 100644 --- a/page_table_multiarch/src/arch/x86_64.rs +++ b/page_table_multiarch/src/arch/x86_64.rs @@ -14,11 +14,14 @@ impl PagingMetaData for X64PagingMetaData { #[inline] fn flush_tlb(vaddr: Option) { + #[cfg(target_arch = "x86_64")] if let Some(vaddr) = vaddr { x86_64::instructions::tlb::flush(x86_64::VirtAddr::new(vaddr.as_usize() as u64)); } else { x86_64::instructions::tlb::flush_all(); } + #[cfg(not(target_arch = "x86_64"))] + let _ = vaddr; } } From 8d3067bdf72d01b83f4de0ee1e60c3ca67b8bde2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Fri, 21 Nov 2025 21:13:39 +0800 Subject: [PATCH 5/6] chore: add the comment back --- page_table_entry/src/arch/aarch64.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/page_table_entry/src/arch/aarch64.rs b/page_table_entry/src/arch/aarch64.rs index f814f50..360d01d 100644 --- a/page_table_entry/src/arch/aarch64.rs +++ b/page_table_entry/src/arch/aarch64.rs @@ -107,7 +107,7 @@ impl MemAttr { | MAIR_EL1::Attr1_Normal_Outer::WriteBack_NonTransient_ReadWriteAlloc.value; let attr2 = MAIR_EL1::Attr2_Normal_Inner::NonCacheable.value + MAIR_EL1::Attr2_Normal_Outer::NonCacheable.value; - attr0 | attr1 | attr2 + attr0 | attr1 | attr2 // 0x44_ff_04 }; } From 36ce172d3f7e6c9a088ce2e62e1002543616d078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Fri, 21 Nov 2025 21:19:16 +0800 Subject: [PATCH 6/6] feat: panic on unimplemented targets --- page_table_multiarch/src/arch/aarch64.rs | 11 ++++++++--- page_table_multiarch/src/arch/loongarch64.rs | 11 ++++++++--- page_table_multiarch/src/arch/riscv.rs | 5 ++++- page_table_multiarch/src/arch/x86_64.rs | 5 ++++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/page_table_multiarch/src/arch/aarch64.rs b/page_table_multiarch/src/arch/aarch64.rs index fa191a1..9ac042b 100644 --- a/page_table_multiarch/src/arch/aarch64.rs +++ b/page_table_multiarch/src/arch/aarch64.rs @@ -1,6 +1,5 @@ //! AArch64 specific page table structures. -use core::arch::asm; use page_table_entry::aarch64::A64PTE; use crate::{PageTable64, PagingMetaData}; @@ -21,16 +20,22 @@ impl PagingMetaData for A64PagingMetaData { #[inline] fn flush_tlb(vaddr: Option) { + #[cfg(target_arch = "aarch64")] unsafe { if let Some(vaddr) = vaddr { // TLB Invalidate by VA, All ASID, EL1, Inner Shareable const VA_MASK: usize = (1 << 44) - 1; // VA[55:12] => bits[43:0] - asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) ((vaddr.as_usize() >> 12) & VA_MASK)) + core::arch::asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) ((vaddr.as_usize() >> 12) & VA_MASK)) } else { // TLB Invalidate by VMID, All at stage 1, EL1 - asm!("tlbi vmalle1; dsb sy; isb") + core::arch::asm!("tlbi vmalle1; dsb sy; isb") } } + #[cfg(not(target_arch = "aarch64"))] + { + let _ = vaddr; + unimplemented!() + } } } diff --git a/page_table_multiarch/src/arch/loongarch64.rs b/page_table_multiarch/src/arch/loongarch64.rs index 04a527b..52f4f18 100644 --- a/page_table_multiarch/src/arch/loongarch64.rs +++ b/page_table_multiarch/src/arch/loongarch64.rs @@ -1,7 +1,6 @@ //! LoongArch64 specific page table structures. use crate::{PageTable64, PagingMetaData}; -use core::arch::asm; use page_table_entry::loongarch64::LA64PTE; /// Metadata of LoongArch64 page tables. @@ -48,6 +47,7 @@ impl PagingMetaData for LA64MetaData { #[inline] fn flush_tlb(vaddr: Option) { + #[cfg(target_arch = "loongarch64")] unsafe { if let Some(vaddr) = vaddr { // @@ -66,12 +66,17 @@ impl PagingMetaData for LA64MetaData { // // When the operation indicated by op does not require an ASID, the // general register rj should be set to r0. - asm!("dbar 0; invtlb 0x05, $r0, {reg}", reg = in(reg) vaddr.as_usize()); + core::arch::asm!("dbar 0; invtlb 0x05, $r0, {reg}", reg = in(reg) vaddr.as_usize()); } else { // op 0x0: Clear all page table entries - asm!("dbar 0; invtlb 0x00, $r0, $r0"); + core::arch::asm!("dbar 0; invtlb 0x00, $r0, $r0"); } } + #[cfg(not(target_arch = "loongarch64"))] + { + let _ = vaddr; + unimplemented!() + } } } diff --git a/page_table_multiarch/src/arch/riscv.rs b/page_table_multiarch/src/arch/riscv.rs index 8bf6dbc..f03736f 100644 --- a/page_table_multiarch/src/arch/riscv.rs +++ b/page_table_multiarch/src/arch/riscv.rs @@ -19,7 +19,10 @@ impl SvVirtAddr for memory_addr::VirtAddr { riscv::asm::sfence_vma_all(); } #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] - let _ = vaddr; + { + let _ = vaddr; + unimplemented!() + } } } diff --git a/page_table_multiarch/src/arch/x86_64.rs b/page_table_multiarch/src/arch/x86_64.rs index e71f8ce..a648c22 100644 --- a/page_table_multiarch/src/arch/x86_64.rs +++ b/page_table_multiarch/src/arch/x86_64.rs @@ -21,7 +21,10 @@ impl PagingMetaData for X64PagingMetaData { x86_64::instructions::tlb::flush_all(); } #[cfg(not(target_arch = "x86_64"))] - let _ = vaddr; + { + let _ = vaddr; + unimplemented!() + } } }