Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [add `MappedPageTable::display`](https://github.com/rust-osdev/x86_64/pull/574)
- The mappings of a `MappedPageTable` can now be displayed.
- [Increase the Minimum Supported Rust Version to 1.98](https://github.com/rust-osdev/x86_64/pull/604)
- [make memory encryption bit an upper limit for physical address bits](https://github.com/rust-osdev/x86_64/pull/603)

# 0.15.5 – 2026-07-11

Expand Down
7 changes: 4 additions & 3 deletions src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::ops::{Add, AddAssign, Sub, SubAssign};
use core::sync::atomic::Ordering;

#[cfg(feature = "memory_encryption")]
use crate::structures::mem_encrypt::ENC_BIT_MASK;
use crate::structures::mem_encrypt::PHYSICAL_ADDRESS_MASK;
use crate::structures::paging::page_table::PageTableLevel;
use crate::structures::paging::{PageOffset, PageTableIndex};

Expand Down Expand Up @@ -571,14 +571,15 @@ impl PhysAddr {
#[cfg(feature = "memory_encryption")]
#[inline]
pub fn new_truncate(addr: u64) -> PhysAddr {
PhysAddr((addr % (1 << 52)) & !ENC_BIT_MASK.load(Ordering::Relaxed))
PhysAddr(addr & PHYSICAL_ADDRESS_MASK.load(Ordering::Relaxed))
}

/// Creates a new physical address, without any checks.
///
/// ## Safety
///
/// You must make sure bits 52..64 are zero. This is not checked.
/// You must make sure bits 52..64 are zero and that no bits at or above
/// the encryption bit (if one is configured) are set. This is not checked.
#[inline]
pub const unsafe fn new_unsafe(addr: u64) -> PhysAddr {
PhysAddr(addr)
Expand Down
25 changes: 21 additions & 4 deletions src/structures/mem_encrypt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@
use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};

use crate::structures::paging::PageTableFlags;
use crate::structures::paging::page_table::PHYSICAL_ADDRESS_MASK;

/// Position of the encryption (C/S) bit in the physical address
///
/// If a memory encryption configuration has been set up, this contains a bit
/// mask with just that bit set.
pub(crate) static ENC_BIT_MASK: AtomicU64 = AtomicU64::new(0);

/// Is the encryption bit reversed (i.e. its presence denote that the page is _decrypted_ rather
/// than encrypted)
static ENC_BIT_REVERSED: AtomicBool = AtomicBool::new(false);

/// The mask of valid physical address bits.
#[cfg(feature = "memory_encryption")]
pub(crate) static PHYSICAL_ADDRESS_MASK: AtomicU64 = AtomicU64::new(0x000f_ffff_ffff_ffffu64);

/// Defines the configuration for memory encryption
#[derive(Debug)]
pub enum MemoryEncryptionConfiguration {
Expand All @@ -34,22 +40,33 @@ pub enum MemoryEncryptionConfiguration {
}

/// Enable memory encryption by defining the physical address bit that is used to mark a page
/// encrypted (or shared) in a page table entry
/// encrypted (or shared) in a page table entry.
///
/// Once memory encryption has been enabled [`PhysAddr::new`](crate::addr::PhysAddr::new) will not
/// allow any bits at or above the encryption bit to be set.
///
/// # Safety
///
/// Caller must make sure that any existing page table entry is discarded or adapted to take this
/// bit into consideration.
///
/// The caller must ensure that there are no [`PhysAddr`](crate::addr::PhysAddr) instances that
/// have the encryption bit or any bits above it set.
///
/// The configuration provided by caller must be correct, otherwise physical address bits will
/// incorrectly be considered as page table flags.
///
/// This function may only be called once.
pub unsafe fn enable_memory_encryption(configuration: MemoryEncryptionConfiguration) {
let (bit_position, reversed) = match configuration {
MemoryEncryptionConfiguration::EncryptedBit(pos) => (pos, false),
MemoryEncryptionConfiguration::SharedBit(pos) => (pos, true),
};

let c_bit_mask = 1u64 << bit_position;
let addr_mask = u64::MAX << bit_position;
PHYSICAL_ADDRESS_MASK.fetch_and(!addr_mask, Ordering::Relaxed);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that the method is only called once, right? We should add that to the safety docs of the method?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I update the doc comment.


PHYSICAL_ADDRESS_MASK.fetch_and(!c_bit_mask, Ordering::Relaxed);
let c_bit_mask = 1u64 << bit_position;
ENC_BIT_MASK.store(c_bit_mask, Ordering::Relaxed);
ENC_BIT_REVERSED.store(reversed, Ordering::Release);
}
Expand Down
12 changes: 5 additions & 7 deletions src/structures/paging/page_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use core::fmt;
use core::iter::Step;
use core::ops::{Index, IndexMut};
#[cfg(feature = "memory_encryption")]
use core::sync::atomic::{AtomicU64, Ordering};
use core::sync::atomic::Ordering;

use super::{PageSize, PhysFrame, Size4KiB};
use crate::addr::PhysAddr;
#[cfg(feature = "memory_encryption")]
use crate::structures::mem_encrypt::PHYSICAL_ADDRESS_MASK;

use bitflags::bitflags;
use dep_const_fn::const_fn;
Expand All @@ -23,10 +25,6 @@ pub enum FrameError {
HugeFrame,
}

/// The mask used to remove flags from a page table entry to obtain the physical address
#[cfg(feature = "memory_encryption")]
pub(crate) static PHYSICAL_ADDRESS_MASK: AtomicU64 = AtomicU64::new(0x000f_ffff_ffff_f000u64);

/// A 64-bit page table entry.
#[derive(Clone)]
#[repr(transparent)]
Expand Down Expand Up @@ -109,13 +107,13 @@ impl PageTableEntry {
#[inline(always)]
#[cfg(not(feature = "memory_encryption"))]
const fn physical_address_mask() -> u64 {
0x000f_ffff_ffff_f000u64
0x000f_ffff_ffff_f000
}

#[inline(always)]
#[cfg(feature = "memory_encryption")]
fn physical_address_mask() -> u64 {
PHYSICAL_ADDRESS_MASK.load(Ordering::Relaxed)
PHYSICAL_ADDRESS_MASK.load(Ordering::Relaxed) & !0xfff
}
}

Expand Down
Loading