islet_rmm/rmi/realm/
params.rs1use crate::const_assert_eq;
2use crate::granule::{GRANULE_SHIFT, GRANULE_SIZE};
3use crate::measurement::Hashable;
4use crate::pmu;
5use crate::realm::mm::rtt::{RTT_PAGE_LEVEL, RTT_STRIDE};
6use crate::rmi::error::Error;
7use crate::rmi::features;
8use crate::rmi::{HASH_ALGO_SHA256, HASH_ALGO_SHA512};
9use crate::simd;
10
11use armv9a::{define_bitfield, define_bits, define_mask};
12use autopadding::*;
13
14define_bits!(
15 RmiRealmFlags,
16 Lpa2[0 - 0],
17 Sve[1 - 1],
18 Pmu[2 - 2],
19 Reserved[63 - 3]
20);
21
22pad_struct_and_impl_default!(
23pub struct Params {
24 0x0 pub flags: u64,
25 0x8 pub s2sz: u8,
26 0x10 pub sve_vl: u8,
27 0x18 pub num_bps: u8,
28 0x20 pub num_wps: u8,
29 0x28 pub pmu_num_ctrs: u8,
30 0x30 pub hash_algo: u8,
31 0x400 pub rpv: [u8; 64],
32 0x800 pub vmid: u16,
33 0x808 pub rtt_base: u64,
34 0x810 pub rtt_level_start: i64,
35 0x818 pub rtt_num_start: u32,
36 0x1000 => @END,
37}
38);
39
40const_assert_eq!(core::mem::size_of::<Params>(), GRANULE_SIZE);
41const SUPPORTED: u64 = 1;
42
43impl core::fmt::Debug for Params {
44 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 f.debug_struct("Params")
46 .field(
47 "flags",
48 &format_args!(
49 "lpa2: {:?} sve: {:?} pmu: {:?}",
50 RmiRealmFlags::new(self.flags).get_masked_value(RmiRealmFlags::Lpa2),
51 RmiRealmFlags::new(self.flags).get_masked_value(RmiRealmFlags::Sve),
52 RmiRealmFlags::new(self.flags).get_masked_value(RmiRealmFlags::Pmu)
53 ),
54 )
55 .field("s2sz", &self.s2sz)
56 .field("sve_vl", &self.sve_vl)
57 .field("num_bps", &self.num_bps)
58 .field("num_wps", &self.num_wps)
59 .field("pmu_num_ctrs", &self.pmu_num_ctrs)
60 .field("hash_algo", &self.hash_algo)
61 .field("rpv", &self.rpv)
62 .field("vmid", &self.vmid)
63 .field("rtt_base", &format_args!("{:#X}", &self.rtt_base))
64 .field("rtt_level_start", &self.rtt_level_start)
65 .field("rtt_num_start", &self.rtt_num_start)
66 .finish()
67 }
68}
69
70impl Hashable for Params {
71 fn hash(
72 &self,
73 hasher: &crate::measurement::Hasher,
74 out: &mut [u8],
75 ) -> Result<(), crate::measurement::MeasurementError> {
76 hasher.hash_fields_into(out, |alg| {
77 alg.hash_u64(self.flags);
78 alg.hash(self._padflags);
79 alg.hash_u8(self.s2sz);
80 alg.hash(self._pads2sz);
81 alg.hash_u8(self.sve_vl);
82 alg.hash(self._padsve_vl);
83 alg.hash_u8(self.num_bps);
84 alg.hash(self._padnum_bps);
85 alg.hash_u8(self.num_wps);
86 alg.hash(self._padnum_wps);
87 alg.hash_u8(self.pmu_num_ctrs);
88 alg.hash(self._padpmu_num_ctrs);
89 alg.hash_u8(self.hash_algo);
90 alg.hash(self._padhash_algo);
91 alg.hash([0u8; 64]); alg.hash(self._padrpv);
93 alg.hash_u16(0); alg.hash(self._padvmid);
95 alg.hash_u64(0); alg.hash(self._padrtt_base);
97 alg.hash_u64(0); alg.hash(self._padrtt_level_start);
99 alg.hash_u32(0); alg.hash(self._padrtt_num_start);
101 })
102 }
103}
104
105impl Params {
106 pub fn ipa_bits(&self) -> usize {
107 self.s2sz as usize
108 }
109
110 pub fn sve_en(&self) -> bool {
111 let flags = RmiRealmFlags::new(self.flags);
112 flags.get_masked_value(RmiRealmFlags::Sve) == SUPPORTED
113 }
114
115 pub fn pmu_en(&self) -> bool {
116 let flags = RmiRealmFlags::new(self.flags);
117 flags.get_masked_value(RmiRealmFlags::Pmu) == SUPPORTED
118 }
119
120 pub fn verify_compliance(&self, rd: usize) -> Result<(), Error> {
121 trace!("{:?}", self);
122 if self.rtt_base as usize == rd {
123 return Err(Error::RmiErrorInput);
124 }
125
126 if !(self.rtt_base as usize).is_multiple_of(GRANULE_SIZE) {
127 return Err(Error::RmiErrorInput);
128 }
129
130 if !features::validate(self.s2sz as usize) {
131 return Err(Error::RmiErrorInput);
132 }
133
134 let ipa_bits = self.ipa_bits();
136 let rtt_slvl = self.rtt_level_start as usize;
137
138 let level = RTT_PAGE_LEVEL
139 .checked_sub(rtt_slvl)
140 .ok_or(Error::RmiErrorInput)?;
141 let min_ipa_bits = level * RTT_STRIDE + GRANULE_SHIFT + 1;
142 let max_ipa_bits = min_ipa_bits + (RTT_STRIDE - 1) + 4;
143 let sl_ipa_bits = (level * RTT_STRIDE) + GRANULE_SHIFT + RTT_STRIDE;
144
145 if (ipa_bits < min_ipa_bits) || (ipa_bits > max_ipa_bits) {
146 return Err(Error::RmiErrorInput);
147 }
148
149 let s2_num_root_rtts = {
150 if sl_ipa_bits >= ipa_bits {
151 1
152 } else {
153 1 << (ipa_bits - sl_ipa_bits)
154 }
155 };
156 if s2_num_root_rtts != self.rtt_num_start {
157 return Err(Error::RmiErrorInput);
158 }
159
160 let flags = RmiRealmFlags::new(self.flags);
162 if flags.get_masked_value(RmiRealmFlags::Lpa2) != features::LPA2_VALUE {
163 return Err(Error::RmiErrorInput);
164 }
165 if !simd::validate(self.sve_en(), self.sve_vl as u64) {
166 return Err(Error::RmiErrorInput);
167 }
168 if self.pmu_en()
169 && (!pmu::pmu_present()
170 || self.pmu_num_ctrs > pmu::pmu_num_ctrs() as u8
171 || (self.pmu_num_ctrs == 0 && !pmu::hpmn0_present()))
172 {
173 return Err(Error::RmiErrorInput);
174 }
175
176 match self.hash_algo {
177 HASH_ALGO_SHA256 | HASH_ALGO_SHA512 => Ok(()),
178 _ => Err(Error::RmiErrorInput),
179 }
180 }
181}
182
183impl safe_abstraction::raw_ptr::RawPtr for Params {}
184
185impl safe_abstraction::raw_ptr::SafetyChecked for Params {}
186
187impl safe_abstraction::raw_ptr::SafetyAssured for Params {
188 fn is_initialized(&self) -> bool {
189 true
196 }
197
198 fn verify_ownership(&self) -> bool {
199 true
205 }
206}