Repository navigation
Conversation
The CPU sets the accessed and dirty bits of live page table entries atomically, so software accesses to a live table should be atomic too. The crate only offers `PageTableEntry` and `PageTable`, both non-atomic, so kernels keep their own `AtomicU64` arrays and reimplement the flag and address handling. `PageTableEntry::bits` and `from_bits` expose the raw value. The `PageTableEntryBits` and `PageTableEntryBitsMut` traits encode the operations common to the plain and atomic entries: `bits` and `set_bits` are required, and `is_unused`, `flags`, `addr`, `frame` and the setters are derived from them. `PageTableEntry` keeps its inherent methods, including the `const` ones, and implements the traits through the raw value. `AtomicPageTableEntry` is a `#[repr(transparent)]` wrapper around `AtomicU64` with explicit load, store, swap, compare-exchange and fetch operations taking `PageTableEntry` values, plus the trait methods with relaxed loads and stores. `AtomicPageTable` is `#[repr(C, align(4096))]` and mirrors `PageTable`'s API: `new`, `zero`, `iter`, `iter_mut`, `is_empty`, indexing, `Clone`, `Default` and `Debug`. The atomic types exist on targets with 64-bit atomics. `PageTable` and the existing `PageTableEntry` API are otherwise unchanged.
The trait defaults now decode and encode entries directly from the raw value, and the non-const `PageTableEntry` methods delegate to them. Only the `const` operations stay inherent: `bits`, `is_unused` and `flags`. They use the same private helpers as the trait defaults, so the address mask, flag decoding and frame checks exist once. No behavior change, and `PageTableEntry` keeps its public API.
Recent nightlies add `set_bit` and `get_bit` to the integer types, which collides with `bit_field::BitField` and becomes an error under `-Dwarnings`. Allow the lint until `bit_field` avoids the collision.
|
Thank you for you contribution! Let's take a step back. Do we want atomic types *and* non-atomic types or should we only expose atomic types? What are the different use-cases? We should provide some guidance in the documentation to help users make the right choice for their use-cases. |
At runtime, AtomicU64 covers every page table use case, including private tables via get_mut or relaxed access.
So the decision is (d). If breaking compatibility is acceptable, atomic-only is viable on x86_64. |
02a0b26 to
f34a70b
Compare
Related to #416.
The CPU sets the accessed and dirty bits of live entries atomically. The crate only has non-atomic
PageTableEntryandPageTable, so kernels keep their ownAtomicU64arrays.This adds
PageTableEntry::bits/from_bits, thePageTableEntryBits/PageTableEntryBitsMuttraits, andAtomicPageTableEntry/AtomicPageTable. The traits require onlybits/set_bitsand derive the flags, address, frame and setters. The atomic entry wrapsAtomicU64with explicit ordered operations.AtomicPageTablemirrorsPageTable's API and layout.The trait methods use relaxed loads and stores, and the setters are not a single read-modify-write, so live updates use the explicit atomic operations. The atomic types exist on targets with 64-bit atomics.
PageTableandPageTableEntryare otherwise unchanged. This does not fix the mapper's&mut PageTablerequirement, so #416 stays open.Tested with the feature matrix, clippy and rustdoc with
-Dwarnings, MSRV 1.98, the CI cross targets, and Miri.