|
| 1 | +//! Provides glue to support memory encryption features of some CPUs. |
| 2 | +//! |
| 3 | +//! Memory encryption typically relies on using a physical address bit in the page table entry to |
| 4 | +//! mark a page as encrypted/decrypted. This module provides a function that, given the position and |
| 5 | +//! type of that physical address bit, updates the dynamic page-table flags structure to ensure that |
| 6 | +//! the flag is treated properly and not returned as part of the physical address. |
| 7 | +
|
| 8 | +use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; |
| 9 | + |
| 10 | +use crate::structures::paging::page_table::PHYSICAL_ADDRESS_MASK; |
| 11 | +use crate::structures::paging::PageTableFlags; |
| 12 | + |
| 13 | +/// Position of the encryption (C/S) bit in the physical address |
| 14 | +pub(crate) static ENC_BIT_MASK: AtomicU64 = AtomicU64::new(0); |
| 15 | + |
| 16 | +/// Is the encryption bit reversed (i.e. its presence denote that the page is _decrypted_ rather |
| 17 | +/// than encrypted) |
| 18 | +static ENC_BIT_REVERSED: AtomicBool = AtomicBool::new(false); |
| 19 | + |
| 20 | +/// Defines the configuration for memory encryption |
| 21 | +#[derive(Debug)] |
| 22 | +pub enum MemoryEncryptionConfiguration { |
| 23 | + /// Defines that a memory page should be accessed encrypted if this bit of its physical address |
| 24 | + /// is set in the page table entry. |
| 25 | + /// |
| 26 | + /// Use this for AMD Secure Memory Encryption (AMD-SME) and Secure Encrypted Virtualization (SEV) |
| 27 | + EncryptedBit(u8), |
| 28 | + |
| 29 | + /// Defines that a memory page should be accessed decrypted if this bit of its physical address |
| 30 | + /// is set in the page table entry. |
| 31 | + /// |
| 32 | + /// Use this for Intel Trust Domain Extension (Intel TDX) |
| 33 | + SharedBit(u8), |
| 34 | +} |
| 35 | + |
| 36 | +/// Enable memory encryption by defining the physical address bit that is used to mark a page |
| 37 | +/// encrypted (or shared) in a page table entry |
| 38 | +/// |
| 39 | +/// # Safety |
| 40 | +/// Caller must make sure that any existing page table entry is discarded or adapted to take this |
| 41 | +/// bit into consideration. |
| 42 | +/// The configuration provided by caller must be correct, otherwise physical address bits will |
| 43 | +/// incorrectly be considered as page table flags. |
| 44 | +pub unsafe fn enable_memory_encryption(configuration: MemoryEncryptionConfiguration) { |
| 45 | + let (bit_position, reversed) = match configuration { |
| 46 | + MemoryEncryptionConfiguration::EncryptedBit(pos) => (pos, false), |
| 47 | + MemoryEncryptionConfiguration::SharedBit(pos) => (pos, true), |
| 48 | + }; |
| 49 | + |
| 50 | + let c_bit_mask = 1u64 << bit_position; |
| 51 | + |
| 52 | + PHYSICAL_ADDRESS_MASK.fetch_and(!c_bit_mask, Ordering::Relaxed); |
| 53 | + ENC_BIT_MASK.store(c_bit_mask, Ordering::Relaxed); |
| 54 | + ENC_BIT_REVERSED.store(reversed, Ordering::Release); |
| 55 | +} |
| 56 | + |
| 57 | +impl PageTableFlags { |
| 58 | + #[inline] |
| 59 | + fn enc_bit_flag() -> Option<PageTableFlags> { |
| 60 | + let bit_mask = ENC_BIT_MASK.load(Ordering::Relaxed); |
| 61 | + |
| 62 | + if bit_mask > 0 { |
| 63 | + Some(PageTableFlags::from_bits_retain(bit_mask)) |
| 64 | + } else { |
| 65 | + None |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + /// Marks the page for encryption in the page table entry. |
| 70 | + /// |
| 71 | + /// # Panics |
| 72 | + /// |
| 73 | + /// Panics if memory encryption has not been previously configured by calling [`enable_memory_encryption`] |
| 74 | + pub fn set_encrypted(&mut self, encrypted: bool) { |
| 75 | + let flag = Self::enc_bit_flag().expect("memory encryption is not enabled"); |
| 76 | + self.set(flag, encrypted ^ ENC_BIT_REVERSED.load(Ordering::Relaxed)); |
| 77 | + } |
| 78 | + |
| 79 | + /// Checks if memory encryption is enabled on the page |
| 80 | + pub fn is_encrypted(&self) -> bool { |
| 81 | + if let Some(c_bit_flag) = Self::enc_bit_flag() { |
| 82 | + self.contains(c_bit_flag) ^ ENC_BIT_REVERSED.load(Ordering::Relaxed) |
| 83 | + } else { |
| 84 | + false |
| 85 | + } |
| 86 | + } |
| 87 | +} |
0 commit comments