1use super::Rec;
2use crate::gic::*;
3use crate::rmi::error::Error;
4use crate::rmi::rec::run::Run;
5
6use aarch64_cpu::registers::*;
7
8pub fn init_gic(rec: &mut Rec<'_>) {
9 let gic_state = &mut rec.context.gic_state;
10 gic_state.ich_hcr_el2 = ICH_HCR_EL2_INIT;
11}
12
13pub fn restore_state(rec: &Rec<'_>) {
14 let gic_state = &rec.context.gic_state;
15 let nr_lrs = nr_lrs();
16 let nr_aprs = nr_aprs();
17
18 for i in 0..=nr_lrs {
19 set_lr(i, gic_state.ich_lr_el2[i]);
20 }
21 for i in 0..=nr_aprs {
22 set_ap0r(i, gic_state.ich_ap0r_el2[i]);
23 set_ap1r(i, gic_state.ich_ap1r_el2[i]);
24 }
25 ICH_VMCR_EL2.set(gic_state.ich_vmcr_el2);
26 ICH_HCR_EL2.set(gic_state.ich_hcr_el2);
27}
28
29pub fn save_state(rec: &mut Rec<'_>) {
30 let gic_state = &mut rec.context.gic_state;
31 let nr_lrs = nr_lrs();
32 let nr_aprs = nr_aprs();
33
34 for i in 0..=nr_lrs {
35 gic_state.ich_lr_el2[i] = get_lr(i);
36 }
37 for i in 0..=nr_aprs {
38 gic_state.ich_ap0r_el2[i] = get_ap0r(i);
39 gic_state.ich_ap1r_el2[i] = get_ap1r(i);
40 }
41
42 gic_state.ich_vmcr_el2 = ICH_VMCR_EL2.get();
43 gic_state.ich_hcr_el2 = ICH_HCR_EL2.get();
44 gic_state.ich_misr_el2 = ICH_MISR_EL2.get();
45
46 ICH_HCR_EL2.set(gic_state.ich_hcr_el2 & !(ICH_HCR_EL2::En.mask << ICH_HCR_EL2::En.shift));
47}
48
49pub fn receive_state_from_host(rec: &mut Rec<'_>, run: &Run) -> Result<(), Error> {
50 let gic_state = &mut rec.context.gic_state;
51 let nr_lrs = nr_lrs();
52
53 gic_state.ich_lr_el2[..nr_lrs].copy_from_slice(&run.entry_gic_lrs()[..nr_lrs]);
54 gic_state.ich_hcr_el2 &= !ICH_HCR_EL2_NS_MASK;
55 gic_state.ich_hcr_el2 |= run.entry_gic_hcr() & ICH_HCR_EL2_NS_MASK;
56 Ok(())
57}
58
59pub fn send_state_to_host(rec: &Rec<'_>, run: &mut Run) -> Result<(), Error> {
60 let gic_state = &rec.context.gic_state;
61 let nr_lrs = nr_lrs();
62
63 run.exit_gic_lrs_mut()[..nr_lrs].copy_from_slice(&gic_state.ich_lr_el2[..nr_lrs]);
64 run.set_gic_misr(gic_state.ich_misr_el2);
65 run.set_gic_vmcr(gic_state.ich_vmcr_el2);
66 run.set_gic_hcr(gic_state.ich_hcr_el2 & (ICH_HCR_EL2_EOI_COUNT_MASK | ICH_HCR_EL2_NS_MASK));
67 Ok(())
68}
69
70pub fn validate_state(run: &Run) -> bool {
71 let hcr = run.entry_gic_hcr();
72
73 if (hcr & !ICH_HCR_EL2_NS_MASK) != 0 {
75 return false;
76 }
77
78 for i in 0..nr_lrs() {
79 let lrs = run.entry_gic_lrs();
80 let lr = lrs[i];
81
82 let state = (lr >> ICH_LR0_EL2::State.shift) & ICH_LR0_EL2::State.mask;
83 let vintid = (lr >> ICH_LR0_EL2::vINTID.shift) & ICH_LR0_EL2::vINTID.mask;
84 let priority = (lr >> ICH_LR0_EL2::Priority.shift) & ICH_LR0_EL2::Priority.mask;
85
86 let pintid_mask = ICH_LR0_EL2::pINTID.mask << ICH_LR0_EL2::pINTID.shift;
87 let eoi_mask = ICH_LR0_EL2::EOI.mask << ICH_LR0_EL2::EOI.shift;
88 let only_eoi = pintid_mask & !eoi_mask;
89
90 let hw = (lr >> ICH_LR0_EL2::HW.shift) & ICH_LR0_EL2::HW.mask;
91
92 if state == ICH_LR0_EL2::State::Invalid.into() {
93 continue;
94 }
95
96 if hw != 0
98 || priority & pri_res0_mask() != 0
100 || lr & only_eoi != 0
102 || !valid_vintid(vintid)
104 {
105 return false;
106 }
107
108 for j in i + 1..=nr_lrs() {
113 let lrs = run.entry_gic_lrs();
114 let lr = lrs[j];
115
116 let vintid_2 = (lr >> ICH_LR0_EL2::vINTID.shift) & ICH_LR0_EL2::vINTID.mask;
117 let state = (lr >> ICH_LR0_EL2::State.shift) & ICH_LR0_EL2::State.mask;
118
119 if state == ICH_LR0_EL2::State::Invalid.into() {
120 continue;
121 }
122
123 if vintid == vintid_2 {
124 return false;
125 }
126 }
127 }
128
129 true
130}