Skip to content

Commit

Permalink
realm/mm: add tlbi operations
Browse files Browse the repository at this point in the history
1. Invalidate single leaf entry for a page or block
2. Invalidate by range in case we fold.
   This involves tlbi range operation which requires
   feature addition 'tlb-rmi'.

Signed-off-by: Bokdeuk Jeong <[email protected]>
  • Loading branch information
bokdeuk-jeong committed Aug 14, 2024
1 parent 4c9f6d5 commit 5fda8fa
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 65 deletions.
3 changes: 2 additions & 1 deletion plat/fvp/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ target = "aarch64-unknown-none-softfloat"
[target.aarch64-unknown-none-softfloat]
rustflags = [
"-C", "link-args=-Tplat/fvp/memory.x",
"-C", "target-feature=+ecv"
"-C", "target-feature=+ecv",
"-C", "target-feature=+tlb-rmi"
]
12 changes: 9 additions & 3 deletions rmm/src/realm/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ use core::ffi::c_void;
use core::fmt::Debug;

use address::{GuestPhysAddr, PhysAddr};
use stage2_translation::Tlbi;

pub trait IPATranslation: Debug + Send + Sync {
fn get_base_address(&self) -> *const c_void;
// TODO: remove mut
fn ipa_to_pa(&mut self, guest: GuestPhysAddr, level: usize) -> Option<PhysAddr>;
fn ipa_to_pte(&mut self, guest: GuestPhysAddr, level: usize) -> Option<(u64, usize)>;
fn ipa_to_pte_set(&mut self, guest: GuestPhysAddr, level: usize, val: u64)
-> Result<(), Error>;
fn clean(&mut self);
fn ipa_to_pte_set(
&mut self,
guest: GuestPhysAddr,
level: usize,
val: u64,
invalidate: Tlbi,
) -> Result<(), Error>;
fn clean(&mut self, vmid: usize);
fn space_size(&self, level: usize) -> usize;
}
12 changes: 7 additions & 5 deletions rmm/src/realm/mm/page.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use super::attribute::page_type;
use super::stage2_tte::S2TTE;
use super::table_level::{L1Table, L2Table, L3Table};
use crate::config::{HUGE_PAGE_SIZE, LARGE_PAGE_SIZE, PAGE_SIZE};
use vmsa::page::PageSize;
use vmsa::page_table::Level;

use armv9a::bits_in_reg;

Expand All @@ -10,7 +12,7 @@ use armv9a::bits_in_reg;
pub enum BasePageSize {}
impl PageSize for BasePageSize {
const SIZE: usize = PAGE_SIZE;
const MAP_TABLE_LEVEL: usize = 3;
const MAP_TABLE_LEVEL: usize = L3Table::THIS_LEVEL;
const MAP_EXTRA_FLAG: u64 = bits_in_reg(S2TTE::TYPE, page_type::TABLE_OR_PAGE);
}

