1extern crate alloc;
2
3use crate::event::RmiHandle;
4use crate::granule::{
5 is_granule_aligned, is_not_in_realm, set_granule, GranuleState, GRANULE_SIZE,
6};
7use crate::host;
8use crate::host::DataPage;
9use crate::listen;
10use crate::measurement::HashContext;
11use crate::realm::mm::rtt;
12use crate::realm::mm::rtt::{RTT_MIN_BLOCK_LEVEL, RTT_PAGE_LEVEL};
13use crate::realm::mm::stage2_tte::{level_mask, S2TTE};
14use crate::realm::rd::{Rd, State};
15use crate::rec::Rec;
16use crate::rmi;
17use crate::rmi::error::Error;
18#[cfg(not(feature = "gst_page_table"))]
19use crate::{get_granule, get_granule_if};
20#[cfg(feature = "gst_page_table")]
21use crate::{get_granule, get_granule_if, set_state_and_get_granule};
22
23fn is_valid_rtt_cmd(rd: &Rd, ipa: usize, level: usize) -> bool {
24 if level > RTT_PAGE_LEVEL {
25 return false;
26 }
27
28 if ipa >= rd.ipa_size() {
29 return false;
30 }
31 let mask = level_mask(level).unwrap_or(0);
32 if ipa & mask as usize != ipa {
33 return false;
34 }
35 true
36}
37
38pub fn set_event_handler(rmi: &mut RmiHandle) {
39 listen!(rmi, rmi::RTT_CREATE, |arg, _ret, rmm| {
40 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
41 let rtt_addr = arg[1];
42 let rd = rd_granule.content::<Rd>()?;
43 let ipa = arg[2];
44 let level = arg[3];
45
46 let min_level = rd.s2_starting_level() as usize + 1;
47
48 if (level < min_level) || (level > RTT_PAGE_LEVEL) || !is_valid_rtt_cmd(&rd, ipa, level - 1)
49 {
50 return Err(Error::RmiErrorInput);
51 }
52 if rtt_addr == arg[0] {
53 return Err(Error::RmiErrorInput);
54 }
55 let mut rtt_granule = get_granule_if!(rtt_addr, GranuleState::Delegated)?;
56
57 #[cfg(not(kani))]
60 rmm.page_table.map(rtt_addr, true);
61 rtt::create(&rd, rtt_addr, ipa, level)?;
62 set_granule(&mut rtt_granule, GranuleState::RTT)?;
63 Ok(())
64 });
65
66 listen!(rmi, rmi::RTT_DESTROY, |arg, ret, _rmm| {
67 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
68 let rd = rd_granule.content::<Rd>()?;
69 let ipa = arg[1];
70 let level = arg[2];
71
72 let min_level = rd.s2_starting_level() as usize + 1;
73
74 if (level < min_level) || (level > RTT_PAGE_LEVEL) || !is_valid_rtt_cmd(&rd, ipa, level - 1)
75 {
76 return Err(Error::RmiErrorInput);
77 }
78 let (ipa, walk_top) = rtt::destroy(&rd, ipa, level, |t| {
79 ret[2] = t;
80 })?;
81 ret[1] = ipa;
82 ret[2] = walk_top;
83 Ok(())
84 });
85
86 listen!(rmi, rmi::RTT_INIT_RIPAS, |arg, ret, _rmm| {
87 let mut rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
88 let mut rd = rd_granule.content_mut::<Rd>()?;
89 let base = arg[1];
90 let top = arg[2];
91
92 if rd.state() != State::New {
93 return Err(Error::RmiErrorRealm(0));
94 }
95
96 if top <= base {
97 return Err(Error::RmiErrorInput);
98 }
99
100 if !is_valid_rtt_cmd(&rd, base, RTT_PAGE_LEVEL)
101 || !is_valid_rtt_cmd(&rd, top, RTT_PAGE_LEVEL)
102 || !rd.addr_in_par(base)
103 || !rd.addr_in_par(top - GRANULE_SIZE)
104 {
105 return Err(Error::RmiErrorInput);
106 }
107
108 let out_top = rtt::init_ripas(&mut rd, base, top)?;
109 ret[1] = out_top; Ok(())
112 });
113
114 listen!(rmi, rmi::RTT_SET_RIPAS, |arg, ret, _rmm| {
115 let base = arg[2];
116 let top = arg[3];
117
118 if arg[0] == arg[1] {
119 warn!("Granules of RD and REC shouldn't be identical");
120 return Err(Error::RmiErrorInput);
121 }
122 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
123 let rd = rd_granule.content::<Rd>()?;
124 let mut rec_granule = get_granule_if!(arg[1], GranuleState::Rec)?;
125 let mut rec = rec_granule.content_mut::<Rec<'_>>()?;
126 if rec.realmid()? != rd.id() {
127 warn!("RD:{:X} doesn't own REC:{:X}", arg[0], arg[1]);
128 return Err(Error::RmiErrorRec);
129 }
130
131 if rec.ripas_addr() != base as u64 || rec.ripas_end() < top as u64 {
132 return Err(Error::RmiErrorInput);
133 }
134
135 if !is_granule_aligned(base)
136 || !is_granule_aligned(top)
137 || !rd.addr_in_par(base)
138 || top.checked_sub(GRANULE_SIZE).is_none()
139 || !rd.addr_in_par(top - GRANULE_SIZE)
140 {
141 return Err(Error::RmiErrorInput);
142 }
143
144 let out_top = rtt::set_ripas(&rd, base, top, rec.ripas_state(), rec.ripas_flags())?;
145 ret[1] = out_top;
146 rec.set_ripas_addr(out_top as u64);
147 Ok(())
148 });
149
150 listen!(rmi, rmi::RTT_READ_ENTRY, |arg, ret, _rmm| {
151 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
152 let rd = rd_granule.content::<Rd>()?;
153 let ipa = arg[1];
154 let level = arg[2];
155 if !is_valid_rtt_cmd(&rd, ipa, level) {
156 return Err(Error::RmiErrorInput);
157 }
158
159 let res = rtt::read_entry(&rd, ipa, level)?;
160 ret[1..5].copy_from_slice(&res[0..4]);
161
162 Ok(())
163 });
164
165 listen!(rmi, rmi::DATA_CREATE, |arg, _ret, rmm| {
166 let rd = arg[0];
168 let target_pa = arg[1];
169 let ipa = arg[2];
170 let src_pa = arg[3];
171 let flags = arg[4];
172
173 if target_pa == rd || target_pa == src_pa || rd == src_pa {
174 return Err(Error::RmiErrorInput);
175 }
176
177 let mut rd_granule = get_granule_if!(rd, GranuleState::RD)?;
179 let mut rd = rd_granule.content_mut::<Rd>()?;
180
181 if !rd.at_state(State::New) {
184 return Err(Error::RmiErrorRealm(0));
185 }
186
187 validate_ipa(&rd, ipa)?;
188
189 if !is_not_in_realm(src_pa) {
190 return Err(Error::RmiErrorInput);
191 };
192
193 let mut target_page_granule = get_granule_if!(target_pa, GranuleState::Delegated)?;
195 let mut target_page = target_page_granule.content_mut::<DataPage>()?;
196 #[cfg(not(kani))]
197 rmm.page_table.map(target_pa, true);
199
200 #[cfg(not(kani))]
202 rmm.page_table.map(src_pa, false);
203 host::copy_to_obj::<DataPage>(src_pa, &mut target_page).ok_or(Error::RmiErrorInput)?;
204 #[cfg(not(kani))]
205 rmm.page_table.unmap(src_pa);
206
207 rtt::data_create(&rd, ipa, target_pa, false)?;
209
210 #[cfg(not(kani))]
211 HashContext::new(&mut rd)?.measure_data_granule(&target_page, ipa, flags)?;
213
214 set_granule(&mut target_page_granule, GranuleState::Data)?;
215 Ok(())
216 });
217
218 listen!(rmi, rmi::DATA_CREATE_UNKNOWN, |arg, _ret, rmm| {
219 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
221 let rd = rd_granule.content::<Rd>()?;
222
223 let target_pa = arg[1];
225 let ipa = arg[2];
226 if target_pa == arg[0] {
227 return Err(Error::RmiErrorInput);
228 }
229
230 validate_ipa(&rd, ipa)?;
231
232 let mut target_page_granule = get_granule_if!(target_pa, GranuleState::Delegated)?;
235 #[cfg(not(kani))]
236 rmm.page_table.map(target_pa, true);
238
239 rtt::data_create(&rd, ipa, target_pa, true)?;
241
242 set_granule(&mut target_page_granule, GranuleState::Data)?;
245 Ok(())
246 });
247
248 listen!(rmi, rmi::DATA_DESTROY, |arg, ret, _rmm| {
249 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
251 let rd = rd_granule.content::<Rd>()?;
252 let ipa = arg[1];
253
254 if !rd.addr_in_par(ipa) || !is_valid_rtt_cmd(&rd, ipa, RTT_PAGE_LEVEL) {
255 return Err(Error::RmiErrorInput);
256 }
257
258 let (pa, top) = rtt::data_destroy(&rd, ipa, |t| {
259 ret[2] = t;
260 })?;
261
262 #[cfg(feature = "gst_page_table")]
264 set_state_and_get_granule!(pa, GranuleState::Delegated)?;
265
266 #[cfg(not(feature = "gst_page_table"))]
267 {
268 let mut granule = get_granule!(pa)?;
269 set_granule(&mut granule, GranuleState::Delegated)?;
270 }
271
272 ret[1] = pa;
273 ret[2] = top;
274 Ok(())
275 });
276
277 listen!(rmi, rmi::RTT_MAP_UNPROTECTED, |arg, _ret, _rmm| {
279 let ipa = arg[1];
280 let level = arg[2];
281 let host_s2tte = arg[3];
282 let s2tte = S2TTE::from(host_s2tte);
283 if !s2tte.is_host_ns_valid(level) {
284 return Err(Error::RmiErrorInput);
285 }
286
287 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
289 let rd = rd_granule.content::<Rd>()?;
290
291 if (level < rd.s2_starting_level() as usize)
292 || (level < RTT_MIN_BLOCK_LEVEL)
293 || (level > RTT_PAGE_LEVEL)
294 || !is_valid_rtt_cmd(&rd, ipa, level)
295 {
296 return Err(Error::RmiErrorInput);
297 }
298
299 rtt::map_unprotected(&rd, ipa, level, host_s2tte)?;
300 Ok(())
301 });
302
303 listen!(rmi, rmi::RTT_UNMAP_UNPROTECTED, |arg, ret, _rmm| {
305 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
306 let rd = rd_granule.content::<Rd>()?;
307
308 let ipa = arg[1];
309
310 let level = arg[2];
311 if (level < rd.s2_starting_level() as usize)
312 || (level < RTT_MIN_BLOCK_LEVEL)
313 || (level > RTT_PAGE_LEVEL)
314 || !is_valid_rtt_cmd(&rd, ipa, level)
315 {
316 return Err(Error::RmiErrorInput);
317 }
318
319 let top = rtt::unmap_unprotected(&rd, ipa, level, |t| {
320 ret[1] = t;
321 })?;
322 ret[1] = top;
323
324 Ok(())
325 });
326
327 listen!(rmi, rmi::RTT_FOLD, |arg, ret, _rmm| {
329 let rd_granule = get_granule_if!(arg[0], GranuleState::RD)?;
330 let rd = rd_granule.content::<Rd>()?;
331 let ipa = arg[1];
332 let level = arg[2];
333
334 let min_level = rd.s2_starting_level() as usize + 1;
335
336 if (level < min_level) || (level > RTT_PAGE_LEVEL) || !is_valid_rtt_cmd(&rd, ipa, level - 1)
337 {
338 return Err(Error::RmiErrorInput);
339 }
340
341 let rtt = rtt::fold(&rd, ipa, level)?;
342 ret[1] = rtt;
343 Ok(())
344 });
345}
346
347pub fn validate_ipa(rd: &Rd, ipa: usize) -> Result<(), Error> {
348 if !is_granule_aligned(ipa) {
349 error!("ipa: {:x} is not aligned with {:x}", ipa, GRANULE_SIZE);
350 return Err(Error::RmiErrorInput);
351 }
352
353 if !rd.addr_in_par(ipa) {
354 error!(
355 "ipa: {:x} is not in protected ipa range {:x}",
356 ipa,
357 rd.par_size()
358 );
359 return Err(Error::RmiErrorInput);
360 }
361
362 if !is_valid_rtt_cmd(rd, ipa, RTT_PAGE_LEVEL) {
363 return Err(Error::RmiErrorInput);
364 }
365
366 Ok(())
367}
368
369#[cfg(test)]
370mod test {
371 use crate::granule::GRANULE_SIZE;
372 use crate::realm::rd::{Rd, State};
373 use crate::rmi::*;
374 use crate::test_utils::{mock, *};
375
376 use alloc::vec;
377
378 #[test]
382 fn rmi_rtt_create_positive() {
383 let rd = realm_create();
384
385 let (rtt1, rtt2, rtt3, rtt4) = (
386 mock::host::alloc_granule(IDX_RTT_LEVEL1),
387 mock::host::alloc_granule(IDX_RTT_LEVEL2),
388 mock::host::alloc_granule(IDX_RTT_LEVEL3),
389 mock::host::alloc_granule(IDX_RTT_OTHER),
390 );
391
392 for rtt in &[rtt1, rtt2, rtt3, rtt4] {
393 let ret = rmi::<GRANULE_DELEGATE>(&[*rtt]);
394 assert_eq!(ret[0], SUCCESS);
395 }
396
397 let test_data = vec![
398 (rtt1, 0x0, 0x1),
399 (rtt2, 0x0, 0x2),
400 (rtt3, 0x0, 0x3),
401 (rtt4, 0x40000000, 0x2),
402 ];
403
404 unsafe {
405 let rd_obj = &*(rd as *const Rd);
406 assert!(rd_obj.at_state(State::New));
407 };
408
409 for (rtt, ipa, level) in &test_data {
410 let ret = rmi::<RTT_CREATE>(&[rd, *rtt, *ipa, *level]);
411 assert_eq!(ret[0], SUCCESS);
412 }
413
414 let (rtt4_ipa, rtt4_level) = (test_data[3].1, test_data[3].2);
415 let ret = rmi::<RTT_READ_ENTRY>(&[rd, rtt4_ipa, rtt4_level - 1]);
416 assert_eq!(ret[0], SUCCESS);
417
418 let (state, desc) = (ret[2], ret[3]);
419 const RMI_TABLE: usize = 2;
420 assert_eq!(state, RMI_TABLE);
421 assert_eq!(desc, rtt4);
422
423 for (_, ipa, level) in test_data.iter().rev() {
424 let ret = rmi::<RTT_DESTROY>(&[rd, *ipa, *level]);
425 assert_eq!(ret[0], SUCCESS);
426 }
427
428 for rtt in &[rtt1, rtt2, rtt3, rtt4] {
429 let ret = rmi::<GRANULE_UNDELEGATE>(&[*rtt]);
430 assert_eq!(ret[0], SUCCESS);
431 }
432
433 realm_destroy(rd);
434
435 miri_teardown();
436 }
437
438 #[test]
442 fn rmi_rtt_init_ripas_positive() {
443 let rd = realm_create();
444 let ipa = 0;
445 mock::host::map(rd, ipa);
446
447 let base = (ipa / L3_SIZE) * L3_SIZE;
448 let top = base + L3_SIZE;
449 let ret = rmi::<RTT_INIT_RIPAS>(&[rd, base, top]);
450 assert_eq!(ret[0], SUCCESS);
451 assert_eq!(ret[1], top);
452
453 let ret = rmi::<RTT_READ_ENTRY>(&[rd, ipa, MAP_LEVEL]);
454 assert_eq!(ret[0], SUCCESS);
455
456 let (level, ripas) = (ret[1], ret[4]);
457 const RMI_RAM: usize = 1;
458 assert_eq!(level, MAP_LEVEL);
459 assert_eq!(ripas, RMI_RAM);
460
461 mock::host::unmap(rd, ipa, false);
462
463 realm_destroy(rd);
464
465 miri_teardown();
466 }
467
468 #[test]
472 fn rmi_rtt_map_unprotected_positive() {
473 let rd = realm_create();
474
475 const IPA_ADDR_UNPROTECTED_UNASSIGNED: usize = (1 << (IPA_WIDTH - 1)) + L3_SIZE;
476 mock::host::map(rd, IPA_ADDR_UNPROTECTED_UNASSIGNED);
477
478 let ipa = IPA_ADDR_UNPROTECTED_UNASSIGNED;
479 let level = MAP_LEVEL;
480 let ns = mock::host::alloc_granule(IDX_NS_DESC);
481 let desc = ns | ATTR_NORMAL_WB_WA_RA | ATTR_STAGE2_AP_RW;
482
483 let ret = rmi::<RTT_MAP_UNPROTECTED>(&[rd, ipa, level, desc]);
484 assert_eq!(ret[0], SUCCESS);
485
486 let ret = rmi::<RTT_READ_ENTRY>(&[rd, ipa, level]);
487 assert_eq!(ret[0], SUCCESS);
488
489 let (_level, state, out_desc, _ripas) = (ret[1], ret[2], ret[3], ret[4]);
490 const RMI_ASSIGNED: usize = 1;
491 assert_eq!(state, RMI_ASSIGNED);
492 assert_eq!(out_desc, desc);
493
494 let ret = rmi::<RTT_UNMAP_UNPROTECTED>(&[rd, ipa, level]);
495 assert_eq!(ret[0], SUCCESS);
496
497 mock::host::unmap(rd, ipa, false);
498
499 realm_destroy(rd);
500
501 miri_teardown();
502 }
503
504 #[test]
508 fn rmi_data_create_positive() {
509 let rd = realm_create();
510
511 const IPA_ADDR_ASSIGNED: usize = GRANULE_SIZE;
512 const IPA_ADDR_DATA: usize = GRANULE_SIZE * 3;
513 const IPA_ADDR_PROTECTED_ASSIGNED_EMPTY: usize = GRANULE_SIZE * 4;
514
515 const RMI_UNASSIGNED: usize = 0;
516 const RMI_DESTROYED: usize = 2;
517 const RMI_EMPTY: usize = 0;
518
519 data_create(rd, IPA_ADDR_ASSIGNED, IDX_DATA1, IDX_SRC1);
520
521 data_create(rd, IPA_ADDR_DATA, IDX_DATA2, IDX_SRC2);
522
523 let ipa = IPA_ADDR_ASSIGNED;
524 let ret = rmi::<DATA_DESTROY>(&[rd, ipa]);
525 assert_eq!(ret[0], SUCCESS);
526
527 let (data, top) = (ret[1], ret[2]);
528 assert_eq!(data, granule_addr(IDX_DATA1));
529 assert_eq!(top, IPA_ADDR_DATA);
530
531 let ret = rmi::<RTT_READ_ENTRY>(&[rd, ipa, MAP_LEVEL]);
533 assert_eq!(ret[0], SUCCESS);
534
535 let (_level, state, _desc, ripas) = (ret[1], ret[2], ret[3], ret[4]);
536 assert_eq!(state, RMI_UNASSIGNED);
537 assert_eq!(ripas, RMI_DESTROYED);
538
539 let data = mock::host::alloc_granule(IDX_DATA3);
541 let ret = rmi::<GRANULE_DELEGATE>(&[data]);
542 assert_eq!(ret[0], SUCCESS);
543
544 let ret = rmi::<DATA_CREATE_UNKNOWN>(&[rd, data, ipa]);
545 assert_eq!(ret[0], SUCCESS);
546
547 let ret = rmi::<DATA_DESTROY>(&[rd, ipa]);
548 assert_eq!(ret[0], SUCCESS);
549
550 let ret = rmi::<RTT_READ_ENTRY>(&[rd, ipa, MAP_LEVEL]);
551 assert_eq!(ret[0], SUCCESS);
552
553 let (_level, state, _desc, ripas) = (ret[1], ret[2], ret[3], ret[4]);
554 assert_eq!(state, RMI_UNASSIGNED);
555 assert_eq!(ripas, RMI_DESTROYED);
556
557 let ipa = IPA_ADDR_PROTECTED_ASSIGNED_EMPTY;
559 let ret = rmi::<RTT_READ_ENTRY>(&[rd, ipa, MAP_LEVEL]);
560 assert_eq!(ret[0], SUCCESS);
561
562 mock::host::map(rd, ipa);
563
564 let data = mock::host::alloc_granule(IDX_DATA4);
565 let ret = rmi::<GRANULE_DELEGATE>(&[data]);
566 assert_eq!(ret[0], SUCCESS);
567
568 let ret = rmi::<DATA_CREATE_UNKNOWN>(&[rd, data, ipa]);
569 assert_eq!(ret[0], SUCCESS);
570
571 let ret = rmi::<RTT_READ_ENTRY>(&[rd, ipa, MAP_LEVEL]);
572 assert_eq!(ret[0], SUCCESS);
573
574 let ret = rmi::<DATA_DESTROY>(&[rd, ipa]);
575 assert_eq!(ret[0], SUCCESS);
576
577 let ret = rmi::<RTT_READ_ENTRY>(&[rd, ipa, MAP_LEVEL]);
578 assert_eq!(ret[0], SUCCESS);
579
580 let (_level, state, _desc, ripas) = (ret[1], ret[2], ret[3], ret[4]);
581 assert_eq!(state, RMI_UNASSIGNED);
582 assert_eq!(ripas, RMI_EMPTY);
583
584 let ret = rmi::<DATA_DESTROY>(&[rd, IPA_ADDR_DATA]);
585 assert_eq!(ret[0], SUCCESS);
586
587 mock::host::unmap(rd, ipa, false);
589 for idx in IDX_DATA1..IDX_DATA4 + 1 {
590 let ret = rmi::<GRANULE_UNDELEGATE>(&[granule_addr(idx)]);
591 assert_eq!(ret[0], SUCCESS);
592 }
593
594 realm_destroy(rd);
595
596 miri_teardown();
597 }
598
599 #[test]
603 fn rmi_rtt_fold_positive() {
604 let rd = realm_create();
605
606 const IPA_HOMOGENEOUS_RTT: usize = 0;
607 let ipa = IPA_HOMOGENEOUS_RTT;
608
609 mock::host::map(rd, ipa);
610
611 let base = ipa;
612 let top = ipa + L2_SIZE;
613 let ret = rmi::<RTT_INIT_RIPAS>(&[rd, base, top]);
614 assert_eq!(ret[0], SUCCESS);
615
616 let ret = rmi::<RTT_READ_ENTRY>(&[rd, base, MAP_LEVEL - 1]);
618 let (_level, _state, parent_desc, _ripas) = (ret[1], ret[2], ret[3], ret[4]);
619 assert_eq!(ret[0], SUCCESS);
620
621 let ret = rmi::<RTT_READ_ENTRY>(&[rd, base, MAP_LEVEL]);
623 let (_level, fold_state, fold_desc, fold_ripas) = (ret[1], ret[2], ret[3], ret[4]);
624 assert_eq!(ret[0], SUCCESS);
625
626 let ret = rmi::<RTT_FOLD>(&[rd, base, MAP_LEVEL]);
627 assert_eq!(ret[0], SUCCESS);
628 let out_rtt = ret[1];
629 assert_eq!(out_rtt, parent_desc);
630
631 let ret = rmi::<RTT_READ_ENTRY>(&[rd, base, MAP_LEVEL - 1]);
633 assert_eq!(ret[0], SUCCESS);
634
635 let (_level, state, desc, ripas) = (ret[1], ret[2], ret[3], ret[4]);
637 assert_eq!(fold_state, state);
638 assert_eq!(fold_desc, desc);
639 assert_eq!(fold_ripas, ripas);
640
641 mock::host::unmap(rd, ipa, true);
642
643 realm_destroy(rd);
644
645 miri_teardown();
646 }
647
648 #[test]
652 fn rmi_rtt_set_ripas_positive() {
653 use crate::rmi::rec::run::Run;
654 use crate::rsi::PSCI_CPU_ON;
655
656 let rd = mock::host::realm_setup();
657
658 let (rec1, run1) = (granule_addr(IDX_REC1), granule_addr(IDX_REC1_RUN));
659 let ret = rmi::<REC_ENTER>(&[rec1, run1]);
660 assert_eq!(ret[0], SUCCESS);
661
662 let ipa = 0;
663 mock::host::map(rd, ipa);
664
665 unsafe {
666 let run = &*(run1 as *const Run);
667 let (base, top) = run.ripas();
668
669 let ret = rmi::<RTT_SET_RIPAS>(&[rd, rec1, base as usize, top as usize]);
670 assert_eq!(ret[0], SUCCESS);
671 }
672
673 mock::host::unmap(rd, ipa, false);
674 mock::host::realm_teardown(rd);
675
676 miri_teardown();
677 }
678}