devices: pvpanic: add method for DeviceManager

Add method for DeviceManager to invoke.

Signed-off-by: Yi Wang <foxywang@tencent.com>
Signed-off-by: Rob Bradford <rbradford@rivosinc.com>
This commit is contained in:
Yi Wang 2023-06-15 12:02:45 +08:00 committed by Rob Bradford
parent 8e9ce3ab7c
commit d99c0c0d1d
7 changed files with 69 additions and 0 deletions

View File

@ -25,6 +25,7 @@ pub mod pvpanic;
pub mod tpm; pub mod tpm;
pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice}; pub use self::acpi::{AcpiGedDevice, AcpiPmTimerDevice, AcpiShutdownDevice};
pub use self::pvpanic::{PvPanicDevice, PVPANIC_DEVICE_MMIO_SIZE};
bitflags! { bitflags! {
pub struct AcpiNotificationFlags: u8 { pub struct AcpiNotificationFlags: u8 {

View File

@ -136,6 +136,10 @@ impl PvPanicDevice {
events: self.events, events: self.events,
} }
} }
pub fn config_bar_addr(&self) -> u64 {
self.configuration.get_bar_addr(0)
}
} }
impl BusDevice for PvPanicDevice { impl BusDevice for PvPanicDevice {

View File

@ -225,6 +225,10 @@ pub struct TopLevel {
/// cid=<context_id>, socket=<socket_path>, iommu=on|off, id=<device_id>, pci_segment=<segment_id> /// cid=<context_id>, socket=<socket_path>, iommu=on|off, id=<device_id>, pci_segment=<segment_id>
vsock: Option<String>, vsock: Option<String>,
#[argh(switch, long = "pvpanic")]
/// enable pvpanic device
pvpanic: bool,
#[argh(option, long = "numa")] #[argh(option, long = "numa")]
/// guest_numa_id=<node_id>, cpus=<cpus_id>, distances=<list_of_distances_to_destination_nodes>, memory_zones=<list_of_memory_zones>, sgx_epc_sections=<list_of_sgx_epc_sections> /// guest_numa_id=<node_id>, cpus=<cpus_id>, distances=<list_of_distances_to_destination_nodes>, memory_zones=<list_of_memory_zones>, sgx_epc_sections=<list_of_sgx_epc_sections>
numa: Vec<String>, numa: Vec<String>,
@ -349,6 +353,9 @@ impl TopLevel {
}; };
let vsock = self.vsock.as_deref(); let vsock = self.vsock.as_deref();
let pvpanic = self.pvpanic;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
let sgx_epc = if !self.sgx_epc.is_empty() { let sgx_epc = if !self.sgx_epc.is_empty() {
Some(self.sgx_epc.iter().map(|x| x.as_str()).collect()) Some(self.sgx_epc.iter().map(|x| x.as_str()).collect())
@ -387,6 +394,7 @@ impl TopLevel {
user_devices, user_devices,
vdpa, vdpa,
vsock, vsock,
pvpanic,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
sgx_epc, sgx_epc,
numa, numa,
@ -773,6 +781,7 @@ mod unit_tests {
user_devices: None, user_devices: None,
vdpa: None, vdpa: None,
vsock: None, vsock: None,
pvpanic: false,
iommu: false, iommu: false,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
sgx_epc: None, sgx_epc: None,

View File

@ -370,6 +370,7 @@ pub struct VmParams<'a> {
pub user_devices: Option<Vec<&'a str>>, pub user_devices: Option<Vec<&'a str>>,
pub vdpa: Option<Vec<&'a str>>, pub vdpa: Option<Vec<&'a str>>,
pub vsock: Option<&'a str>, pub vsock: Option<&'a str>,
pub pvpanic: bool,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub sgx_epc: Option<Vec<&'a str>>, pub sgx_epc: Option<Vec<&'a str>>,
pub numa: Option<Vec<&'a str>>, pub numa: Option<Vec<&'a str>>,
@ -2084,6 +2085,7 @@ impl VmConfig {
user_devices, user_devices,
vdpa, vdpa,
vsock, vsock,
pvpanic: vm_params.pvpanic,
iommu: false, // updated in VmConfig::validate() iommu: false, // updated in VmConfig::validate()
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
sgx_epc, sgx_epc,
@ -2767,6 +2769,7 @@ mod tests {
user_devices: None, user_devices: None,
vdpa: None, vdpa: None,
vsock: None, vsock: None,
pvpanic: false,
iommu: false, iommu: false,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
sgx_epc: None, sgx_epc: None,

View File

@ -114,6 +114,7 @@ const RNG_DEVICE_NAME: &str = "__rng";
const IOMMU_DEVICE_NAME: &str = "__iommu"; const IOMMU_DEVICE_NAME: &str = "__iommu";
const BALLOON_DEVICE_NAME: &str = "__balloon"; const BALLOON_DEVICE_NAME: &str = "__balloon";
const CONSOLE_DEVICE_NAME: &str = "__console"; const CONSOLE_DEVICE_NAME: &str = "__console";
const PVPANIC_DEVICE_NAME: &str = "__pvpanic";
// Devices that the user may name and for which we generate // Devices that the user may name and for which we generate
// identifiers if the user doesn't give one // identifiers if the user doesn't give one
@ -470,6 +471,9 @@ pub enum DeviceManagerError {
/// Failed retrieving device state from snapshot /// Failed retrieving device state from snapshot
RestoreGetState(MigratableError), RestoreGetState(MigratableError),
/// Cannot create a PvPanic device
PvPanicCreate(devices::pvpanic::PvPanicError),
} }
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>; pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
@ -931,6 +935,9 @@ pub struct DeviceManager {
// GPIO device for AArch64 // GPIO device for AArch64
gpio_device: Option<Arc<Mutex<devices::legacy::Gpio>>>, gpio_device: Option<Arc<Mutex<devices::legacy::Gpio>>>,
// pvpanic device
pvpanic_device: Option<Arc<Mutex<devices::PvPanicDevice>>>,
// Flag to force setting the iommu on virtio devices // Flag to force setting the iommu on virtio devices
force_iommu: bool, force_iommu: bool,
@ -1122,6 +1129,7 @@ impl DeviceManager {
virtio_mem_devices: Vec::new(), virtio_mem_devices: Vec::new(),
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
gpio_device: None, gpio_device: None,
pvpanic_device: None,
force_iommu, force_iommu,
io_uring_supported: None, io_uring_supported: None,
boot_id_list, boot_id_list,
@ -1245,6 +1253,10 @@ impl DeviceManager {
self.virtio_devices = virtio_devices; self.virtio_devices = virtio_devices;
if self.config.clone().lock().unwrap().pvpanic {
self.pvpanic_device = self.add_pvpanic_device()?;
}
Ok(()) Ok(())
} }
@ -3604,6 +3616,43 @@ impl DeviceManager {
Ok(pci_device_bdf) Ok(pci_device_bdf)
} }
fn add_pvpanic_device(
&mut self,
) -> DeviceManagerResult<Option<Arc<Mutex<devices::PvPanicDevice>>>> {
let id = String::from(PVPANIC_DEVICE_NAME);
let pci_segment_id = 0x0_u16;
info!("Creating pvpanic device {}", id);
let (pci_segment_id, pci_device_bdf, resources) =
self.pci_resources(&id, pci_segment_id)?;
let snapshot = snapshot_from_id(self.snapshot.as_ref(), id.as_str());
let pvpanic_device = devices::PvPanicDevice::new(id.clone(), snapshot)
.map_err(DeviceManagerError::PvPanicCreate)?;
let pvpanic_device = Arc::new(Mutex::new(pvpanic_device));
let new_resources = self.add_pci_device(
pvpanic_device.clone(),
pvpanic_device.clone(),
pci_segment_id,
pci_device_bdf,
resources,
)?;
let mut node = device_node!(id, pvpanic_device);
node.resources = new_resources;
node.pci_bdf = Some(pci_device_bdf);
node.pci_device_handle = None;
self.device_tree.lock().unwrap().insert(id, node);
Ok(Some(pvpanic_device))
}
fn pci_resources( fn pci_resources(
&self, &self,
id: &str, id: &str,

View File

@ -2197,6 +2197,7 @@ mod unit_tests {
user_devices: None, user_devices: None,
vdpa: None, vdpa: None,
vsock: None, vsock: None,
pvpanic: false,
iommu: false, iommu: false,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
sgx_epc: None, sgx_epc: None,

View File

@ -586,6 +586,8 @@ pub struct VmConfig {
pub vdpa: Option<Vec<VdpaConfig>>, pub vdpa: Option<Vec<VdpaConfig>>,
pub vsock: Option<VsockConfig>, pub vsock: Option<VsockConfig>,
#[serde(default)] #[serde(default)]
pub pvpanic: bool,
#[serde(default)]
pub iommu: bool, pub iommu: bool,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub sgx_epc: Option<Vec<SgxEpcConfig>>, pub sgx_epc: Option<Vec<SgxEpcConfig>>,