islet_rmm/rmi/realm/
mod.rs1pub mod params;
2pub use self::params::Params;
3use super::error::Error;
4use crate::event::RmiHandle;
5use crate::granule::GRANULE_SIZE;
6use crate::granule::{set_granule, GranuleState};
7use crate::host;
8use crate::listen;
9use crate::measurement::{HashContext, MEASUREMENTS_SLOT_RIM};
10use crate::realm::mm::stage2_translation::Stage2Translation;
11use crate::realm::mm::IPATranslation;
12use crate::realm::rd::State;
13use crate::realm::rd::{insert_rtt, Rd};
14use crate::realm::registry::{remove, VMID_SET};
15use crate::rmi::{self, metadata::IsletRealmMetadata};
16use crate::{get_granule, get_granule_if};
17
18use alloc::boxed::Box;
19use alloc::sync::Arc;
20use spin::mutex::Mutex;
21
22extern crate alloc;
23
24pub fn set_event_handler(rmi: &mut RmiHandle) {
25 #[cfg(any(not(kani), feature = "mc_rmi_realm_activate"))]
26 listen!(rmi, rmi::REALM_ACTIVATE, |arg, _, _| {
27 let rd = arg[0];
28 let mut rd_granule = get_granule_if!(rd, GranuleState::RD)?;
29 let mut rd = rd_granule.content_mut::<Rd>()?;
30
31 if let Some(meta) = rd.metadata() {
32 debug!("Realm metadata is in use!");
33 let metadata_granule = get_granule_if!(meta, GranuleState::Metadata)?;
34 let metadata_obj = metadata_granule.content::<IsletRealmMetadata>()?;
35
36 if !metadata_obj.equal_rd_rim(&rd.measurements[MEASUREMENTS_SLOT_RIM]) {
37 error!("Calculated rim and those read from metadata are not the same!");
38 return Err(Error::RmiErrorRealm(0));
39 }
40
41 if !metadata_obj.equal_rd_hash_algo(rd.hash_algo()) {
42 error!("Provided measurement hash algorithm and metadata hash algorithm are different!");
43 return Err(Error::RmiErrorRealm(0));
44 }
45 }
46
47 if !rd.at_state(State::New) {
48 return Err(Error::RmiErrorRealm(0));
49 }
50
51 rd.set_state(State::Active);
52 Ok(())
53 });
54
55 #[cfg(not(kani))]
56 listen!(rmi, rmi::REALM_CREATE, |arg, _, rmm| {
57 let rd = arg[0];
58 let params_ptr = arg[1];
59
60 if rd == params_ptr {
61 return Err(Error::RmiErrorInput);
62 }
63
64 let mut rd_granule = get_granule_if!(rd, GranuleState::Delegated)?;
65 let mut rd_obj = rd_granule.content_mut::<Rd>()?;
66 #[cfg(not(kani))]
67 rmm.page_table.map(rd, true);
69
70 rmm.page_table.map(params_ptr, false);
71 let params = host::copy_from::<Params>(params_ptr).ok_or(Error::RmiErrorInput)?;
72 rmm.page_table.unmap(params_ptr);
73 params.verify_compliance(rd)?;
74
75 for i in 0..params.rtt_num_start as usize {
76 let rtt = params.rtt_base as usize + i * GRANULE_SIZE;
77 let _ = get_granule_if!(rtt, GranuleState::Delegated)?;
78 rmm.page_table.map(rtt, true);
81 }
82
83 create_realm(params.vmid as usize).map(|_| {
85 let s2 = Box::new(Stage2Translation::new(
86 params.rtt_base as usize,
87 params.rtt_level_start as usize,
88 params.rtt_num_start as usize,
89 )) as Box<dyn IPATranslation>;
90
91 insert_rtt(params.vmid as usize, Arc::new(Mutex::new(s2)));
92
93 rd_obj.init(
94 params.vmid,
95 params.rtt_base as usize,
96 params.rtt_num_start as usize,
97 params.ipa_bits(),
98 params.rtt_level_start as isize,
99 params.rpv,
100 params.sve_en(),
101 params.sve_vl as u64,
102 params.pmu_en(),
103 params.pmu_num_ctrs as usize,
104 )
105 })?;
106
107 let rtt_base = rd_obj.rtt_base();
108 rd_obj.set_hash_algo(params.hash_algo);
109
110 #[cfg(not(kani))]
111 HashContext::new(&mut rd_obj)?.measure_realm_create(¶ms)?;
113
114 let mut epilogue = move || {
115 for i in 0..params.rtt_num_start as usize {
116 let rtt = rtt_base + i * GRANULE_SIZE;
117 let mut rtt_granule = get_granule_if!(rtt, GranuleState::Delegated)?;
118 set_granule(&mut rtt_granule, GranuleState::RTT)?;
119 }
120 set_granule(&mut rd_granule, GranuleState::RD)
121 };
122
123 epilogue().inspect_err(|_| {
124 #[cfg(not(kani))]
125 rmm.page_table.unmap(rd);
127 remove(params.vmid as usize).expect("Realm should be created before.");
128 })
129 });
130
131 #[cfg(any(not(kani), feature = "mc_rmi_rec_aux_count"))]
132 listen!(rmi, rmi::REC_AUX_COUNT, |arg, ret, _| {
133 let _ = get_granule_if!(arg[0], GranuleState::RD)?;
134 ret[1] = rmi::MAX_REC_AUX_GRANULES;
135 Ok(())
136 });
137
138 #[cfg(any(not(kani), feature = "mc_rmi_realm_destroy"))]
139 listen!(rmi, rmi::REALM_DESTROY, |arg, _ret, rmm| {
140 let mut rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
142 if rd_granule.num_children() > 0 {
143 return Err(Error::RmiErrorRealm(0));
144 }
145 let mut rd = rd_granule.content::<Rd>()?;
146 let vmid = rd.id();
147 let rtt_base = rd.rtt_base();
148
149 if let Some(meta) = rd.metadata() {
150 let mut meta_granule = get_granule_if!(meta, GranuleState::Metadata)?;
151 set_granule(&mut meta_granule, GranuleState::Delegated)?;
152 rd.set_metadata(None);
153 rmm.page_table.unmap(meta);
154 }
155
156 #[cfg(kani)]
157 kani::assume(crate::granule::validate_addr(rtt_base));
159
160 #[cfg(not(feature = "gst_page_table"))]
161 {
162 #[cfg(not(kani))]
163 for i in 0..rd.rtt_num_start() {
164 let rtt = rtt_base + i * GRANULE_SIZE;
165
166 let rtt_granule = get_granule!(rtt)?;
167 if rtt_granule.num_children() > 0 {
168 return Err(Error::RmiErrorRealm(0));
169 }
170 }
171 #[cfg(kani)]
172 {
173 let rtt_granule = get_granule!(rtt_base)?;
176 if rtt_granule.num_children() > 0 {
177 return Err(Error::RmiErrorRealm(0));
178 }
179 }
180 }
181
182 #[cfg(not(kani))]
183 for i in 0..rd.rtt_num_start() {
184 let rtt = rtt_base + i * GRANULE_SIZE;
185 let mut rtt_granule = get_granule!(rtt)?;
186 set_granule(&mut rtt_granule, GranuleState::Delegated)?;
187 }
188 #[cfg(kani)]
189 {
190 let mut rtt_granule = get_granule!(rtt_base)?;
193 set_granule(&mut rtt_granule, GranuleState::Delegated)?;
194 }
195
196 set_granule(&mut rd_granule, GranuleState::Delegated)?;
198 #[cfg(not(kani))]
199 rmm.page_table.unmap(arg[0]);
201 #[cfg(not(kani))]
203 remove(vmid)?;
204
205 Ok(())
206 });
207
208 listen!(rmi, rmi::ISLET_REALM_SET_METADATA, |arg, _ret, rmm| {
215 let rd_addr = arg[0];
216 let mdg_addr = arg[1];
217 let meta_ptr = arg[2];
218
219 rmm.page_table.map(meta_ptr, false);
220 let realm_metadata: Box<IsletRealmMetadata> =
221 Box::new(host::copy_from(meta_ptr).ok_or(Error::RmiErrorInput)?);
222 rmm.page_table.unmap(meta_ptr);
223 realm_metadata.dump();
224
225 if let Err(e) = realm_metadata.verify_signature() {
226 error!("Verification of realm metadata signature has failed");
227 Err(e)?;
228 }
229
230 if let Err(e) = realm_metadata.validate() {
231 error!("The content of realm metadata is not valid");
232 Err(e)?;
233 }
234
235 let mut rd_granule = get_granule_if!(rd_addr, GranuleState::RD)?;
236 let mut rd = rd_granule.content_mut::<Rd>()?;
237
238 if !rd.at_state(State::New) {
239 error!("Metadata can only be set for new realms");
240 Err(Error::RmiErrorRealm(0))?;
241 }
242
243 if rd.metadata().is_some() {
244 error!("Metadata is already set");
245 Err(Error::RmiErrorRealm(0))?;
246 }
247
248 rmm.page_table.map(mdg_addr, true);
249 let mut metadata_granule = get_granule_if!(mdg_addr, GranuleState::Delegated)?;
250 let mut metadata_obj = metadata_granule.content_mut::<IsletRealmMetadata>()?;
251
252 *metadata_obj = *realm_metadata.clone();
253 set_granule(&mut metadata_granule, GranuleState::Metadata)?;
254 rd.set_metadata(Some(mdg_addr));
255
256 Ok(())
257 });
258}
259
260fn create_realm(vmid: usize) -> Result<(), Error> {
261 let mut vmid_set = VMID_SET.lock();
262 if vmid_set.contains(&vmid) {
263 return Err(Error::RmiErrorInput);
264 } else {
265 vmid_set.insert(vmid);
266 };
267
268 Ok(())
269}
270
271#[cfg(test)]
272mod test {
273 use crate::realm::rd::{Rd, State};
274 use crate::rmi::{ERROR_INPUT, REALM_ACTIVATE, REALM_CREATE, SUCCESS};
275 use crate::test_utils::*;
276
277 use alloc::vec;
278
279 #[test]
280 fn rmi_realm_create_positive() {
281 let rd = realm_create();
282
283 let ret = rmi::<REALM_ACTIVATE>(&[rd]);
284 assert_eq!(ret[0], SUCCESS);
285
286 unsafe {
287 let rd_obj = &*(rd as *const Rd);
288 assert!(rd_obj.at_state(State::Active));
289 };
290
291 realm_destroy(rd);
292
293 miri_teardown();
294 }
295
296 #[test]
331 fn rmi_realm_create_negative() {
332 let test_data = vec![
333 ((0x88300000 as usize, 0x88303001 as usize), ERROR_INPUT),
335 ];
336
337 for (input, output) in test_data {
339 let ret = rmi::<REALM_CREATE>(&[input.0, input.1, 0]);
340 assert_eq!(output, ret[0]);
341 }
342 }
343}