use core::mem;
use aarch64_cpu::registers::*;
use ax_errno::AxResult;
use axvcpu::AxArchPerCpu;
#[repr(C)]
#[repr(align(4096))]
pub struct Aarch64PerCpu {
pub cpu_id: usize,
pub original_vbar_el2: u64,
}
unsafe extern "C" {
fn exception_vector_base_vcpu();
}
impl AxArchPerCpu for Aarch64PerCpu {
fn new(cpu_id: usize) -> AxResult<Self> {
Ok(Self {
cpu_id,
original_vbar_el2: 0,
})
}
fn is_enabled(&self) -> bool {
HCR_EL2.is_set(HCR_EL2::VM)
}
fn hardware_enable(&mut self) -> AxResult {
self.original_vbar_el2 = VBAR_EL2.get();
VBAR_EL2.set(exception_vector_base_vcpu as *const () as usize as _);
HCR_EL2.modify(
HCR_EL2::VM::Enable + HCR_EL2::RW::EL1IsAarch64 + HCR_EL2::TSC::EnableTrapEl1SmcToEl2,
);
Ok(())
}
fn hardware_disable(&mut self) -> AxResult {
VBAR_EL2.set(mem::take(&mut self.original_vbar_el2));
HCR_EL2.set(HCR_EL2::VM::Disable.into());
Ok(())
}
fn max_guest_page_table_levels(&self) -> usize {
crate::vcpu::max_gpt_level(crate::vcpu::pa_bits())
}
}