islet_rmm/granule/array/
mod.rs1pub mod entry;
2
3use self::entry::Entry;
4use self::entry::Granule;
5use crate::config;
6use crate::rmi::error::Error;
7
8pub const GRANULE_SIZE: usize = 4096;
9pub const GRANULE_SHIFT: usize = 12;
10pub const GRANULE_MASK: usize = !((1 << GRANULE_SHIFT) - 1);
11
12#[cfg(any(kani, miri, test, fuzzing))]
13pub const GRANULE_MEM_SIZE: usize = GRANULE_SIZE * GRANULE_STATUS_TABLE_SIZE;
14#[cfg(any(kani, miri, test, fuzzing))]
15pub static mut GRANULE_REGION: [u8; GRANULE_MEM_SIZE] = [0; GRANULE_MEM_SIZE];
26
27#[cfg(not(any(kani, miri, test, fuzzing)))]
28pub fn validate_addr(addr: usize) -> bool {
29 if !addr.is_multiple_of(GRANULE_SIZE) {
30 warn!("address need to be aligned 0x{:X}", addr);
32 return false;
33 }
34 if !config::is_ns_dram(addr) {
35 warn!("address is strange 0x{:X}", addr);
37 return false;
38 }
39 true
40}
41#[cfg(any(kani, miri, test, fuzzing))]
42pub fn validate_addr(addr: usize) -> bool {
44 if addr % GRANULE_SIZE != 0 {
45 warn!("address need to be aligned 0x{:X}", addr);
47 return false;
48 }
49 let g_start = unsafe { GRANULE_REGION.as_ptr() as usize };
50 let g_end = g_start + GRANULE_MEM_SIZE;
51 addr >= g_start && addr < g_end
52}
53
54#[cfg(not(any(kani, miri, test, fuzzing)))]
55pub fn granule_addr_to_index(addr: usize) -> usize {
56 let regions = config::NS_DRAM_REGIONS.lock();
57
58 let mut base_idx = 0;
59 for range in regions.iter() {
60 if range.contains(&addr) {
61 return (addr - range.start) / GRANULE_SIZE + base_idx;
62 }
63 base_idx += (range.end - range.start) / GRANULE_SIZE;
64 }
65
66 usize::MAX
67}
68#[cfg(any(kani, miri, test, fuzzing))]
69pub fn granule_addr_to_index(addr: usize) -> usize {
71 let g_start = unsafe { GRANULE_REGION.as_ptr() as usize };
72 let g_end = g_start + GRANULE_MEM_SIZE;
73 if addr >= g_start && addr < g_end {
74 return (addr - g_start) / GRANULE_SIZE;
75 }
76 usize::MAX
77}
78
79pub fn is_granule_aligned(addr: usize) -> bool {
80 addr.is_multiple_of(GRANULE_SIZE)
81}
82
83#[derive(Clone, Copy, Debug, PartialEq)]
84pub struct GranuleState {
85 pub inner: u8,
86}
87
88#[allow(non_upper_case_globals)]
89impl GranuleState {
90 pub const Undelegated: u8 = 0;
91 pub const Delegated: u8 = 1;
92 pub const RD: u8 = 2;
93 pub const Rec: u8 = 3;
94 pub const RecAux: u8 = 4;
95 pub const Data: u8 = 5;
96 pub const RTT: u8 = 6;
97 pub const Metadata: u8 = 7;
98
99 pub fn new(state: u8) -> Self {
100 Self { inner: state }
101 }
102}
103
104pub fn set_granule(granule: &mut Granule, state: u8) -> Result<(), Error> {
105 granule.set_state(state)
106}
107
108lazy_static! {
109 pub static ref GRANULE_STATUS_TABLE: GranuleStatusTable = GranuleStatusTable::new();
110}
111
112#[cfg(not(any(kani, miri, test, fuzzing)))]
113pub const GRANULE_STATUS_TABLE_SIZE: usize = config::MAX_DRAM_SIZE / GRANULE_SIZE; #[cfg(kani)]
115pub const GRANULE_STATUS_TABLE_SIZE: usize = 6;
116#[cfg(any(miri, test))]
117pub const GRANULE_STATUS_TABLE_SIZE: usize = 55;
118#[cfg(fuzzing)]
119pub const GRANULE_STATUS_TABLE_SIZE: usize = 2048;
120
121pub struct GranuleStatusTable {
122 pub entries: [Entry; GRANULE_STATUS_TABLE_SIZE],
123}
124
125impl GranuleStatusTable {
126 pub fn new() -> Self {
127 Self {
128 entries: core::array::from_fn(|_| Entry::new()),
129 }
130 }
131
132 #[cfg(kani)]
133 pub fn is_valid(&self) -> bool {
134 self.entries
135 .iter()
136 .fold(true, |acc, x| acc && x.lock().unwrap().is_valid())
137 }
138}
139
140#[macro_export]
141macro_rules! get_granule {
142 ($addr:expr) => {{
143 use crate::granule::array::{GRANULE_STATUS_TABLE, GRANULE_STATUS_TABLE_SIZE};
144 use crate::granule::{granule_addr_to_index, validate_addr};
145 use crate::rmi::error::Error;
146 if !validate_addr($addr) {
147 Err(Error::RmiErrorInput)
148 } else {
149 let idx = granule_addr_to_index($addr);
150 if idx >= GRANULE_STATUS_TABLE_SIZE {
151 Err(Error::RmiErrorInput)
152 } else {
153 let gst = &GRANULE_STATUS_TABLE;
154 match gst.entries[idx].lock() {
155 Ok(guard) => Ok(guard),
156 Err(e) => Err(e),
157 }
158 }
159 }
160 }};
161}
162
163#[macro_export]
164macro_rules! get_granule_if {
165 ($addr:expr, $state:expr) => {{
166 get_granule!($addr).and_then(|guard| {
167 if guard.state() != $state {
168 use crate::rmi::error::Error;
169 Err(Error::RmiErrorInput)
170 } else {
171 Ok(guard)
172 }
173 })
174 }};
175}
176
177pub fn is_not_in_realm(addr: usize) -> bool {
178 match get_granule_if!(addr, GranuleState::Undelegated) {
179 Ok(_) => true,
180 _ => false,
181 }
182}