Expand All @@ -19,15 +21,15 @@ impl PageSize for BasePageSize {
pub enum LargePageSize {}
impl PageSize for LargePageSize {
const SIZE: usize = LARGE_PAGE_SIZE;
const MAP_TABLE_LEVEL: usize = 2;
const MAP_EXTRA_FLAG: u64 = 0;
const MAP_TABLE_LEVEL: usize = L2Table::THIS_LEVEL;
const MAP_EXTRA_FLAG: u64 = bits_in_reg(S2TTE::TYPE, page_type::BLOCK);
}

#[derive(Clone, Copy)]
/// A 1 GiB page mapped in the L1Table.
pub enum HugePageSize {}
impl PageSize for HugePageSize {
const SIZE: usize = HUGE_PAGE_SIZE;
const MAP_TABLE_LEVEL: usize = 1;
const MAP_EXTRA_FLAG: u64 = 0;
const MAP_TABLE_LEVEL: usize = L1Table::THIS_LEVEL;
const MAP_EXTRA_FLAG: u64 = bits_in_reg(S2TTE::TYPE, page_type::BLOCK);
}
72 changes: 44 additions & 28 deletions rmm/src/realm/mm/rtt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::granule::{set_granule, GranuleState};
use crate::realm::mm::address::GuestPhysAddr;
use crate::realm::mm::attribute::{desc_type, memattr, permission, shareable};
use crate::realm::mm::entry;
use crate::realm::mm::stage2_translation::RttAllocator;
use crate::realm::mm::stage2_translation::{RttAllocator, Tlbi};
use crate::realm::mm::stage2_tte::{invalid_hipas, invalid_ripas, mapping_size, S2TTE};
use crate::realm::mm::stage2_tte::{level_mask, INVALID_UNPROTECTED};
use crate::realm::mm::table_level;
Expand Down Expand Up @@ -54,6 +54,7 @@ fn create_pgtbl_at(
}

pub fn create(rd: &Rd, rtt_addr: usize, ipa: usize, level: usize) -> Result<(), Error> {
let mut invalidate = Tlbi::NONE;
let mut rtt_granule = get_granule_if!(rtt_addr, GranuleState::Delegated)?;

let (parent_s2tte, last_level) = S2TTE::get_s2tte(rd, ipa, level - 1, Error::RmiErrorInput)?;
Expand Down Expand Up @@ -106,6 +107,7 @@ pub fn create(rd: &Rd, rtt_addr: usize, ipa: usize, level: usize) -> Result<(),
.into(); //XXX: check this again

create_pgtbl_at(rtt_addr, flags, pa, map_size)?;
invalidate = Tlbi::LEAF(rd.id());
} else if parent_s2tte.is_assigned_ns(level - 1) {
unimplemented!();
} else if parent_s2tte.is_table(level - 1) {
Expand All @@ -117,9 +119,12 @@ pub fn create(rd: &Rd, rtt_addr: usize, ipa: usize, level: usize) -> Result<(),
set_granule(&mut rtt_granule, GranuleState::RTT)?;

let parent_s2tte = rtt_addr as u64 | bits_in_reg(S2TTE::DESC_TYPE, desc_type::L012_TABLE);
rd.s2_table()
.lock()
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level - 1, parent_s2tte)?;
rd.s2_table().lock().ipa_to_pte_set(
GuestPhysAddr::from(ipa),
level - 1,
parent_s2tte,
invalidate,
)?;

// The below is added to avoid a fault regarding the RTT entry
crate::mm::translation::PageTable::get_ref().map(rtt_addr, true);
Expand All @@ -133,6 +138,7 @@ pub fn destroy<F: FnMut(usize)>(
level: usize,
mut f: F,
) -> Result<(usize, usize), Error> {
let invalidate;
let (parent_s2tte, last_level) = S2TTE::get_s2tte(rd, ipa, level - 1, Error::RmiErrorRtt(0))?;

if (last_level != level - 1) || !parent_s2tte.is_table(level - 1) {
Expand All @@ -152,17 +158,22 @@ pub fn destroy<F: FnMut(usize)>(
// Unless its ref count is 0, RTT DESTROY should fail

let parent_s2tte = if rd.addr_in_par(ipa) {
invalidate = Tlbi::LEAF(rd.id());
bits_in_reg(S2TTE::INVALID_HIPAS, invalid_hipas::UNASSIGNED)
| bits_in_reg(S2TTE::INVALID_RIPAS, invalid_ripas::DESTROYED)
} else {
invalidate = Tlbi::BREAKDOWN(rd.id());
bits_in_reg(S2TTE::NS, 1)
| bits_in_reg(S2TTE::INVALID_HIPAS, invalid_hipas::UNASSIGNED)
| INVALID_UNPROTECTED
};

rd.s2_table()
.lock()
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level - 1, parent_s2tte)?;
rd.s2_table().lock().ipa_to_pte_set(
GuestPhysAddr::from(ipa),
level - 1,
parent_s2tte,
invalidate,
)?;

set_granule(&mut g_rtt, GranuleState::Delegated)?;

Expand Down Expand Up @@ -204,6 +215,7 @@ pub fn init_ripas(rd: &Rd, base: usize, top: usize) -> Result<usize, Error> {
GuestPhysAddr::from(addr),
last_level,
new_s2tte,
Tlbi::NONE,
)?;
} else if !s2tte.is_unassigned_ram() {
break;
Expand Down Expand Up @@ -312,9 +324,12 @@ pub fn map_unprotected(rd: &Rd, ipa: usize, level: usize, host_s2tte: usize) ->
| bits_in_reg(S2TTE::DESC_TYPE, desc_type::L012_BLOCK);
}

rd.s2_table()
.lock()
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level, new_s2tte)?;
rd.s2_table().lock().ipa_to_pte_set(
GuestPhysAddr::from(ipa),
level,
new_s2tte,
Tlbi::LEAF(rd.id()),
)?;

Ok(())
}
Expand Down Expand Up @@ -345,18 +360,12 @@ pub fn unmap_unprotected<F: FnMut(usize)>(
| bits_in_reg(S2TTE::INVALID_HIPAS, invalid_hipas::UNASSIGNED)
| INVALID_UNPROTECTED;

rd.s2_table()
.lock()
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level, new_s2tte)?;

