|
5 | 5 | //! dynamic page-table flags structure to ensure that the flag is treated properly and not
|
6 | 6 | //! returned as part of the physical address.
|
7 | 7 |
|
8 |
| -use core::sync::atomic::{AtomicU64, Ordering}; |
| 8 | +use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; |
9 | 9 |
|
10 | 10 | use crate::structures::paging::page_table::PHYSICAL_ADDRESS_MASK;
|
11 | 11 | use crate::structures::paging::PageTableFlags;
|
12 | 12 |
|
13 |
| -static C_BIT_MASK: AtomicU64 = AtomicU64::new(0); |
| 13 | +/// Position of the encryption (C/S) bit in the physical address |
| 14 | +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 | +pub enum MemoryEncryptionConfiguration { |
| 21 | + /// Defines that a memory page should be accessed encrypted if this bit of its physical address |
| 22 | + /// is set in the page table entry. |
| 23 | + /// |
| 24 | + /// Use this for AMD Secure Memory Encryption (AMD-SME) and Secure Encrypted Virtualization (SEV) |
| 25 | + EncryptBit(u8), |
| 26 | + |
| 27 | + /// Defines that a memory page should be accessed decrypted if this bit of its physical address |
| 28 | + /// is set in the page table entry. |
| 29 | + /// |
| 30 | + /// Use this for Intel Trust Domain Extension (Intel TDX) |
| 31 | + ShareBit(u8), |
| 32 | +} |
14 | 33 |
|
15 | 34 | /// Enable memory encryption by defining the physical address bit that is used to mark a page
|
16 |
| -/// encrypted in a page table entry |
17 |
| -pub fn define_encryption_bit(bit_position: u64) { |
| 35 | +/// encrypted (or shared) in a page table entry |
| 36 | +pub unsafe fn enable_memory_encryption(configuration: MemoryEncryptionConfiguration) { |
| 37 | + let (bit_position, reversed) = match configuration { |
| 38 | + MemoryEncryptionConfiguration::EncryptBit(pos) => (pos as u64, false), |
| 39 | + MemoryEncryptionConfiguration::ShareBit(pos) => (pos as u64, true), |
| 40 | + }; |
| 41 | + |
18 | 42 | let c_bit_mask = 1u64 << bit_position;
|
19 | 43 |
|
20 |
| - PHYSICAL_ADDRESS_MASK.fetch_and(!c_bit_mask, Ordering::AcqRel); |
21 |
| - C_BIT_MASK.store(c_bit_mask, Ordering::Relaxed); |
| 44 | + PHYSICAL_ADDRESS_MASK.fetch_and(!c_bit_mask, Ordering::Relaxed); |
| 45 | + ENC_BIT_MASK.store(c_bit_mask, Ordering::Relaxed); |
| 46 | + ENC_BIT_REVERSED.store(reversed, Ordering::Release); |
22 | 47 | }
|
23 | 48 |
|
24 | 49 | impl PageTableFlags {
|
25 | 50 | #[inline]
|
26 |
| - fn c_bit_mask() -> PageTableFlags { |
27 |
| - let bit_mask = C_BIT_MASK.load(Ordering::Relaxed); |
28 |
| - assert_ne!(bit_mask, 0, "C-bit is not set"); |
29 |
| - PageTableFlags::from_bits_retain(bit_mask) |
| 51 | + fn c_bit_flag() -> Option<PageTableFlags> { |
| 52 | + let bit_mask = ENC_BIT_MASK.load(Ordering::Relaxed); |
| 53 | + |
| 54 | + if bit_mask > 0 { |
| 55 | + Some(PageTableFlags::from_bits_retain(bit_mask)) |
| 56 | + } else { |
| 57 | + None |
| 58 | + } |
30 | 59 | }
|
31 | 60 |
|
32 |
| - /// Sets the encryption bit on the page table entry. |
| 61 | + /// Marks the page for encryption in the page table entry. |
33 | 62 | ///
|
34 |
| - /// Requires memory encryption to be enabled, or this will panic. |
| 63 | + /// # Panics |
| 64 | + /// |
| 65 | + /// Panics if memory encryption has not been previously configured by calling [`enable_memory_encryption`] |
35 | 66 | pub fn set_encrypted(&mut self, encrypted: bool) {
|
36 |
| - self.set(Self::c_bit_mask(), encrypted); |
| 67 | + let flag = Self::c_bit_flag().expect("memory encryption is not enabled"); |
| 68 | + self.set(flag, encrypted ^ ENC_BIT_REVERSED.load(Ordering::Relaxed)); |
37 | 69 | }
|
38 | 70 |
|
39 |
| - /// Checks if the encryption bit is set on the page table entry. |
40 |
| - /// |
41 |
| - /// Requires memory encryption to be enabled, or this will panic. |
| 71 | + /// Checks if memory encryption is enabled on the page |
42 | 72 | pub fn is_encrypted(&self) -> bool {
|
43 |
| - self.contains(Self::c_bit_mask()) |
| 73 | + if let Some(c_bit_flag) = Self::c_bit_flag() { |
| 74 | + self.contains(c_bit_flag) ^ ENC_BIT_REVERSED.load(Ordering::Relaxed) |
| 75 | + } else { |
| 76 | + false |
| 77 | + } |
44 | 78 | }
|
45 | 79 | }
|
0 commit comments