From fa2b5ca12b35b23c9def34e0d03c2050f247451f Mon Sep 17 00:00:00 2001 From: Jinank Jain Date: Mon, 5 May 2025 04:49:15 +0000 Subject: [PATCH] vmm: hypervisor: Add a new interface to setup GICR for vcpus For MSHV arm64 guest, there is an in-hypervisor GICv2M emulation and for that to work, it needs to be enlightened with the base address of GIC redistributor exposed to guest via FDT. Signed-off-by: Jinank Jain --- hypervisor/src/cpu.rs | 8 +++++++- hypervisor/src/mshv/mod.rs | 18 ++++++++++++++++++ vmm/src/cpu.rs | 21 +++++++++++++++++++++ vmm/src/vm.rs | 23 ++++++++++++++++++++++- 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index afdc532a5..6059499d1 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -590,7 +590,13 @@ pub trait Vcpu: Send + Sync { fn set_sev_control_register(&self, _reg: u64) -> Result<()> { unimplemented!() } - + /// + /// Sets the value of GIC redistributor address + /// + #[cfg(target_arch = "aarch64")] + fn set_gic_redistributor_addr(&self, _gicr_base_addr: u64) -> Result<()> { + Ok(()) + } #[cfg(target_arch = "x86_64")] /// /// Trigger NMI interrupt diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 4f975e7c4..b65fad46e 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -1603,6 +1603,24 @@ impl cpu::Vcpu for MshvVcpu { .request_virtual_interrupt(&cfg) .map_err(|e| cpu::HypervisorCpuError::Nmi(e.into())) } + /// + /// Set the GICR base address for the vcpu. + /// + #[cfg(target_arch = "aarch64")] + fn set_gic_redistributor_addr(&self, gicr_base_addr: u64) -> cpu::Result<()> { + debug!( + "Setting GICR base address to: {:#x}, for vp_index: {:?}", + gicr_base_addr, self.vp_index + ); + let arr_reg_name_value = [( + hv_register_name_HV_ARM64_REGISTER_GICR_BASE_GPA, + gicr_base_addr, + )]; + set_registers_64!(self.fd, arr_reg_name_value) + .map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?; + + Ok(()) + } } impl MshvVcpu { diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 663119e2d..42952d8a3 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -147,6 +147,10 @@ pub enum Error { #[error("Error finalising vCPU: {0}")] VcpuArmFinalize(#[source] hypervisor::HypervisorCpuError), + #[cfg(target_arch = "aarch64")] + #[error("Error initialising GICR base address: {0}")] + VcpuSetGicrBaseAddr(#[source] hypervisor::HypervisorCpuError), + #[error("Failed to join on vCPU threads: {0:?}")] ThreadCleanup(std::boxed::Box), @@ -463,6 +467,23 @@ impl Vcpu { .set_sev_control_register(vmsa_pfn) .map_err(Error::SetSevControlRegister) } + + /// + /// Sets the vCPU's GIC redistributor base address. + /// + #[cfg(target_arch = "aarch64")] + pub fn set_gic_redistributor_addr( + &self, + base_redist_addr: u64, + redist_size: u64, + ) -> Result<()> { + let gicr_base = base_redist_addr + (arch::layout::GIC_V3_REDIST_SIZE * self.id as u64); + assert!(gicr_base + arch::layout::GIC_V3_REDIST_SIZE <= base_redist_addr + redist_size); + self.vcpu + .set_gic_redistributor_addr(gicr_base) + .map_err(Error::VcpuSetGicrBaseAddr)?; + Ok(()) + } } impl Pausable for Vcpu {} diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 66eea3390..bda4a76b1 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -2203,6 +2203,21 @@ impl Vm { #[cfg(feature = "tdx")] let tdx_enabled = self.config.lock().unwrap().is_tdx_enabled(); + #[cfg(target_arch = "aarch64")] + let vgic = self + .device_manager + .lock() + .unwrap() + .get_interrupt_controller() + .unwrap() + .lock() + .unwrap() + .get_vgic() + .unwrap(); + + #[cfg(target_arch = "aarch64")] + let redist_addr = vgic.lock().unwrap().device_properties(); + // Configure the vcpus that have been created let vcpus = self.cpu_manager.lock().unwrap().vcpus(); for vcpu in vcpus { @@ -2211,7 +2226,13 @@ impl Vm { self.cpu_manager .lock() .unwrap() - .configure_vcpu(vcpu, boot_setup) + .configure_vcpu(vcpu.clone(), boot_setup) + .map_err(Error::CpuManager)?; + + #[cfg(target_arch = "aarch64")] + vcpu.lock() + .unwrap() + .set_gic_redistributor_addr(redist_addr[2], redist_addr[3]) .map_err(Error::CpuManager)?; }