Workspace Structure
Relevant source files
This document explains the two-crate workspace structure of the page_table_multiarch
repository and how the crates interact to provide multi-architecture page table functionality. It covers the workspace configuration, crate responsibilities, dependency management, and conditional compilation strategy.
For detailed information about the individual crate implementations, see page_table_multiarch Crate and page_table_entry Crate.
Workspace Overview
The page_table_multiarch
repository is organized as a Cargo workspace containing two complementary crates that provide a layered approach to page table management across multiple hardware architectures.
Workspace Definition
The workspace is defined in the root Cargo.toml(L1 - L7) with two member crates:
Crate | Purpose | Role |
---|---|---|
page_table_multiarch | High-level page table abstractions | Main API providingPageTable64and unified interface |
page_table_entry | Low-level page table entries | Architecture-specific PTE implementations andGenericPTEtrait |
Workspace Structure Diagram
flowchart TD subgraph subGraph2["page_table_multiarch Workspace"] ROOT["Cargo.toml(Workspace Root)"] subgraph subGraph1["page_table_entry Crate"] PTE["page_table_entryPage table entry definitions"] PTE_CARGO["page_table_entry/Cargo.toml"] end subgraph subGraph0["page_table_multiarch Crate"] PTM_CARGO["page_table_multiarch/Cargo.toml"] PTM["page_table_multiarchGeneric page table structures"] end end PTE_CARGO --> PTE PTM --> PTE PTM_CARGO --> PTM ROOT --> PTE_CARGO ROOT --> PTM_CARGO
Sources: Cargo.toml(L4 - L7) page_table_multiarch/Cargo.toml(L2 - L3) page_table_entry/Cargo.toml(L2 - L3)
Shared Workspace Configuration
The workspace defines common package metadata in Cargo.toml(L9 - L19) that is inherited by both member crates:
- Version:
0.5.3
- synchronized across all crates - Edition:
2024
- uses latest Rust edition - Categories:
["os", "hardware-support", "memory-management", "no-std"]
- Keywords:
["arceos", "paging", "page-table", "virtual-memory"]
- Rust Version:
1.85
- minimum supported Rust version
Sources: Cargo.toml(L9 - L19) page_table_multiarch/Cargo.toml(L5 - L13) page_table_entry/Cargo.toml(L5 - L13)
Crate Interaction Architecture
The two crates form a layered architecture where page_table_multiarch
provides high-level abstractions while depending on page_table_entry
for low-level functionality.
Crate Dependency and Interaction Diagram
flowchart TD subgraph subGraph3["External Dependencies"] MEMORY_ADDR["memory_addr crateAddress types"] LOG["log crateLogging"] BITFLAGS["bitflags crateFlag manipulation"] ARCH_SPECIFIC["x86, riscv, aarch64-cpux86_64 crates"] end subgraph subGraph2["page_table_entry Crate"] PTE_TRAIT["GenericPTE trait"] PTE_IMPL["X64PTE, A64PTERv64PTE, LA64PTE"] PTE_FLAGS["MappingFlagsArchitecture conversion"] end subgraph subGraph1["page_table_multiarch Crate"] PTM_API["PageTable64"] PTM_TRAITS["PagingMetaDataPagingHandler traits"] PTM_IMPL["Architecture-specificPageTable implementations"] end subgraph subGraph0["Application Layer"] APP["Operating SystemsHypervisorsKernel Code"] end APP --> PTM_API PTE_IMPL --> ARCH_SPECIFIC PTE_IMPL --> BITFLAGS PTE_IMPL --> PTE_FLAGS PTE_TRAIT --> MEMORY_ADDR PTE_TRAIT --> PTE_FLAGS PTM_API --> LOG PTM_API --> MEMORY_ADDR PTM_API --> PTM_IMPL PTM_API --> PTM_TRAITS PTM_IMPL --> ARCH_SPECIFIC PTM_IMPL --> PTE_IMPL PTM_TRAITS --> PTE_TRAIT
Sources: page_table_multiarch/Cargo.toml(L15 - L18) page_table_entry/Cargo.toml(L18 - L20)
Dependency Relationship
The page_table_multiarch
crate explicitly depends on page_table_entry
as defined in page_table_multiarch/Cargo.toml(L18) :
page_table_entry = { path = "../page_table_entry", version = "0.5.2" }
This creates a clear separation of concerns:
- High-level operations (page table walking, mapping, unmapping) in
page_table_multiarch
- Low-level PTE manipulation (bit operations, flag conversions) in
page_table_entry
Sources: page_table_multiarch/Cargo.toml(L18)
Architecture-Specific Dependencies
Both crates use conditional compilation to include only the necessary architecture-specific dependencies based on the target platform.
page_table_multiarch Dependencies
Conditional Dependencies Diagram
flowchart TD subgraph subGraph0["page_table_multiarch Dependencies"] CORE["Core Dependencieslog, memory_addrpage_table_entry"] X86_TARGET["cfg(target_arch = x86_64)"] X86_DEP["x86 = 0.52"] RISCV_TARGET["cfg(target_arch = riscv32/64)"] RISCV_DEP["riscv = 0.12"] DOC_TARGET["cfg(doc)"] ALL_DEP["All arch dependenciesfor documentation"] end CORE --> DOC_TARGET CORE --> RISCV_TARGET CORE --> X86_TARGET DOC_TARGET --> ALL_DEP RISCV_TARGET --> RISCV_DEP X86_TARGET --> X86_DEP
Sources: page_table_multiarch/Cargo.toml(L20 - L24) page_table_multiarch/Cargo.toml(L26 - L27)
page_table_entry Dependencies
The page_table_entry
crate includes more architecture-specific dependencies:
Target Architecture | Dependencies | Purpose |
---|---|---|
x86_64 | x86_64 = "0.15.2" | x86-64 specific register and instruction access |
aarch64 | aarch64-cpu = "10.0" | ARM64 system register and instruction access |
riscv32/riscv64 | None (built-in) | RISC-V support uses standard library features |
loongarch64 | None (built-in) | LoongArch support uses standard library features |
page_table_entry Architecture Dependencies
flowchart TD subgraph subGraph2["page_table_entry Conditional Dependencies"] PTE_CORE["Core Dependenciesbitflags, memory_addr"] subgraph subGraph1["Feature Flags"] ARM_EL2["arm-el2 featureARM Exception Level 2"] end subgraph subGraph0["Architecture Dependencies"] AARCH64_CFG["cfg(target_arch = aarch64)"] X86_64_CFG["cfg(target_arch = x86_64)"] DOC_CFG["cfg(doc)"] AARCH64_DEP["aarch64-cpu = 10.0"] X86_64_DEP["x86_64 = 0.15.2"] DOC_DEP["All dependencies"] end end AARCH64_CFG --> AARCH64_DEP AARCH64_DEP --> ARM_EL2 DOC_CFG --> DOC_DEP PTE_CORE --> AARCH64_CFG PTE_CORE --> DOC_CFG PTE_CORE --> X86_64_CFG X86_64_CFG --> X86_64_DEP
Sources: page_table_entry/Cargo.toml(L22 - L26) page_table_entry/Cargo.toml(L15 - L16)
Documentation Configuration
Both crates include special configuration for documentation generation using docs.rs
:
- Documentation builds include all architecture dependencies via
cfg(doc)
- Rustc arguments add
--cfg doc
for conditional compilation during docs generation - This ensures complete documentation coverage across all supported architectures
The configuration in page_table_multiarch/Cargo.toml(L26 - L27) and page_table_entry/Cargo.toml(L28 - L29) enables this behavior.
Sources: page_table_multiarch/Cargo.toml(L26 - L27) page_table_entry/Cargo.toml(L28 - L29)
Workspace Benefits
The two-crate structure provides several architectural advantages:
- Separation of Concerns: High-level page table operations vs. low-level PTE manipulation
- Conditional Compilation: Architecture-specific dependencies are isolated and only included when needed
- Reusability: The
page_table_entry
crate can be used independently for PTE operations - Testing: Each layer can be tested independently with appropriate mocking
- Documentation: Clear API boundaries make the system easier to understand and document
Sources: Cargo.toml(L1 - L19) page_table_multiarch/Cargo.toml(L1 - L28) page_table_entry/Cargo.toml(L1 - L29)