//TODO: add page/block invalidation
/*
if level == RTT_PAGE_LEVEL {
// invalidate the page
} else {
// invalidate the block
}
*/
rd.s2_table().lock().ipa_to_pte_set(
GuestPhysAddr::from(ipa),
level,
new_s2tte,
Tlbi::LEAF(rd.id()),
)?;

let top_ipa = skip_non_live_entries(rd, ipa, level)?;
Ok(top_ipa)
Expand Down Expand Up @@ -386,6 +395,7 @@ pub fn set_ripas(rd: &Rd, base: usize, top: usize, ripas: u8, flags: u64) -> Res
}

while addr < table_top && addr < top {
let mut invalidate = Tlbi::NONE;
let (s2tte, last_level) =
S2TTE::get_s2tte(rd, addr, RTT_PAGE_LEVEL, Error::RmiErrorRtt(level))?;
let mut new_s2tte = 0;
Expand All @@ -412,10 +422,12 @@ pub fn set_ripas(rd: &Rd, base: usize, top: usize, ripas: u8, flags: u64) -> Res
} else if s2tte.is_assigned_ram(level) {
new_s2tte |= bits_in_reg(S2TTE::INVALID_HIPAS, invalid_hipas::ASSIGNED);
add_pa = true;
invalidate = Tlbi::LEAF(rd.id());
} else if s2tte.is_assigned_destroyed() {
if flags & CHANGE_DESTROYED != 0 {
new_s2tte |= bits_in_reg(S2TTE::INVALID_HIPAS, invalid_hipas::ASSIGNED);
add_pa = true;
invalidate = Tlbi::LEAF(rd.id());
} else {
break;
}
Expand Down Expand Up @@ -462,9 +474,12 @@ pub fn set_ripas(rd: &Rd, base: usize, top: usize, ripas: u8, flags: u64) -> Res
if add_pa {
new_s2tte |= pa as u64;
}
rd.s2_table()
.lock()
.ipa_to_pte_set(GuestPhysAddr::from(addr), last_level, new_s2tte)?;
rd.s2_table().lock().ipa_to_pte_set(
GuestPhysAddr::from(addr),
last_level,
new_s2tte,
invalidate,
)?;

addr += map_size;
}
Expand Down Expand Up @@ -507,7 +522,7 @@ pub fn data_create(rd: &Rd, ipa: usize, target_pa: usize, unknown: bool) -> Resu

rd.s2_table()
.lock()
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level, new_s2tte)?;
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level, new_s2tte, Tlbi::NONE)?;

Ok(())
}
Expand All @@ -517,6 +532,7 @@ pub fn data_destroy<F: FnMut(usize)>(
ipa: usize,
mut f: F,
) -> Result<(usize, usize), Error> {
let mut invalidate = Tlbi::NONE;
let level = RTT_PAGE_LEVEL;
let (s2tte, last_level) = S2TTE::get_s2tte(rd, ipa, level, Error::RmiErrorRtt(level))?;

Expand All @@ -540,7 +556,7 @@ pub fn data_destroy<F: FnMut(usize)>(
if s2tte.is_assigned_ram(RTT_PAGE_LEVEL) {
flags |= bits_in_reg(S2TTE::INVALID_HIPAS, invalid_hipas::UNASSIGNED);
flags |= bits_in_reg(S2TTE::INVALID_RIPAS, invalid_ripas::DESTROYED);
// TODO: call invalidate page
invalidate = Tlbi::LEAF(rd.id());
} else if s2tte.is_assigned_empty() {
flags |= bits_in_reg(S2TTE::INVALID_HIPAS, invalid_hipas::UNASSIGNED);
flags |= bits_in_reg(S2TTE::INVALID_RIPAS, invalid_ripas::EMPTY);
Expand All @@ -551,7 +567,7 @@ pub fn data_destroy<F: FnMut(usize)>(
let new_s2tte = flags;
rd.s2_table()
.lock()
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level, new_s2tte)?;
.ipa_to_pte_set(GuestPhysAddr::from(ipa), level, new_s2tte, invalidate)?;

let top_ipa = skip_non_live_entries(rd, ipa, level)?;

Expand Down
Loading

0 comments on commit 5fda8fa

Please sign in to comment.