Skip to main content

islet_rmm/rmi/
features.rs

1use crate::event::RmiHandle;
2use crate::gic;
3use crate::listen;
4use crate::pmu;
5use crate::rec;
6use crate::rmi;
7use crate::simd;
8use armv9a::{define_bitfield, define_bits, define_mask};
9
10extern crate alloc;
11
12define_bits!(
13    FeatureReg0,
14    MAX_RECS_ORDER[41 - 38],
15    GICV3_NUM_LRS[37 - 34],
16    HASH_SHA_512[33 - 33],
17    HASH_SHA_256[32 - 32],
18    PMU_NUM_CTRS[31 - 27],
19    PMU_EN[26 - 26],
20    NUM_WPS[25 - 20],
21    NUM_BPS[19 - 14],
22    SVE_VL[13 - 10],
23    SVE_EN[9 - 9],
24    LPA2[8 - 8],
25    S2SZ[7 - 0]
26);
27
28const S2SZ_VALUE: u64 = 48;
29pub const LPA2_VALUE: u64 = 0;
30const HASH_SHA_256_VALUE: u64 = SUPPORTED;
31const HASH_SHA_512_VALUE: u64 = SUPPORTED;
32
33pub const NOT_SUPPORTED: u64 = 0;
34pub const SUPPORTED: u64 = 1;
35
36const FEATURE_REGISTER_0_INDEX: usize = 0;
37
38pub fn set_event_handler(rmi: &mut RmiHandle) {
39    listen!(rmi, rmi::FEATURES, |arg, ret, _| {
40        if arg[0] != FEATURE_REGISTER_0_INDEX {
41            ret[1] = 0;
42            return Ok(());
43        }
44
45        let mut feat_reg0 = FeatureReg0::new(0);
46        feat_reg0
47            .set_masked_value(FeatureReg0::S2SZ, S2SZ_VALUE)
48            .set_masked_value(FeatureReg0::LPA2, LPA2_VALUE)
49            .set_masked_value(FeatureReg0::HASH_SHA_256, HASH_SHA_256_VALUE)
50            .set_masked_value(FeatureReg0::HASH_SHA_512, HASH_SHA_512_VALUE)
51            .set_masked_value(FeatureReg0::MAX_RECS_ORDER, rec::max_recs_order() as u64);
52
53        #[cfg(not(any(miri, test, fuzzing)))]
54        feat_reg0
55            .set_masked_value(
56                FeatureReg0::SVE_EN,
57                if simd::sve_en() {
58                    SUPPORTED
59                } else {
60                    NOT_SUPPORTED
61                },
62            )
63            .set_masked_value(FeatureReg0::SVE_VL, simd::max_sve_vl())
64            .set_masked_value(
65                FeatureReg0::PMU_EN,
66                if pmu::pmu_present() {
67                    SUPPORTED
68                } else {
69                    NOT_SUPPORTED
70                },
71            )
72            .set_masked_value(FeatureReg0::PMU_NUM_CTRS, pmu::pmu_num_ctrs())
73            .set_masked_value(FeatureReg0::GICV3_NUM_LRS, gic::nr_lrs() as u64);
74        #[cfg(any(miri, test, fuzzing))]
75        feat_reg0
76            .set_masked_value(FeatureReg0::SVE_EN, NOT_SUPPORTED)
77            .set_masked_value(FeatureReg0::SVE_VL, 0)
78            .set_masked_value(FeatureReg0::GICV3_NUM_LRS, 0);
79
80        ret[1] = feat_reg0.get() as usize;
81        debug!("rmi::FEATURES ret:{:X}", feat_reg0.get());
82        Ok(())
83    });
84}
85
86//TODO: locate validate() in armv9a to check against AA64MMFR_EL1 register
87pub fn validate(s2sz: usize) -> bool {
88    const MIN_IPA_SIZE: usize = 32;
89    if !(MIN_IPA_SIZE..=S2SZ_VALUE as usize).contains(&s2sz) {
90        return false;
91    }
92
93    true
94}
95
96#[cfg(test)]
97mod test {
98    use crate::rmi::{FEATURES, SUCCESS};
99    use crate::test_utils::*;
100
101    // Source: https://github.com/ARM-software/cca-rmm-acs
102    // Test Case: cmd_rmi_features_host
103    #[test]
104    fn rmi_features() {
105        let ret = rmi::<FEATURES>(&[0]);
106
107        assert_eq!(ret[0], SUCCESS);
108        assert_eq!(extract_bits(ret[1], 42, 63), 0);
109
110        let ret = rmi::<FEATURES>(&[1]);
111        assert_eq!(ret[0], SUCCESS);
112        assert_eq!(ret[1], 0);
113    }
114}