xref: /cloud-hypervisor/hypervisor/src/arch/aarch64/gic.rs (revision ed63b352d1ebf70f36c7d36a0d6b52fc96186581)
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")]
20     CreateGic(#[source] HypervisorVmError),
21     /// Error while setting device attributes for the GIC.
22     #[error("Failed setting device attributes for the GIC")]
23     SetDeviceAttribute(#[source] HypervisorDeviceError),
24     /// Error while getting device attributes for the GIC.
25     #[error("Failed getting device attributes for the GIC")]
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