1 // Copyright 2022 Arm Limited (or its affiliates). All rights reserved. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 use std::any::Any; 6 use std::result; 7 8 use serde::de::Error as SerdeError; 9 use serde::{Deserialize, Serialize}; 10 use serde_json; 11 use thiserror::Error; 12 13 use crate::{CpuState, HypervisorDeviceError, HypervisorVmError}; 14 15 /// Errors thrown while setting up the VGIC. 16 #[derive(Debug, Error)] 17 pub enum Error { 18 /// Error while calling KVM ioctl for setting up the global interrupt controller. 19 #[error("Failed creating GIC device: {0}")] 20 CreateGic(#[source] HypervisorVmError), 21 /// Error while setting device attributes for the GIC. 22 #[error("Failed setting device attributes for the GIC: {0}")] 23 SetDeviceAttribute(#[source] HypervisorDeviceError), 24 /// Error while getting device attributes for the GIC. 25 #[error("Failed getting device attributes for the GIC: {0}")] 26 GetDeviceAttribute(#[source] HypervisorDeviceError), 27 } 28 pub type Result<T> = result::Result<T, Error>; 29 30 #[derive(Debug)] 31 pub struct VgicConfig { 32 pub vcpu_count: u64, 33 pub dist_addr: u64, 34 pub dist_size: u64, 35 pub redists_addr: u64, 36 pub redists_size: u64, 37 pub msi_addr: u64, 38 pub msi_size: u64, 39 pub nr_irqs: u32, 40 } 41 42 #[derive(Clone, Serialize)] 43 pub enum GicState { 44 #[cfg(feature = "kvm")] 45 Kvm(crate::kvm::aarch64::gic::Gicv3ItsState), 46 #[cfg(feature = "mshv")] 47 MshvGicV2M(crate::mshv::aarch64::gic::MshvGicV2MState), 48 } 49 50 impl<'de> Deserialize<'de> for GicState { 51 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> 52 where 53 D: serde::Deserializer<'de>, 54 { 55 // GicStateDefaultDeserialize is a helper enum that mirrors GicState but also derives the Deserialize trait. 56 // This enables backward-compatible deserialization of GicState, facilitating live-upgrade scenarios. 57 #[derive(Deserialize)] 58 pub enum GicStateDefaultDeserialize { 59 #[cfg(feature = "kvm")] 60 Kvm(crate::kvm::aarch64::gic::Gicv3ItsState), 61 #[cfg(feature = "mshv")] 62 MshvGicV2M(crate::mshv::aarch64::gic::MshvGicV2MState), 63 } 64 65 const { 66 assert!( 67 std::mem::size_of::<GicStateDefaultDeserialize>() 68 == std::mem::size_of::<GicState>() 69 ) 70 }; 71 72 let value: serde_json::Value = Deserialize::deserialize(deserializer)?; 73 74 #[cfg(feature = "kvm")] 75 if let Ok(gicv3_its_state) = 76 crate::kvm::aarch64::gic::Gicv3ItsState::deserialize(value.clone()) 77 { 78 return Ok(GicState::Kvm(gicv3_its_state)); 79 } 80 81 if let Ok(gic_state_de) = GicStateDefaultDeserialize::deserialize(value.clone()) { 82 return match gic_state_de { 83 #[cfg(feature = "kvm")] 84 GicStateDefaultDeserialize::Kvm(state) => Ok(GicState::Kvm(state)), 85 #[cfg(feature = "mshv")] 86 GicStateDefaultDeserialize::MshvGicV2M(state) => Ok(GicState::MshvGicV2M(state)), 87 }; 88 } 89 Err(SerdeError::custom("Failed to deserialize GicState")) 90 } 91 } 92 /// Hypervisor agnostic interface for a virtualized GIC 93 pub trait Vgic: Send + Sync { 94 /// Returns the fdt compatibility property of the device 95 fn fdt_compatibility(&self) -> &str; 96 97 /// Returns the maint_irq fdt property of the device 98 fn fdt_maint_irq(&self) -> u32; 99 100 /// Returns an array with GIC device properties 101 fn device_properties(&self) -> [u64; 4]; 102 103 /// Returns the number of vCPUs this GIC handles 104 fn vcpu_count(&self) -> u64; 105 106 /// Returns whether the GIC device is MSI compatible or not 107 fn msi_compatible(&self) -> bool; 108 109 /// Returns the MSI compatibility property of the device 110 fn msi_compatibility(&self) -> &str; 111 112 /// Returns the MSI reg property of the device 113 fn msi_properties(&self) -> [u64; 2]; 114 115 /// Get the values of GICR_TYPER for each vCPU. 116 fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]); 117 118 /// Downcast the trait object to its concrete type. 119 fn as_any_concrete_mut(&mut self) -> &mut dyn Any; 120 121 /// Save the state of GICv3ITS. 122 fn state(&self) -> Result<GicState>; 123 124 /// Restore the state of GICv3ITS. 125 fn set_state(&mut self, state: &GicState) -> Result<()>; 126 127 /// Saves GIC internal data tables into RAM. 128 fn save_data_tables(&self) -> Result<()>; 129 } 130