diff --git a/lib/vmsa/src/lib.rs b/lib/vmsa/src/lib.rs index b2b6ced7f678f..41efbdd47f959 100644 --- a/lib/vmsa/src/lib.rs +++ b/lib/vmsa/src/lib.rs @@ -1,7 +1,4 @@ #![no_std] -#![allow(incomplete_features)] -#![feature(specialization)] -#![feature(generic_const_exprs)] #![warn(rust_2018_idioms)] pub mod address; diff --git a/lib/vmsa/src/page_table.rs b/lib/vmsa/src/page_table.rs index 2f56419a079fc..6b28d8b30040d 100644 --- a/lib/vmsa/src/page_table.rs +++ b/lib/vmsa/src/page_table.rs @@ -12,11 +12,16 @@ use core::marker::PhantomData; // - As of now, concurrency safety for RTT and Realm page table is achieved by a big lock. // - If we want to use entry-level locking for a better efficiency, several pieces of codes in this file should be modified accordingly. +const PAGE_SIZE: usize = 4096; +const NUM_ENTRIES: usize = 512; +const TABLE_SIZE: usize = PAGE_SIZE; +const TABLE_ALIGN: usize = PAGE_SIZE; + pub trait Level { const THIS_LEVEL: usize; const TABLE_SIZE: usize; const TABLE_ALIGN: usize; - const NUM_ENTRIES: usize; + const NUM_ENTRIES: usize; // TODO: remove this later } pub trait HasSubtable: Level { @@ -66,6 +71,7 @@ pub trait Entry { } } fn index(addr: usize) -> usize; + fn index_with_level(addr: usize, level: usize, is_root: bool, root_n: usize) -> usize; fn subtable(&self, _index: usize, level: usize) -> Result { match self.address(level) { @@ -92,18 +98,18 @@ pub trait MemAlloc { } } -pub struct PageTable { +pub struct PageTable { entries: [E; N], - level: PhantomData, address: PhantomData, } -impl MemAlloc for PageTable {} -impl MemAlloc for PageTable {} +impl MemAlloc for PageTable {} + +pub trait PageTableMethods { + fn new_with_base(base: usize) -> Result<*mut PageTable, Error>; + + fn new_with_align(size: usize, align: usize) -> Result<*mut PageTable, Error>; -pub trait PageTableMethods { - fn new_with_base(base: usize) -> Result<*mut PageTable, Error>; - fn new_with_align(size: usize, align: usize) -> Result<*mut PageTable, Error>; /// Sets multiple page table entries /// /// (input) @@ -113,10 +119,12 @@ pub trait PageTableMethods { /// is_raw: (if on) a user-provided `flags` is only attached (== without attaching a default flag) fn set_pages( &mut self, + level: usize, guest: PageIter, phys: PageIter, flags: u64, is_raw: bool, + root_n: usize, ) -> Result<(), Error>; /// Sets a single page table entry /// @@ -127,16 +135,20 @@ pub trait PageTableMethods { /// is_raw: (if on) a user-provided `flags` is only attached (== without attaching a default flag) fn set_page( &mut self, + level: usize, guest: Page, phys: Page, flags: u64, is_raw: bool, + is_root: bool, + root_n: usize, ) -> Result<(), Error>; /// Traverses page table entries recursively and calls the callback for the lastly reached entry /// /// (input) + /// this_level: the current level /// guest: a target guest page to translate - /// level: the intended page-table level to reach + /// last_level: the intended page-table level to reach /// no_valid_check: (if on) omits a validity check which is irrelevant in stage 2 TTE /// func : the callback to be processed /// @@ -148,41 +160,41 @@ pub trait PageTableMethods { /// None fn entry Result>, Error>>( &mut self, + this_level: usize, guest: Page, - level: usize, + last_level: usize, no_valid_check: bool, func: F, + is_root: bool, + root_n: usize, ) -> Result<(Option>, usize), Error>; fn drop(&mut self); - fn unset_page(&mut self, guest: Page); + fn unset_page(&mut self, level: usize, guest: Page, root_n: usize); } -impl PageTable { +impl PageTable { pub fn new() -> Self { Self { entries: core::array::from_fn(|_| E::new()), - level: PhantomData::, address: PhantomData::, } } } -impl PageTableMethods - for PageTable -{ - fn new_with_align(size: usize, align: usize) -> Result<*mut PageTable, Error> { - assert_eq!(N, L::NUM_ENTRIES); +impl PageTableMethods for PageTable { + fn new_with_align(size: usize, align: usize) -> Result<*mut PageTable, Error> { + assert_eq!(N, NUM_ENTRIES); let table = unsafe { Self::alloc_zeroed( - Layout::from_size_align(L::TABLE_SIZE * size, L::TABLE_ALIGN * align).unwrap(), + Layout::from_size_align(TABLE_SIZE * size, TABLE_ALIGN * align).unwrap(), ) }; if table as usize == 0 { return Err(Error::MmAllocFail); } - let table = table as *mut PageTable; + let table = table as *mut PageTable; unsafe { let arr: [E; N] = core::array::from_fn(|_| E::new()); (*table).entries = arr; @@ -190,8 +202,8 @@ impl PageTableMethods Result<*mut PageTable, Error> { - let table = base as *mut PageTable; + fn new_with_base(base: usize) -> Result<*mut PageTable, Error> { + let table = base as *mut PageTable; unsafe { let arr: [E; N] = core::array::from_fn(|_| E::new()); (*table).entries = arr; @@ -201,15 +213,17 @@ impl PageTableMethods( &mut self, + level: usize, guest: PageIter, phys: PageIter, flags: u64, is_raw: bool, + root_n: usize, ) -> Result<(), Error> { let mut phys = phys; for guest in guest { let phys = phys.next().unwrap(); - match self.set_page(guest, phys, flags, is_raw) { + match self.set_page(level, guest, phys, flags, is_raw, true, root_n) { Ok(_) => {} Err(e) => { return Err(e); @@ -219,120 +233,108 @@ impl PageTableMethods( + fn set_page( &mut self, + level: usize, guest: Page, phys: Page, flags: u64, is_raw: bool, + is_root: bool, + root_n: usize, ) -> Result<(), Error> { - assert!(L::THIS_LEVEL == S::MAP_TABLE_LEVEL); + assert!(level <= S::MAP_TABLE_LEVEL); - let index = E::index::(guest.address().into()); - if is_raw { - self.entries[index].set(phys.address(), flags, is_raw) - } else { - self.entries[index].set(phys.address(), flags | S::MAP_EXTRA_FLAG, is_raw) - } - } + let index = E::index_with_level(guest.address().into(), level, is_root, root_n); - default fn entry< - S: PageSize, - F: FnMut(&mut E) -> Result>, Error>, - >( - &mut self, - guest: Page, - level: usize, - no_valid_check: bool, - mut func: F, - ) -> Result<(Option>, usize), Error> { - assert!(L::THIS_LEVEL == S::MAP_TABLE_LEVEL); - if level > S::MAP_TABLE_LEVEL { - return Err(Error::MmInvalidLevel); - } - // TODO: remove the level param out of the entry() and don't check this - if level != L::THIS_LEVEL { - return Err(Error::MmInvalidLevel); - } - - // TODO: check if the index is within the total number of entries - let index = E::index::(guest.address().into()); + if level < S::MAP_TABLE_LEVEL { + self.entries[index].set_with_page_table_flags_via_alloc(index, || { + let subtable = unsafe { + Self::alloc_zeroed(Layout::from_size_align(TABLE_SIZE, TABLE_ALIGN).unwrap()) + } as *mut PageTable; - if no_valid_check { - Ok((func(&mut self.entries[index])?, L::THIS_LEVEL)) - } else { - match self.entries[index].is_valid() { - true => Ok((func(&mut self.entries[index])?, L::THIS_LEVEL)), - false => Err(Error::MmNoEntry), - } - } - } + if subtable as usize != 0 { + let subtable_ptr = subtable; + unsafe { + let arr: [E; NUM_ENTRIES] = core::array::from_fn(|_| E::new()); + (*subtable_ptr).entries = arr; + } + } - default fn drop(&mut self) { - unsafe { - Self::dealloc( - self as *mut PageTable as *mut u8, - Layout::from_size_align(L::TABLE_SIZE, L::TABLE_ALIGN).unwrap(), - ); - } - } + subtable as usize + })?; - default fn unset_page(&mut self, guest: Page) { - let index = E::index::(guest.address().into()); - if self.entries[index].is_valid() { - let _res = self.entry(guest, S::MAP_TABLE_LEVEL, false, |e| { - e.clear(); - Ok(None) - }); + // map the page in the subtable (recursive) + self.subtable_and_set_page(level, guest, phys, flags, is_raw, is_root, root_n) + } else if level == S::MAP_TABLE_LEVEL { + // Map page in this level page table + if is_raw { + self.entries[index].set(phys.address(), flags, is_raw) + } else { + self.entries[index].set(phys.address(), flags | S::MAP_EXTRA_FLAG, is_raw) + } + } else { + Err(Error::MmInvalidLevel) } } -} -/// This overrides default PageTableMethods for PageTables with subtable. -/// (L0Table, L1Table, L2Table) -/// PageTableMethods for L3 Table remains unmodified. -impl PageTableMethods - for PageTable -where - L::NextLevel: Level, - [E; L::NextLevel::NUM_ENTRIES]: Sized, -{ fn entry Result>, Error>>( &mut self, + this_level: usize, page: Page, - level: usize, + last_level: usize, no_valid_check: bool, mut func: F, + is_root: bool, + root_n: usize, ) -> Result<(Option>, usize), Error> { - assert!(L::THIS_LEVEL <= S::MAP_TABLE_LEVEL); - if level > S::MAP_TABLE_LEVEL { + assert!(this_level <= S::MAP_TABLE_LEVEL); + + if last_level > S::MAP_TABLE_LEVEL { return Err(Error::MmInvalidLevel); } - let index = E::index::(page.address().into()); + let index = E::index_with_level(page.address().into(), this_level, is_root, root_n); if no_valid_check { - if L::THIS_LEVEL < level { + if this_level < last_level { // Need to go deeper (recursive) - match self.subtable::(page) { - Ok(subtable) => subtable.entry(page, level, no_valid_check, func), - Err(_e) => Ok((None, L::THIS_LEVEL)), + match self.subtable::(this_level, page, is_root, root_n) { + // TODO: is it okay to pass next level here? + Ok(subtable) => subtable.entry( + this_level + 1, + page, + last_level, + no_valid_check, + func, + false, + root_n, + ), + Err(_e) => Ok((None, this_level)), } } else { // The page is either LargePage or HugePage - Ok((func(&mut self.entries[index])?, L::THIS_LEVEL)) + Ok((func(&mut self.entries[index])?, this_level)) } } else { match self.entries[index].is_valid() { true => { - if L::THIS_LEVEL < level { + if this_level < last_level { // Need to go deeper (recursive) - match self.subtable::(page) { - Ok(subtable) => subtable.entry(page, level, no_valid_check, func), - Err(_e) => Ok((None, L::THIS_LEVEL)), + match self.subtable::(this_level, page, is_root, root_n) { + Ok(subtable) => subtable.entry( + this_level + 1, + page, + last_level, + no_valid_check, + func, + false, + root_n, + ), + Err(_e) => Ok((None, this_level)), } } else { // The page is either LargePage or HugePage - Ok((func(&mut self.entries[index])?, L::THIS_LEVEL)) + Ok((func(&mut self.entries[index])?, this_level)) } } false => Err(Error::MmNoEntry), @@ -340,121 +342,69 @@ where } } - fn set_page( - &mut self, - guest: Page, - phys: Page, - flags: u64, - is_raw: bool, - ) -> Result<(), Error> { - assert!(L::THIS_LEVEL <= S::MAP_TABLE_LEVEL); - - let index = E::index::(guest.address().into()); - - if L::THIS_LEVEL < S::MAP_TABLE_LEVEL { - self.entries[index].set_with_page_table_flags_via_alloc(index, || { - let subtable = unsafe { - Self::alloc_zeroed( - Layout::from_size_align( - L::NextLevel::TABLE_SIZE, - L::NextLevel::TABLE_ALIGN, - ) - .unwrap(), - ) - } - as *mut PageTable; - - if subtable as usize != 0 { - let subtable_ptr = subtable - as *mut PageTable; - unsafe { - let arr: [E; L::NextLevel::NUM_ENTRIES] = - core::array::from_fn(|_| E::new()); - (*subtable_ptr).entries = arr; - } - } - - subtable as usize - })?; - - // map the page in the subtable (recursive) - self.subtable_and_set_page(guest, phys, flags, is_raw) - } else if L::THIS_LEVEL == S::MAP_TABLE_LEVEL { - // Map page in this level page table - if is_raw { - self.entries[index].set(phys.address(), flags, is_raw) - } else { - self.entries[index].set(phys.address(), flags | S::MAP_EXTRA_FLAG, is_raw) - } - } else { - Err(Error::MmInvalidLevel) - } - } - fn drop(&mut self) { - for entry in self.entries.iter() { - //if L::THIS_LEVEL < S::MAP_TABLE_LEVEL && entry.points_to_table_or_page() { - // if a table which can have subtables points to a table or a page, it should be a table. - if entry.points_to_table_or_page() { - let subtable_addr = entry.address(L::THIS_LEVEL).unwrap(); - let subtable: &mut PageTable = unsafe { - &mut *(subtable_addr.as_usize() as *mut PageTable) - }; - subtable.drop(); - } - } unsafe { Self::dealloc( - self as *mut PageTable as *mut u8, - Layout::from_size_align(L::TABLE_SIZE, L::TABLE_SIZE).unwrap(), + self as *mut PageTable as *mut u8, + Layout::from_size_align(TABLE_SIZE, TABLE_ALIGN).unwrap(), ); } } - fn unset_page(&mut self, guest: Page) { - let index = E::index::(guest.address().into()); - + fn unset_page(&mut self, level: usize, guest: Page, root_n: usize) { + let index = E::index_with_level(guest.address().into(), level, true, root_n); if self.entries[index].is_valid() { - let _res = self.entry(guest, S::MAP_TABLE_LEVEL, false, |e| { - e.clear(); - Ok(None) - }); + let _res = self.entry( + level, + guest, + S::MAP_TABLE_LEVEL, + false, + |e| { + e.clear(); + Ok(None) + }, + true, + root_n, + ); } } } -impl PageTable -where - L::NextLevel: Level, -{ +impl PageTable { /// Returns the next subtable for the given page in the page table hierarchy. fn subtable( &self, + level: usize, page: Page, - ) -> Result<&mut PageTable, Error> { - assert!(L::THIS_LEVEL < S::MAP_TABLE_LEVEL); - - let index = E::index::(page.address().into()); - match self.entries[index].subtable(index, L::THIS_LEVEL) { - Ok(table_addr) => { - Ok(unsafe { &mut *(table_addr as *mut PageTable) }) - } + is_root: bool, + root_n: usize, + ) -> Result<&mut PageTable, Error> { + assert!(level < S::MAP_TABLE_LEVEL); + + let index = E::index_with_level(page.address().into(), level, is_root, root_n); + match self.entries[index].subtable(index, level) { + Ok(table_addr) => Ok(unsafe { &mut *(table_addr as *mut PageTable) }), Err(_) => Err(Error::MmSubtableError), } } fn subtable_and_set_page( &mut self, + level: usize, page: Page, phys: Page, flags: u64, is_raw: bool, + is_root: bool, + root_n: usize, ) -> Result<(), Error> { - assert!(L::THIS_LEVEL < S::MAP_TABLE_LEVEL); - - let index = E::index::(page.address().into()); - let table_addr = self.entries[index].subtable(index, L::THIS_LEVEL)?; - let table = unsafe { &mut *(table_addr as *mut PageTable) }; - table.set_page(page, phys, flags, is_raw) + assert!(level < S::MAP_TABLE_LEVEL); + + let index = E::index_with_level(page.address().into(), level, is_root, root_n); + let table_addr = self.entries[index].subtable(index, level)?; + let table = unsafe { &mut *(table_addr as *mut PageTable) }; + // XXX: should we pass next level? + let next_level = level + 1; + table.set_page(next_level, page, phys, flags, is_raw, false, root_n) } } diff --git a/rmm/src/granule/page_table/entry.rs b/rmm/src/granule/page_table/entry.rs index 989e2269e6878..0ab1a3ccef45f 100644 --- a/rmm/src/granule/page_table/entry.rs +++ b/rmm/src/granule/page_table/entry.rs @@ -280,6 +280,17 @@ impl page_table::Entry for Entry { } } + fn index_with_level(addr: usize, level: usize, _is_root: bool, _root_n: usize) -> usize { + match addr_to_idx(addr) { + Ok(idx) => match level { + 0 => (idx * GRANULE_SIZE) / L0_TABLE_ENTRY_SIZE_RANGE, + 1 => ((idx * GRANULE_SIZE) % L0_TABLE_ENTRY_SIZE_RANGE) / GRANULE_SIZE, + _ => panic!(), + }, + Err(_) => panic!(), + } + } + fn subtable(&self, index: usize, _level: usize) -> Result { get_l1_table_addr(index) } diff --git a/rmm/src/granule/page_table/mod.rs b/rmm/src/granule/page_table/mod.rs index db6050da3f4ac..60f8e643ecd04 100644 --- a/rmm/src/granule/page_table/mod.rs +++ b/rmm/src/granule/page_table/mod.rs @@ -113,10 +113,15 @@ macro_rules! get_granule { if let Some(gst) = unsafe { &mut *addr_of_mut!(GRANULE_STATUS_TABLE) } { let pa = Page::::including_address(PhysAddr::from($addr)); - match gst - .root_pgtlb - .entry(pa, 1, false, |e| page_table::Entry::lock(e)) - { + match gst.root_pgtlb.entry( + 0, + pa, + 1, + false, + |e| page_table::Entry::lock(e), + true, + 1, + ) { Ok(guard) => match guard { (Some(g), _level) => Ok(g), _ => Err(MmError::MmNoEntry), diff --git a/rmm/src/granule/page_table/translation.rs b/rmm/src/granule/page_table/translation.rs index 1a17d843affa9..b60b9ecbcc28a 100644 --- a/rmm/src/granule/page_table/translation.rs +++ b/rmm/src/granule/page_table/translation.rs @@ -22,9 +22,8 @@ const_assert_eq!( true ); -type L0PageTable = PageTable::NUM_ENTRIES }>; -pub type L1PageTable = - PageTable::NUM_ENTRIES }>; +type L0PageTable = PageTable::NUM_ENTRIES }>; +pub type L1PageTable = PageTable::NUM_ENTRIES }>; pub struct GranuleStatusTable { pub root_pgtlb: L0PageTable, @@ -52,7 +51,7 @@ impl GranuleStatusTable { } let pa1 = Page::::including_address(PhysAddr::from(addr)); let pa2 = Page::::including_address(PhysAddr::from(addr)); - self.root_pgtlb.set_page(pa1, pa2, state, false) + self.root_pgtlb.set_page(0, pa1, pa2, state, false, true, 1) } } diff --git a/rmm/src/mm/page_table/entry.rs b/rmm/src/mm/page_table/entry.rs index 713d58f04354f..416f0a9e36c10 100644 --- a/rmm/src/mm/page_table/entry.rs +++ b/rmm/src/mm/page_table/entry.rs @@ -108,6 +108,16 @@ impl page_table::Entry for Entry { } } + fn index_with_level(addr: usize, level: usize, _is_root: bool, _root_n: usize) -> usize { + match level { + 0 => RawGPA::from(addr).get_masked_value(RawGPA::L0Index) as usize, + 1 => RawGPA::from(addr).get_masked_value(RawGPA::L1Index) as usize, + 2 => RawGPA::from(addr).get_masked_value(RawGPA::L2Index) as usize, + 3 => RawGPA::from(addr).get_masked_value(RawGPA::L3Index) as usize, + _ => panic!(), + } + } + fn points_to_table_or_page(&self) -> bool { match self.is_valid() { true => match self.0.get_masked_value(PTDesc::TYPE) { diff --git a/rmm/src/mm/translation.rs b/rmm/src/mm/translation.rs index cd55bbf2afd85..9ae98abb436e3 100644 --- a/rmm/src/mm/translation.rs +++ b/rmm/src/mm/translation.rs @@ -58,15 +58,14 @@ pub const ALIGN_ROOT_PAGE: usize = 2; struct Inner<'a> { // We will set the translation granule with 4KB. // To reduce the level of page lookup, initial lookup will start from L1. - root_pgtlb: - &'a mut RootPageTable::NUM_ENTRIES }>, + root_pgtlb: &'a mut RootPageTable::NUM_ENTRIES }>, dirty: bool, } impl<'a> Inner<'a> { pub fn new() -> Self { let root_pgtlb = unsafe { - &mut *RootPageTable::::NUM_ENTRIES }>::new_with_align( + &mut *RootPageTable::::NUM_ENTRIES }>::new_with_align( NUM_ROOT_PAGE, ALIGN_ROOT_PAGE, ) @@ -136,7 +135,7 @@ impl<'a> Inner<'a> { if self .root_pgtlb - .set_pages(virtaddr, phyaddr, flags, false) + .set_pages(1, virtaddr, phyaddr, flags, false, 1) .is_err() { warn!("set_pages error"); @@ -146,7 +145,7 @@ impl<'a> Inner<'a> { fn unset_page(&mut self, addr: usize) { let va = VirtAddr::from(addr); let page = Page::::including_address(va); - self.root_pgtlb.unset_page(page); + self.root_pgtlb.unset_page(1, page, 1); } fn set_pages_for_rmi(&mut self, addr: usize, secure: bool) -> bool { diff --git a/rmm/src/realm/mm/page_table/entry.rs b/rmm/src/realm/mm/page_table/entry.rs index c9460465f4238..962b17c43f42d 100644 --- a/rmm/src/realm/mm/page_table/entry.rs +++ b/rmm/src/realm/mm/page_table/entry.rs @@ -113,6 +113,35 @@ impl page_table::Entry for Entry { } } + fn index_with_level(addr: usize, level: usize, is_root: bool, root_n: usize) -> usize { + match level { + 0 => RawGPA::from(addr).get_masked_value(RawGPA::L0Index) as usize, + 1 => { + if is_root && root_n > 1 { + // We know that refering one direct parent table is enough + // because concatenation of the initial lookup table is upto 16. + let l0 = RawGPA::from(addr).get_masked_value(RawGPA::L0Index) as usize; + let l1 = RawGPA::from(addr).get_masked_value(RawGPA::L1Index) as usize; + // assuming L3Table is a single page-sized + l0 * L3Table::NUM_ENTRIES + l1 + } else { + RawGPA::from(addr).get_masked_value(RawGPA::L1Index) as usize + } + } + 2 => { + if is_root && root_n > 1 { + let l1 = RawGPA::from(addr).get_masked_value(RawGPA::L1Index) as usize; + let l2 = RawGPA::from(addr).get_masked_value(RawGPA::L2Index) as usize; + l1 * L3Table::NUM_ENTRIES + l2 + } else { + RawGPA::from(addr).get_masked_value(RawGPA::L2Index) as usize + } + } + 3 => RawGPA::from(addr).get_masked_value(RawGPA::L3Index) as usize, + _ => panic!(), + } + } + fn points_to_table_or_page(&self) -> bool { match self.is_valid() { true => match self.0.get_masked_value(RawPTE::TYPE) { diff --git a/rmm/src/realm/mm/page_table/mod.rs b/rmm/src/realm/mm/page_table/mod.rs index a8a3bd2389f3c..f52411ac190d5 100644 --- a/rmm/src/realm/mm/page_table/mod.rs +++ b/rmm/src/realm/mm/page_table/mod.rs @@ -76,7 +76,7 @@ impl Level for L3Table { const NUM_ENTRIES: usize = (Self::TABLE_SIZE / core::mem::size_of::()); } -const_assert_size!(PageTable, PAGE_SIZE); -const_assert_size!(PageTable, PAGE_SIZE); -const_assert_size!(PageTable, PAGE_SIZE); -const_assert_size!(PageTable, PAGE_SIZE); +const_assert_size!(PageTable, PAGE_SIZE); +const_assert_size!(PageTable, PAGE_SIZE); +const_assert_size!(PageTable, PAGE_SIZE); +const_assert_size!(PageTable, PAGE_SIZE); diff --git a/rmm/src/realm/mm/stage2_translation.rs b/rmm/src/realm/mm/stage2_translation.rs index beadee2780b64..318761eac1e69 100644 --- a/rmm/src/realm/mm/stage2_translation.rs +++ b/rmm/src/realm/mm/stage2_translation.rs @@ -20,6 +20,8 @@ use armv9a::{bits_in_reg, define_bitfield, define_bits, define_mask}; pub const NUM_ROOT_PAGE: usize = 2; pub const ALIGN_ROOT_PAGE: usize = 2; +const NUM_ENTRIES: usize = 512; // CCH added + pub mod tlbi_ns { pub const IPAS_S: u64 = 0b0; pub const IPAS_NS: u64 = 0b1; @@ -34,28 +36,25 @@ const ENTR8: usize = ENTR1 * 8; const ENTR16: usize = ENTR1 * 16; type RootTBL<'a, const L: usize, const N: usize, const E: usize> = - &'a mut PageTable, entry::Entry, { E }>; + &'a mut PageTable; pub enum Root<'a> { - L0N1(RootTBL<'a, 0, 1, ENTR1>), - L0N16(RootTBL<'a, 0, 16, ENTR16>), - L1N1(RootTBL<'a, 1, 1, ENTR1>), - L1N2(RootTBL<'a, 1, 2, ENTR2>), - L1N8(RootTBL<'a, 1, 8, ENTR8>), - L2N4(RootTBL<'a, 2, 4, ENTR4>), - L2N8(RootTBL<'a, 2, 8, ENTR8>), - L2N16(RootTBL<'a, 2, 16, ENTR16>), + L0N1(RootTBL<'a, 0, 1, ENTR1>, usize, usize), + L0N16(RootTBL<'a, 0, 16, ENTR16>, usize, usize), + L1N1(RootTBL<'a, 1, 1, ENTR1>, usize, usize), + L1N2(RootTBL<'a, 1, 2, ENTR2>, usize, usize), + L1N8(RootTBL<'a, 1, 8, ENTR8>, usize, usize), + L2N4(RootTBL<'a, 2, 4, ENTR4>, usize, usize), + L2N8(RootTBL<'a, 2, 8, ENTR8>, usize, usize), + L2N16(RootTBL<'a, 2, 16, ENTR16>, usize, usize), } #[macro_export] macro_rules! init_table { ($level:expr, $pages:expr, $base:expr) => { - &mut *PageTable::< - GuestPhysAddr, - RootTable<$level, $pages>, - entry::Entry, - { as Level>::NUM_ENTRIES }, - >::new_with_base($base) + &mut *PageTable::::new_with_base( + $base, + ) .unwrap() }; } @@ -76,24 +75,24 @@ impl<'a> Stage2Translation<'a> { let root_pgtlb = match root_level { 0 => unsafe { match root_pages { - 1 => Root::L0N1(init_table!(0, 1, rtt_base)), - 16 => Root::L0N16(init_table!(0, 16, rtt_base)), + 1 => Root::L0N1(init_table!(0, 1, rtt_base), 0, 1), + 16 => Root::L0N16(init_table!(0, 16, rtt_base), 0, 16), _ => todo!(), } }, 1 => unsafe { match root_pages { - 1 => Root::L1N1(init_table!(1, 1, rtt_base)), - 2 => Root::L1N2(init_table!(1, 2, rtt_base)), - 8 => Root::L1N8(init_table!(1, 8, rtt_base)), + 1 => Root::L1N1(init_table!(1, 1, rtt_base), 1, 1), + 2 => Root::L1N2(init_table!(1, 2, rtt_base), 1, 2), + 8 => Root::L1N8(init_table!(1, 8, rtt_base), 1, 8), _ => todo!(), } }, 2 => unsafe { match root_pages { - 4 => Root::L2N4(init_table!(2, 4, rtt_base)), - 8 => Root::L2N8(init_table!(2, 8, rtt_base)), - 16 => Root::L2N16(init_table!(2, 16, rtt_base)), + 4 => Root::L2N4(init_table!(2, 4, rtt_base), 2, 4), + 8 => Root::L2N8(init_table!(2, 8, rtt_base), 2, 8), + 16 => Root::L2N16(init_table!(2, 16, rtt_base), 2, 16), _ => todo!(), } }, @@ -158,46 +157,70 @@ impl<'a> MemAlloc for Stage2Translation<'a> { #[macro_export] // ipa_to_pa closure macro_rules! to_pa { - ($root:expr, $guest:expr, $level:expr, $pa:expr) => { - $root.entry($guest, $level, false, |entry| { - $pa = entry.address(0); - Ok(None) - }) + ($root:expr, $guest:expr, $level:expr, $pa:expr, $root_level:expr, $root_n:expr) => { + $root.entry( + $root_level, + $guest, + $level, + false, + |entry| { + $pa = entry.address(0); + Ok(None) + }, + true, + $root_n, + ) }; } // ipa_to_pa closure macro_rules! to_pte { - ($root:expr, $guest:expr, $level:expr, $pte:expr) => { - $root.entry($guest, $level, true, |entry| { - $pte = entry.pte(); - Ok(None) - }) + ($root:expr, $guest:expr, $level:expr, $pte:expr, $root_level:expr, $root_n:expr) => { + $root.entry( + $root_level, + $guest, + $level, + true, + |entry| { + $pte = entry.pte(); + Ok(None) + }, + true, + $root_n, + ) }; } // ipa_to_pte_set clousre macro_rules! set_pte { - ($root:expr, $guest:expr, $level:expr, $val:expr) => { - $root.entry($guest, $level, true, |entry| { - let pte = entry.mut_pte(); - *pte = RawPTE($val); - Ok(None) - }) + ($root:expr, $guest:expr, $level:expr, $val:expr, $root_level:expr, $root_n:expr) => { + $root.entry( + $root_level, + $guest, + $level, + true, + |entry| { + let pte = entry.mut_pte(); + *pte = RawPTE($val); + Ok(None) + }, + true, + $root_n, + ) }; } impl<'a> IPATranslation for Stage2Translation<'a> { fn get_base_address(&self) -> *const c_void { match &self.root_pgtlb { - Root::L2N8(c) => *c as *const _ as *const c_void, // most likely first, for linux-realm - Root::L0N1(a) => *a as *const _ as *const c_void, - Root::L0N16(a) => *a as *const _ as *const c_void, - Root::L1N1(b) => *b as *const _ as *const c_void, - Root::L1N2(b) => *b as *const _ as *const c_void, - Root::L1N8(b) => *b as *const _ as *const c_void, - Root::L2N4(c) => *c as *const _ as *const c_void, - Root::L2N16(c) => *c as *const _ as *const c_void, + Root::L2N8(c, _, _) => *c as *const _ as *const c_void, // most likely first, for linux-realm + Root::L0N1(a, _, _) => *a as *const _ as *const c_void, + Root::L0N16(a, _, _) => *a as *const _ as *const c_void, + Root::L1N1(b, _, _) => *b as *const _ as *const c_void, + Root::L1N2(b, _, _) => *b as *const _ as *const c_void, + Root::L1N8(b, _, _) => *b as *const _ as *const c_void, + Root::L2N4(c, _, _) => *c as *const _ as *const c_void, + Root::L2N16(c, _, _) => *c as *const _ as *const c_void, } } @@ -217,14 +240,30 @@ impl<'a> IPATranslation for Stage2Translation<'a> { let mut pa = None; let res = match &mut self.root_pgtlb { - Root::L2N8(root) => to_pa!(root, guest, level, pa), // most likely first, for linux-realm - Root::L0N1(root) => to_pa!(root, guest, level, pa), - Root::L0N16(root) => to_pa!(root, guest, level, pa), - Root::L1N1(root) => to_pa!(root, guest, level, pa), - Root::L1N2(root) => to_pa!(root, guest, level, pa), - Root::L1N8(root) => to_pa!(root, guest, level, pa), - Root::L2N4(root) => to_pa!(root, guest, level, pa), - Root::L2N16(root) => to_pa!(root, guest, level, pa), + Root::L2N8(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } // most likely first, for linux-realm + Root::L0N1(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } + Root::L0N16(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } + Root::L1N1(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } + Root::L1N2(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } + Root::L1N8(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } + Root::L2N4(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } + Root::L2N16(root, root_level, root_n) => { + to_pa!(root, guest, level, pa, *root_level, *root_n) + } }; if res.is_ok() { pa @@ -248,14 +287,30 @@ impl<'a> IPATranslation for Stage2Translation<'a> { let guest = Page::::including_address(guest); let mut pte = 0; let res = match &mut self.root_pgtlb { - Root::L2N8(root) => to_pte!(root, guest, level, pte), // most likely first, for linux-realm - Root::L0N1(root) => to_pte!(root, guest, level, pte), - Root::L0N16(root) => to_pte!(root, guest, level, pte), - Root::L1N1(root) => to_pte!(root, guest, level, pte), - Root::L1N2(root) => to_pte!(root, guest, level, pte), - Root::L1N8(root) => to_pte!(root, guest, level, pte), - Root::L2N4(root) => to_pte!(root, guest, level, pte), - Root::L2N16(root) => to_pte!(root, guest, level, pte), + Root::L2N8(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } // most likely first, for linux-realm + Root::L0N1(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } + Root::L0N16(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } + Root::L1N1(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } + Root::L1N2(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } + Root::L1N8(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } + Root::L2N4(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } + Root::L2N16(root, root_level, root_n) => { + to_pte!(root, guest, level, pte, *root_level, *root_n) + } }; if let Ok(x) = res { Some((pte, x.1)) @@ -272,14 +327,30 @@ impl<'a> IPATranslation for Stage2Translation<'a> { ) -> Result<(), Error> { let guest = Page::::including_address(guest); let res = match &mut self.root_pgtlb { - Root::L2N8(root) => set_pte!(root, guest, level, val), - Root::L0N1(root) => set_pte!(root, guest, level, val), - Root::L0N16(root) => set_pte!(root, guest, level, val), - Root::L1N1(root) => set_pte!(root, guest, level, val), - Root::L1N2(root) => set_pte!(root, guest, level, val), - Root::L1N8(root) => set_pte!(root, guest, level, val), - Root::L2N4(root) => set_pte!(root, guest, level, val), - Root::L2N16(root) => set_pte!(root, guest, level, val), + Root::L2N8(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } + Root::L0N1(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } + Root::L0N16(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } + Root::L1N1(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } + Root::L1N2(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } + Root::L1N8(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } + Root::L2N4(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } + Root::L2N16(root, root_level, root_n) => { + set_pte!(root, guest, level, val, *root_level, *root_n) + } }; if let Ok(_x) = res { Ok(()) diff --git a/scripts/clippy.sh b/scripts/clippy.sh index 502aa760d450a..e93a5b07f9f43 100755 --- a/scripts/clippy.sh +++ b/scripts/clippy.sh @@ -19,4 +19,5 @@ cargo clippy --lib -p islet_rmm -- \ -A clippy::redundant_pattern_matching \ -A clippy::type_complexity \ -A clippy::upper-case-acronyms \ + -A clippy::too_many_arguments \ --deny "warnings"