Skip to main content

ostd/mm/
page_prop.rs

1// SPDX-License-Identifier: MPL-2.0
2
3//! Definitions of page mapping properties.
4
5use core::fmt::Debug;
6
7use bitflags::bitflags;
8
9/// The property of a mapped virtual memory page.
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct PageProperty {
12    /// The flags associated with the page,
13    pub flags: PageFlags,
14    /// The cache policy for the page.
15    pub cache: CachePolicy,
16    pub(crate) priv_flags: PrivilegedPageFlags,
17}
18
19impl PageProperty {
20    /// Creates a new `PageProperty` with the given flags and cache policy for the user.
21    pub fn new_user(flags: PageFlags, cache: CachePolicy) -> Self {
22        Self {
23            flags,
24            cache,
25            priv_flags: PrivilegedPageFlags::USER,
26        }
27    }
28
29    /// Creates a new `PageProperty` with the given flags and cache policy for the guest.
30    pub fn new_guest(flags: PageFlags, cache: CachePolicy) -> Self {
31        // Use `new_user` to prevent OSTD users from obtaining a kernel page
32        // property. EPT preserves the USER flag as software metadata.
33        Self::new_user(flags, cache)
34    }
35}
36
37// TODO: Make it more abstract when supporting other architectures.
38/// A type to control the cacheability of the main memory.
39///
40/// The type currently follows the definition as defined by the AMD64 manual.
41#[derive(Clone, Copy, Debug, Eq, PartialEq)]
42pub enum CachePolicy {
43    /// Uncacheable (UC).
44    ///
45    /// Reads from, and writes to, UC memory are not cacheable.
46    /// Reads from UC memory cannot be speculative.
47    /// Write-combining to UC memory is not allowed.
48    /// Reads from or writes to UC memory cause the write buffers to be written to memory
49    /// and be invalidated prior to the access to UC memory.
50    ///
51    /// The UC memory type is useful for memory-mapped I/O devices
52    /// where strict ordering of reads and writes is important.
53    Uncacheable,
54    /// Write-Combining (WC).
55    ///
56    /// Reads from, and writes to, WC memory are not cacheable.
57    /// Reads from WC memory can be speculative.
58    ///
59    /// Writes to this memory type can be combined internally by the processor
60    /// and written to memory as a single write operation to reduce memory accesses.
61    ///
62    /// The WC memory type is useful for graphics-display memory buffers
63    /// where the order of writes is not important.
64    WriteCombining,
65    /// Write-Protect (WP).
66    ///
67    /// Reads from WP memory are cacheable and allocate cache lines on a read miss.
68    /// Reads from WP memory can be speculative.
69    ///
70    /// Writes to WP memory that hit in the cache do not update the cache.
71    /// Instead, all writes update memory (write to memory),
72    /// and writes that hit in the cache invalidate the cache line.
73    /// Write buffering of WP memory is allowed.
74    ///
75    /// The WP memory type is useful for shadowed-ROM memory
76    /// where updates must be immediately visible to all devices that read the shadow locations.
77    WriteProtected,
78    /// Writethrough (WT).
79    ///
80    /// Reads from WT memory are cacheable and allocate cache lines on a read miss.
81    /// Reads from WT memory can be speculative.
82    ///
83    /// All writes to WT memory update main memory,
84    /// and writes that hit in the cache update the cache line.
85    /// Writes that miss the cache do not allocate a cache line.
86    /// Write buffering of WT memory is allowed.
87    Writethrough,
88    /// Writeback (WB).
89    ///
90    /// The WB memory is the "normal" memory. See detailed descriptions in the manual.
91    ///
92    /// This type of memory provides the highest-possible performance
93    /// and is useful for most software and data stored in system memory (DRAM).
94    Writeback,
95}
96
97bitflags! {
98    /// Page protection permissions and access status.
99    pub struct PageFlags: u8 {
100        /// Readable.
101        const R = 0b00000001;
102        /// Writable.
103        const W = 0b00000010;
104        /// Executable.
105        const X = 0b00000100;
106        /// Readable + writable.
107        const RW = Self::R.bits | Self::W.bits;
108        /// Readable + executable.
109        const RX = Self::R.bits | Self::X.bits;
110        /// Readable + writable + executable.
111        const RWX = Self::R.bits | Self::W.bits | Self::X.bits;
112
113        /// Has the memory page been read or written.
114        const ACCESSED  = 0b00001000;
115        /// Has the memory page been written.
116        const DIRTY     = 0b00010000;
117
118        /// The second bit available for software use.
119        const AVAIL2    = 0b10000000;
120    }
121}
122
123bitflags! {
124    /// Page property that are only accessible in OSTD.
125    pub(crate) struct PrivilegedPageFlags: u8 {
126        /// Accessible from user mode.
127        const USER      = 0b00000001;
128        /// Global page that won't be evicted from TLB with normal TLB flush.
129        const GLOBAL    = 0b00000010;
130
131        /// The first bit available for software use.
132        /// This flag is reserved for OSTD to distinguish between tracked
133        /// mappings and untracked mappings in the page table.
134        const AVAIL1    = 0b01000000;
135
136        /// (TEE only) If the page is shared with the host.
137        /// Otherwise the page is ensured confidential and not visible outside the guest.
138        #[cfg(all(target_arch = "x86_64", feature = "cvm_guest"))]
139        const SHARED    = 0b10000000;
140    }
141}
142
143bitflags! {
144    /// Flags that can be stored on intermediate page table entries.
145    pub(crate) struct PageTableFlags: u8 {
146        /// The first bit available for software use.
147        const AVAIL1    = 0b01000000;
148        /// The second bit available for software use.
149        const AVAIL2    = 0b10000000;
150    }
151}