islet_rmm/realm/mm/
entry.rs1use crate::config::PAGE_SIZE;
2use crate::realm::mm::attribute::{desc_type, memattr, page_type, shareable};
3use crate::realm::mm::stage2_tte::S2TTE;
4use crate::realm::mm::table_level::L3Table;
5use vmsa::address::PhysAddr;
6use vmsa::error::Error;
7use vmsa::page_table::{self, Level};
8use vmsa::RawGPA;
9
10#[derive(Clone, Copy)]
11pub struct Entry(S2TTE);
12
13impl From<usize> for S2TTE {
14 fn from(val: usize) -> Self {
15 Self(val as u64)
16 }
17}
18
19impl page_table::Entry for Entry {
20 type Inner = S2TTE;
21
22 fn new() -> Self {
23 Self(S2TTE::new(0))
24 }
25
26 fn is_valid(&self) -> bool {
27 self.0.get_masked_value(S2TTE::VALID) != 0
28 }
29
30 fn clear(&mut self) {
31 self.0 = S2TTE::new(0);
32 }
33
34 fn pte(&self) -> u64 {
35 self.0.get()
36 }
37
38 fn mut_pte(&mut self) -> &mut Self::Inner {
39 self.0.get_mut()
40 }
41
42 fn address(&self, level: usize) -> Option<PhysAddr> {
43 match self.is_valid() {
44 true => match self.0.get_masked_value(S2TTE::TYPE) {
45 page_type::TABLE_OR_PAGE => {
46 Some(PhysAddr::from(self.0.get_masked(S2TTE::ADDR_TBL_OR_PAGE)))
47 }
48 page_type::BLOCK => match level {
49 1 => Some(PhysAddr::from(self.0.get_masked(S2TTE::ADDR_BLK_L1))),
50 2 => Some(PhysAddr::from(self.0.get_masked(S2TTE::ADDR_BLK_L2))),
51 _ => None,
52 },
53 _ => None,
54 },
55 false => None,
56 }
57 }
58
59 fn set(&mut self, addr: PhysAddr, flags: u64) -> Result<(), Error> {
60 self.0.set(addr.as_u64() | flags);
61
62 #[cfg(not(any(miri, test, fuzzing)))]
63 unsafe {
64 core::arch::asm!(
65 "dsb ishst",
66 "dc civac, {}",
67 "dsb ish",
68 "isb",
69 in(reg) &self.0 as *const _ as usize,
70 );
71 }
72 Ok(())
73 }
74
75 fn point_to_subtable(&mut self, _index: usize, addr: PhysAddr) -> Result<(), Error> {
76 let mut flags = S2TTE::new(0);
77 flags
78 .set_masked_value(S2TTE::DESC_TYPE, desc_type::L012_TABLE)
79 .set_masked_value(S2TTE::MEMATTR, memattr::NORMAL_FWB)
80 .set_masked_value(S2TTE::SH, shareable::INNER);
81 self.set(addr, flags.get())
82 }
83
84 fn index<L: Level>(addr: usize) -> usize {
85 match L::THIS_LEVEL {
86 0 => RawGPA::from(addr).get_masked_value(RawGPA::L0Index) as usize,
87 1 => {
88 if L::TABLE_SIZE > PAGE_SIZE {
89 let l0 = RawGPA::from(addr).get_masked_value(RawGPA::L0Index) as usize;
92 let l1 = RawGPA::from(addr).get_masked_value(RawGPA::L1Index) as usize;
93 l0 * L3Table::NUM_ENTRIES + l1
95 } else {
96 RawGPA::from(addr).get_masked_value(RawGPA::L1Index) as usize
97 }
98 }
99 2 => {
100 if L::TABLE_SIZE > PAGE_SIZE {
101 let l1 = RawGPA::from(addr).get_masked_value(RawGPA::L1Index) as usize;
102 let l2 = RawGPA::from(addr).get_masked_value(RawGPA::L2Index) as usize;
103 l1 * L3Table::NUM_ENTRIES + l2
104 } else {
105 RawGPA::from(addr).get_masked_value(RawGPA::L2Index) as usize
106 }
107 }
108 3 => RawGPA::from(addr).get_masked_value(RawGPA::L3Index) as usize,
109 _ => panic!(),
110 }
111 }
112
113 fn points_to_table_or_page(&self) -> bool {
114 match self.is_valid() {
115 true => match self.0.get_masked_value(S2TTE::TYPE) {
116 page_type::TABLE_OR_PAGE => true,
117 page_type::BLOCK => false,
118 _ => false,
119 },
120 false => false,
121 }
122 }
123}