1use super::gic;
2use super::pauth;
3use super::pauth::PauthRegister;
4use super::pmu;
5use super::pmu::PmuRegister;
6use super::simd;
7use super::simd::SimdContext;
8use super::timer;
9use super::Rec;
10use crate::rmi::error::Error;
11
12use aarch64_cpu::registers::*;
13
14#[repr(C)]
15#[derive(Default, Debug)]
16pub struct Context {
17 pub gp_regs: [u64; 31],
18 pub elr_el2: u64,
19 pub spsr_el2: u64,
20 pub sys_regs: SystemRegister,
21 pub mdcr_el2: u64,
22 pub gic_state: GICRegister,
23 pub timer: TimerRegister,
24 pub simd: SimdContext,
25 pub pauth: PauthRegister,
26 pub pmu: PmuRegister,
27}
28
29pub struct RegOffset;
30impl RegOffset {
31 pub const PC: usize = 31;
32 pub const PSTATE: usize = 32;
33 pub const SCTLR: usize = 40;
34}
35
36pub fn set_reg(rec: &mut Rec<'_>, register: usize, value: usize) -> Result<(), Error> {
37 match register {
38 0..=30 => {
39 rec.context.gp_regs[register] = value as u64;
40 Ok(())
41 }
42 RegOffset::PC => {
43 rec.context.elr_el2 = value as u64;
44 Ok(())
45 }
46 RegOffset::PSTATE => {
47 rec.context.spsr_el2 = value as u64;
48 Ok(())
49 }
50 _ => Err(Error::RmiErrorInput),
51 }?;
52 Ok(())
53}
54
55pub fn get_reg(rec: &Rec<'_>, register: usize) -> Result<usize, Error> {
56 match register {
57 0..=30 => {
58 let value = rec.context.gp_regs[register];
59 Ok(value as usize)
60 }
61 RegOffset::PC => {
62 let value = rec.context.elr_el2;
63 Ok(value as usize)
64 }
65 _ => Err(Error::RmiErrorInput),
66 }
67}
68
69impl Context {
70 pub fn new() -> Self {
71 Self {
75 spsr_el2: (SPSR_EL2::D.mask << SPSR_EL2::D.shift)
76 | (SPSR_EL2::A.mask << SPSR_EL2::A.shift)
77 | (SPSR_EL2::I.mask << SPSR_EL2::I.shift)
78 | (SPSR_EL2::F.mask << SPSR_EL2::F.shift)
79 | (SPSR_EL2::M.mask & u64::from(SPSR_EL2::M::EL1h)) << SPSR_EL2::M.shift,
80 ..Default::default()
81 }
82 }
83
84 pub unsafe fn into_current(rec: &Rec<'_>) {
91 TPIDR_EL2.set(rec as *const _ as u64);
92 gic::restore_state(rec);
93 pauth::restore_state(rec);
94 pmu::restore_state(rec);
95 #[cfg(not(fuzzing))]
96 timer::restore_state(rec);
97 #[cfg(not(any(test, miri, fuzzing)))]
98 simd::restore_state(rec);
99 }
100
101 pub unsafe fn from_current(rec: &mut Rec<'_>) {
108 gic::save_state(rec);
109 pauth::save_state(rec);
110 pmu::save_state(rec);
111 #[cfg(not(fuzzing))]
112 timer::save_state(rec);
113 #[cfg(not(any(test, miri, fuzzing)))]
114 simd::save_state(rec);
115 }
116}
117
118#[repr(C)]
120#[derive(Default, Debug)]
121pub struct GICRegister {
122 pub ich_ap0r_el2: [u64; 4],
124 pub ich_ap1r_el2: [u64; 4],
126 pub ich_vmcr_el2: u64,
128 pub ich_hcr_el2: u64,
130 pub ich_lr_el2: [u64; 16],
132 pub ich_misr_el2: u64,
134}
135
136#[repr(C)]
137#[derive(Default, Debug)]
138pub struct SystemRegister {
141 pub sp: u64,
142 pub sp_el0: u64,
143 pub esr_el1: u64,
144 pub vbar: u64,
145 pub ttbr0: u64,
146 pub ttbr1: u64,
147 pub mair: u64,
148 pub amair: u64,
149 pub tcr: u64,
150 pub tpidr: u64,
151 pub tpidr_el0: u64,
152 pub tpidrro: u64,
153 pub actlr: u64,
154 pub vmpidr: u64,
155 pub csselr: u64,
156 pub cpacr: u64,
157 pub afsr0: u64,
158 pub afsr1: u64,
159 pub far: u64,
160 pub contextidr: u64,
161 pub cntkctl: u64,
162 pub par: u64,
163 pub vttbr: u64,
164 pub elr: u64,
165 pub spsr: u64,
166 pub sctlr: u64,
167 pub esr_el2: u64,
168 pub hpfar: u64,
169 pub far_el2: u64,
170}
171
172#[repr(C)]
173#[derive(Default, Debug)]
174pub struct TimerRegister {
175 pub cntvoff_el2: u64,
176 pub cntv_cval_el0: u64,
177 pub cntv_ctl_el0: u64,
178 pub cntpoff_el2: u64,
179 pub cntp_cval_el0: u64,
180 pub cntp_ctl_el0: u64,
181 pub cnthctl_el2: u64,
182}