1use crate::granule::is_granule_aligned;
2use crate::granule::GranuleState;
3use crate::realm::mm::stage2_tte::ripas;
4use crate::realm::rd::Rd;
5use crate::rec::context::{get_reg, set_reg};
6use crate::rec::Rec;
7use crate::rmi;
8use crate::rmi::error::Error;
9use crate::rmi::rec::run::{EntryFlag, Run};
10use crate::rsi;
11use crate::Monitor;
12use crate::{get_granule, get_granule_if};
13
14pub fn get_ripas_state(
15 _arg: &[usize],
16 ret: &mut [usize],
17 _rmm: &Monitor,
18 rec: &mut Rec<'_>,
19 _run: &mut Run,
20) -> core::result::Result<(), Error> {
21 let rd_granule = get_granule_if!(rec.owner()?, GranuleState::RD)?;
22 let rd = rd_granule.content::<Rd>()?;
23
24 let base = get_reg(rec, 1)?;
25 let top = get_reg(rec, 2)?;
26 if !is_granule_aligned(base)
29 || !is_granule_aligned(top)
30 || !rd.addr_in_par(base)
31 || top <= base
32 || !rd.addr_in_par(top - 1)
33 {
34 if set_reg(rec, 0, rsi::ERROR_INPUT).is_err() {
35 warn!("Unable to set register 0. rec: {:?}", rec);
36 }
37 ret[0] = rmi::SUCCESS_REC_ENTER;
38 return Ok(());
39 }
40
41 let res = crate::realm::mm::rtt::get_ripas(&rd, base, top);
42 let (out_top, ripas) = if let Ok((out_top, ripas)) = res {
43 if out_top > top {
44 (top, ripas)
45 } else {
46 (out_top, ripas)
47 }
48 } else {
49 if set_reg(rec, 0, rsi::ERROR_INPUT).is_err() {
50 warn!("Unable to set register 0. rec: {:?}", rec);
51 }
52 ret[0] = rmi::SUCCESS_REC_ENTER;
53 return Ok(());
54 };
55
56 debug!(
57 "RSI_IPA_STATE_GET: base: {:X} top: {:X} out_top: {:X} ripas: {:X}",
58 base, top, out_top, ripas
59 );
60
61 if set_reg(rec, 0, rsi::SUCCESS).is_err() {
62 warn!("Unable to set register 0. rec: {:?}", rec);
63 }
64
65 if set_reg(rec, 1, out_top).is_err() {
66 warn!("Unable to set register 1. rec: {:?}", rec);
67 }
68
69 if set_reg(rec, 2, ripas as usize).is_err() {
70 warn!("Unable to set register 2. rec: {:?}", rec);
71 }
72
73 ret[0] = rmi::SUCCESS_REC_ENTER;
74 Ok(())
75}
76
77pub fn set_ripas_state(
78 _arg: &[usize],
79 ret: &mut [usize],
80 _rmm: &Monitor,
81 rec: &mut Rec<'_>,
82 run: &mut Run,
83) -> core::result::Result<(), Error> {
84 let ipa_start = get_reg(rec, 1)?;
85 let ipa_end = get_reg(rec, 2)?;
86 let ipa_state = get_reg(rec, 3)? as u8;
87 let flags = get_reg(rec, 4)? as u64;
88
89 if ipa_end <= ipa_start {
90 set_reg(rec, 0, rsi::ERROR_INPUT)?;
91 ret[0] = rmi::SUCCESS_REC_ENTER;
92 return Ok(());
93 }
95
96 let rd_granule = get_granule_if!(rec.owner()?, GranuleState::RD)?;
97 let rd = rd_granule.content::<Rd>()?;
98
99 if !is_granule_aligned(ipa_start)
100 || !is_granule_aligned(ipa_end)
101 || !is_ripas_valid(ipa_state)
102 || ipa_end <= ipa_start
103 || !rd.addr_in_par(ipa_start)
104 || !rd.addr_in_par(ipa_end - 1)
105 {
106 set_reg(rec, 0, rsi::ERROR_INPUT)?;
107 ret[0] = rmi::SUCCESS_REC_ENTER;
108 return Ok(());
109 }
110
111 run.set_exit_reason(rmi::EXIT_RIPAS_CHANGE);
113 run.set_ripas(ipa_start as u64, ipa_end as u64, ipa_state);
114 rec.set_ripas(ipa_start as u64, ipa_end as u64, ipa_state, flags);
115 ret[0] = rmi::SUCCESS;
116 debug!(
117 "RSI_IPA_STATE_SET: {:X} ~ {:X} {:X} {:X}",
118 ipa_start, ipa_end, ipa_state, flags
119 );
120 Ok(())
121}
122
123fn is_ripas_valid(ripas: u8) -> bool {
124 match ripas as u64 {
125 ripas::EMPTY | ripas::RAM => true,
126 _ => false,
127 }
128}
129
130pub fn complete_ripas(rec: &mut Rec<'_>, run: &Run) -> Result<(), Error> {
131 let ripas_addr = rec.ripas_addr() as usize;
132 if rec.ripas_end() as usize > 0 {
133 set_reg(rec, 0, rsi::SUCCESS)?; set_reg(rec, 1, ripas_addr)?;
135 let flags = run.entry_flags();
136 if flags.get_masked(EntryFlag::RIPAS_RESPONSE) != 0 {
137 set_reg(rec, 2, 1)?; } else {
139 set_reg(rec, 2, 0)?; }
141 rec.set_ripas(0, 0, 0, 0);
142 }
143 Ok(())
144}