use super::{Vcpu, VirtualizationError};
use crate::PhysAddr;
#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GStageMode {
Sv39x4 = 8,
Sv48x4 = 9,
}
impl GStageMode {
pub const fn levels(self) -> usize {
match self {
Self::Sv39x4 => 3,
Self::Sv48x4 => 4,
}
}
pub const fn guest_address_bits(self) -> usize {
match self {
Self::Sv39x4 => 41,
Self::Sv48x4 => 50,
}
}
}
impl Vcpu {
pub fn set_page_table(
&mut self,
root: PhysAddr,
mode: GStageMode,
) -> Result<(), VirtualizationError> {
let address = root.as_usize();
if address & 0x3fff != 0 || address >> 56 != 0 {
return Err(VirtualizationError::InvalidRoot);
}
self.virtual_hs_csrs.hgatp = ((mode as usize) << 60) | (address >> 12);
Ok(())
}
}
pub unsafe fn invalidate_gstage_translations() {
unsafe {
core::arch::asm!(
".option push",
".option arch, +h",
"hfence.gvma",
".option pop",
options(nostack)
);
}
}