1use crate::rec::{Rec, RmmRecEmulatableAbort::EmulatableAbort};
2use crate::rmi::error::Error;
3use crate::rmi::rec::run::{EntryFlag, Run};
4use armv9a::regs::*;
5
6pub fn emulate_mmio(rec: &mut Rec<'_>, run: &Run) -> Result<(), Error> {
7 let flags = run.entry_flags();
8
9 if flags.get_masked(EntryFlag::INJECT_SEA | EntryFlag::EMUL_MMIO) == 0 {
12 return Ok(());
13 }
14
15 let esr_el2 = rec.context.sys_regs.esr_el2;
16 let esr = EsrEl2::new(esr_el2);
17 let ec = esr.get_masked_value(EsrEl2::EC);
18 let wnr = esr.get_masked_value(EsrEl2::WNR);
19 let rt = esr.get_masked_value(EsrEl2::SRT) as usize;
20
21 if ec != ESR_EL2_EC_DATA_ABORT || rec.emulatable_abort() != EmulatableAbort {
22 return Err(Error::RmiErrorRec);
23 }
24
25 if wnr == 0 && rt != 31 {
27 let mask = esr.get_access_size_mask();
28 let val = run.entry_gpr(0)? & mask;
29 let sign_extended = esr.get_masked_value(EsrEl2::SSE);
30 if sign_extended != 0 {
31 unimplemented!();
33 }
34 rec.context.gp_regs[rt] = val;
35 }
36 rec.context.elr_el2 += 4;
37 Ok(())
38}