Skip to main content

islet_rmm/realm/
rd.rs

1use vmsa::guard::Content;
2
3use crate::measurement::{Measurement, MEASUREMENTS_SLOT_NR};
4use crate::realm::mm::IPATranslation;
5use crate::simd::SimdConfig;
6use alloc::boxed::Box;
7use alloc::collections::btree_map::BTreeMap;
8use alloc::sync::Arc;
9use spin::mutex::Mutex;
10
11pub const RPV_SIZE: usize = 64;
12
13lazy_static! {
14    static ref RTT_TABLES: Mutex<BTreeMap<usize, Arc<Mutex<Box<dyn IPATranslation>>>>> = {
15        let m = BTreeMap::new();
16        Mutex::new(m)
17    };
18}
19
20pub fn insert_rtt(id: usize, table: Arc<Mutex<Box<dyn IPATranslation>>>) {
21    RTT_TABLES.lock().insert(id, table);
22}
23
24#[derive(Debug)]
25pub struct Rd {
26    vmid: u16,
27    state: State,
28    rtt_base: usize,
29    rtt_num_start: usize,
30    ipa_bits: usize,
31    rec_index: usize,
32    s2_starting_level: isize,
33    hash_algo: u8,
34    rpv: [u8; RPV_SIZE],
35    num_recs: usize,
36    pub measurements: [Measurement; MEASUREMENTS_SLOT_NR],
37    pub vcpu_index: usize,
38    metadata: Option<usize>,
39    simd_cfg: SimdConfig,
40    pmu_en: bool,
41    pmu_num_ctrs: usize,
42}
43
44impl Rd {
45    #[allow(clippy::too_many_arguments)]
46    pub fn init(
47        &mut self,
48        vmid: u16,
49        rtt_base: usize,
50        rtt_num_start: usize,
51        ipa_bits: usize,
52        s2_starting_level: isize,
53        rpv: [u8; 64],
54        sve_en: bool,
55        sve_vl: u64,
56        pmu_en: bool,
57        pmu_num_ctrs: usize,
58    ) {
59        self.vmid = vmid;
60        self.state = State::New;
61        self.rtt_base = rtt_base;
62        self.rtt_num_start = rtt_num_start;
63        self.ipa_bits = ipa_bits;
64        self.rec_index = 0;
65        self.s2_starting_level = s2_starting_level;
66        self.measurements = [Measurement::empty(); MEASUREMENTS_SLOT_NR];
67        self.vcpu_index = 0;
68        self.rpv.copy_from_slice(rpv.as_slice());
69        self.metadata = None;
70        self.simd_cfg.sve_en = sve_en;
71        self.pmu_en = pmu_en;
72        if sve_en {
73            self.simd_cfg.sve_vq = sve_vl;
74        }
75        if pmu_en {
76            self.pmu_num_ctrs = pmu_num_ctrs;
77        }
78        self.num_recs = 0;
79    }
80
81    pub fn id(&self) -> usize {
82        self.vmid as usize
83    }
84
85    pub fn num_recs(&self) -> usize {
86        self.num_recs
87    }
88
89    pub fn s2_table(&self) -> Arc<Mutex<Box<dyn IPATranslation>>> {
90        Arc::clone(RTT_TABLES.lock().get_mut(&self.id()).unwrap())
91    }
92
93    pub fn state(&self) -> State {
94        self.state
95    }
96
97    pub fn set_state(&mut self, state: State) {
98        self.state = state;
99    }
100
101    pub fn at_state(&self, compared: State) -> bool {
102        self.state == compared
103    }
104
105    pub fn rtt_base(&self) -> usize {
106        self.rtt_base
107    }
108
109    pub fn rtt_num_start(&self) -> usize {
110        self.rtt_num_start
111    }
112
113    pub fn ipa_bits(&self) -> usize {
114        self.ipa_bits
115    }
116
117    pub fn pmu_config(&self) -> (bool, usize) {
118        (self.pmu_en, self.pmu_num_ctrs)
119    }
120
121    pub fn rec_index(&self) -> usize {
122        self.rec_index
123    }
124
125    pub fn s2_starting_level(&self) -> isize {
126        self.s2_starting_level
127    }
128
129    pub fn inc_recs(&mut self) {
130        self.num_recs += 1;
131        self.rec_index += 1;
132    }
133
134    pub fn dec_recs(&mut self) {
135        self.num_recs -= 1;
136    }
137
138    pub fn ipa_size(&self) -> usize {
139        1 << self.ipa_bits
140    }
141
142    pub fn par_size(&self) -> usize {
143        self.ipa_size() / 2
144    }
145
146    pub fn addr_in_par(&self, ipa: usize) -> bool {
147        ipa < self.par_size()
148    }
149
150    pub fn hash_algo(&self) -> u8 {
151        self.hash_algo
152    }
153
154    pub fn set_hash_algo(&mut self, alg: u8) {
155        self.hash_algo = alg;
156    }
157
158    pub fn personalization_value(&self) -> &[u8] {
159        self.rpv.as_slice()
160    }
161
162    pub fn metadata(&self) -> Option<usize> {
163        self.metadata
164    }
165
166    pub fn set_metadata(&mut self, metadata: Option<usize>) {
167        self.metadata = metadata
168    }
169
170    pub fn simd_config(&self) -> &SimdConfig {
171        &self.simd_cfg
172    }
173}
174
175impl Content for Rd {}
176
177impl safe_abstraction::raw_ptr::RawPtr for Rd {}
178
179impl safe_abstraction::raw_ptr::SafetyChecked for Rd {}
180
181impl safe_abstraction::raw_ptr::SafetyAssured for Rd {
182    fn is_initialized(&self) -> bool {
183        // The initialization of this memory is guaranteed
184        // according to the RMM Specification A2.2.4 Granule Wiping.
185        // This instance belongs to a RD Granule and has been initialized.
186        true
187    }
188
189    fn verify_ownership(&self) -> bool {
190        // The ownership of this instance is exclusively ensured by the RMM.
191        // under the following conditions:
192        //
193        // 1. A lock on the given address is obtained using the `get_granule*` macros.
194        // 2. The instance is converted from a raw pointer through the `content*` functions.
195        // 3. The instance is accessed only within the lock scope.
196        //
197        // Ownership verification is guaranteed because these criteria are satisfied
198        // in all cases where this object is accessed.
199        true
200    }
201}
202
203#[derive(Debug, Clone, Copy, PartialEq)]
204pub enum State {
205    Null,
206    New,
207    Active,
208    SystemOff,
209}