1use crate::realm::rd::Rd;
2use crate::rec::context::{set_reg, RegOffset};
3use crate::rec::Rec;
4use crate::rmi::error::Error;
5use crate::rmi::rec::run::{EntryFlag, Run};
6
7use aarch64_cpu::registers::Readable;
8use aarch64_cpu::registers::{HPFAR_EL2, SPSR_EL2};
9use armv9a::regs::*;
10use armv9a::InMemoryRegister; pub fn host_sea_inject(rec: &mut Rec<'_>, run: &Run) -> Result<(), Error> {
13 let flags = run.entry_flags();
14
15 if flags.get_masked(EntryFlag::INJECT_SEA) == 0 {
17 return Ok(());
18 }
19
20 let esr_el2 = rec.context.sys_regs.esr_el2;
21 let esr = EsrEl2::new(esr_el2);
22 let ec = esr.get_masked_value(EsrEl2::EC);
23
24 if ec != ESR_EL2_EC_DATA_ABORT {
25 return Ok(());
26 }
27
28 let fault_ipa = rec.context.sys_regs.hpfar & (HPFAR_EL2::FIPA.mask << HPFAR_EL2::FIPA.shift);
32 let fault_ipa = (fault_ipa << 8) as usize;
33
34 let raw_ptr: *const Rd = rec.owner()? as *const Rd;
35 let rd: &Rd = unsafe { raw_ptr.as_ref().expect("REASON") }; if !rd.addr_in_par(fault_ipa) && fault_ipa < rd.ipa_size() {
37 inject_sea(rec, esr_el2, rec.context.sys_regs.far_el2);
38 }
39
40 Ok(())
41}
42
43pub fn inject_sea(rec: &mut Rec<'_>, esr_el2: u64, far_el2: u64) {
44 let mut esr_el1 = esr_el2 & !(EsrEl2::EC | EsrEl2::FNV | EsrEl2::S1PTW | EsrEl2::DFSC);
45 let mut ec = esr_el2 & EsrEl2::EC;
46 let context = &mut rec.context;
47 let spsr_el2: InMemoryRegister<u64, SPSR_EL2::Register> =
48 InMemoryRegister::new(context.spsr_el2);
49 let elr_el2 = context.elr_el2;
50 let spsr_m = spsr_el2.read(SPSR_EL2::M);
51 if spsr_m != SPSR_EL2::M::EL0t.into() {
52 ec |= 1 << EsrEl2::EC.trailing_zeros();
53 }
54 esr_el1 |= ec;
55 esr_el1 |= EsrEl2::EA;
56 esr_el1 |= 0b010000; const VBAR_CURRENT_SP0_OFFSET: u64 = 0x0;
58 const VBAR_CURRENT_SPX_OFFSET: u64 = 0x200;
59 const VBAR_LOWER_AARCH64_OFFSET: u64 = 0x400;
60 let mut vector_entry = {
61 match spsr_el2.read_as_enum(SPSR_EL2::M) {
62 Some(SPSR_EL2::M::Value::EL0t) => VBAR_LOWER_AARCH64_OFFSET,
63 Some(SPSR_EL2::M::Value::EL1t) => VBAR_CURRENT_SP0_OFFSET,
64 Some(SPSR_EL2::M::Value::EL1h) => VBAR_CURRENT_SPX_OFFSET,
65 _ => panic!("shouldn't be reached here"), }
67 };
68 vector_entry += context.sys_regs.vbar;
69
70 let pstate: u64 = (SPSR_EL2::D::SET
71 + SPSR_EL2::A::SET
72 + SPSR_EL2::I::SET
73 + SPSR_EL2::F::SET
74 + SPSR_EL2::M::EL1h)
75 .into();
76
77 context.sys_regs.esr_el1 = esr_el1;
78 context.sys_regs.far = far_el2;
79 context.sys_regs.elr = elr_el2;
80 context.sys_regs.spsr = spsr_el2.get();
81 context.elr_el2 = vector_entry;
82 let _ = set_reg(rec, RegOffset::PSTATE, pstate as usize);
83}