Skip to main content

islet_rmm/rsi/
ripas.rs

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    // To prevent underflow when top is 0,
27    // check top <= base prior to addr_in_par() check
28    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        //return Err(Error::RmiErrorInput); // integer overflows or size is zero
94    }
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    // TODO: check ipa_state value, ipa address granularity
112    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)?; // RSI_SUCCESS
134        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)?; // REJECT
138        } else {
139            set_reg(rec, 2, 0)?; // ACCEPT
140        }
141        rec.set_ripas(0, 0, 0, 0);
142    }
143    Ok(())
144}