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}