diff --git a/Cargo.lock b/Cargo.lock index 9f4125e7a85a07fbcf4687b6d060b02753d4e9ae..ba5625028589ad20a2981a16df63c8c02f5c8135 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,6 +27,8 @@ dependencies = [ "migration_derive", "nix 0.26.2", "once_cell", + "serde", + "serde_json", "thiserror", "trace", "util", diff --git a/address_space/Cargo.toml b/address_space/Cargo.toml index c77820d3f8cd796b2ff0b588a86321e571dddd8c..b563b82ede6e8cce58458ecdefaeaa3cc52e4067 100644 --- a/address_space/Cargo.toml +++ b/address_space/Cargo.toml @@ -15,6 +15,8 @@ arc-swap = "1.6.0" thiserror = "1.0" anyhow = "1.0" once_cell = "1.18.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" machine_manager = { path = "../machine_manager" } migration = { path = "../migration" } migration_derive = { path = "../migration/migration_derive" } diff --git a/address_space/src/address.rs b/address_space/src/address.rs index 658fdc973fe7eb84dff06da29431741cf3445375..fd1a7e6e89e85bfb2868d8b6c4b5c6ea5a9621e5 100644 --- a/address_space/src/address.rs +++ b/address_space/src/address.rs @@ -13,6 +13,8 @@ use std::cmp::{Ord, Ordering, PartialEq, PartialOrd}; use std::ops::{BitAnd, BitOr}; +use serde::{Deserialize, Serialize}; + use util::num_ops::{round_down, round_up}; #[derive(PartialEq, Eq)] @@ -25,7 +27,7 @@ pub enum AddressAttr { } /// Represent the address in given address space. -#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct GuestAddress(pub u64); impl GuestAddress { diff --git a/devices/src/pci/mod.rs b/devices/src/pci/mod.rs index cac725a1dc650d4c962c2c5dd3109e28cf76d7b1..3d9704fb14db17667b8a0984e70affa70bd77dbb 100644 --- a/devices/src/pci/mod.rs +++ b/devices/src/pci/mod.rs @@ -51,10 +51,8 @@ use crate::{ }; #[cfg(feature = "demo_device")] use demo_device::DemoDev; -use migration::{DeviceStateDesc, FieldDesc}; -use migration_derive::{ByteCode, Desc, DescSerde}; - -use self::config::PCIE_CONFIG_SPACE_SIZE; +use migration::DeviceStateDesc; +use migration_derive::DescSerde; const BDF_FUNC_SHIFT: u8 = 3; pub const PCI_SLOT_MAX: u8 = 32; @@ -142,17 +140,16 @@ pub fn pci_ext_cap_next(header: u32) -> usize { ((header >> 20) & 0xffc) as usize } -#[repr(C)] -#[derive(Copy, Clone, Desc, ByteCode)] -#[desc_version(compat_version = "0.1.0")] +#[derive(Clone, Default, DescSerde, Serialize, Deserialize)] +#[desc_version(current_version = "0.1.0")] pub struct PcieState { - config: [u8; PCIE_CONFIG_SPACE_SIZE], - write_mask: [u8; PCIE_CONFIG_SPACE_SIZE], - write_clear_mask: [u8; PCIE_CONFIG_SPACE_SIZE], + config: Vec, + write_mask: Vec, + write_clear_mask: Vec, last_cap_end: u16, last_ext_cap_offset: u16, last_ext_cap_end: u16, - bme: u8, + bme: bool, } #[derive(Clone, DescSerde, Serialize, Deserialize)] @@ -180,38 +177,25 @@ pub struct PciDevBase { impl PciDevBase { pub fn get_pcie_state(&self) -> PcieState { - let mut pcie_state = PcieState::default(); - - pcie_state.config.copy_from_slice(&self.config.config); - pcie_state - .write_mask - .copy_from_slice(&self.config.write_mask); - pcie_state - .write_clear_mask - .copy_from_slice(&self.config.write_clear_mask); - pcie_state.last_cap_end = self.config.last_cap_end; - pcie_state.last_ext_cap_offset = self.config.last_ext_cap_offset; - pcie_state.last_ext_cap_end = self.config.last_ext_cap_end; - pcie_state.bme = u8::from(self.bme.load(Ordering::Acquire)); - - pcie_state - } - - pub fn set_pcie_state(&mut self, pcie_state: &PcieState) -> Result<()> { - self.config.config = pcie_state.config.to_vec(); - self.config.write_mask = pcie_state.write_mask.to_vec(); - self.config.write_clear_mask = pcie_state.write_clear_mask.to_vec(); + PcieState { + config: self.config.config.clone(), + write_mask: self.config.write_mask.clone(), + write_clear_mask: self.config.write_clear_mask.clone(), + last_cap_end: self.config.last_cap_end, + last_ext_cap_offset: self.config.last_ext_cap_offset, + last_ext_cap_end: self.config.last_ext_cap_end, + bme: self.bme.load(Ordering::Acquire), + } + } + + pub fn set_pcie_state(&mut self, pcie_state: &PcieState) { + self.config.config = pcie_state.config.clone(); + self.config.write_mask = pcie_state.write_mask.clone(); + self.config.write_clear_mask = pcie_state.write_clear_mask.clone(); self.config.last_cap_end = pcie_state.last_cap_end; self.config.last_ext_cap_offset = pcie_state.last_ext_cap_end; self.config.last_ext_cap_end = pcie_state.last_ext_cap_end; - - if pcie_state.bme != 0 && pcie_state.bme != 1 { - bail!("Pcie bme state is error: {}", pcie_state.bme); - } - let bme = pcie_state.bme == 1; - self.bme.store(bme, Ordering::Release); - - Ok(()) + self.bme.store(pcie_state.bme, Ordering::Release); } pub fn get_pci_state(&self) -> PciState { diff --git a/machine_manager/src/config/chardev.rs b/machine_manager/src/config/chardev.rs index 0768c6404628ae6cfb49f7ff4b0b7ed9f92c658d..803c69cca65428961a11529c2862ca6dfa8affd7 100644 --- a/machine_manager/src/config/chardev.rs +++ b/machine_manager/src/config/chardev.rs @@ -24,7 +24,7 @@ use crate::config::{valid_id, valid_path, valid_socket_path, ConfigCheck, VmConf use crate::qmp::qmp_schema; /// Default value of max ports for virtio-serial. -pub const DEFAULT_SERIAL_PORTS_NUMBER: usize = 31; +const DEFAULT_SERIAL_PORTS_NUMBER: usize = 31; /// Config structure for virtio-serial-port. #[derive(Parser, Debug, Clone)] diff --git a/machine_manager/src/config/mod.rs b/machine_manager/src/config/mod.rs index 35d705c143f499cd9beaeac76bcb97af7ca0cf9b..e6bb1bfd74d8dd523d8854586977b22ee8b7ea92 100644 --- a/machine_manager/src/config/mod.rs +++ b/machine_manager/src/config/mod.rs @@ -85,8 +85,11 @@ pub const MAX_STRING_LENGTH: usize = 255; pub const MAX_PATH_LENGTH: usize = 4096; // Maximum length of the socket path is restricted by linux. pub const MAX_SOCK_PATH_LENGTH: usize = 108; -// FIXME: `queue_config` len in `VirtioPciState` struct needs to be modified together. pub const MAX_VIRTIO_QUEUE: usize = 32; +// Currently, virito-serial support 64 queues: +// 1) 31 ports, every port has 2 queues. +// 2) 2 control queues. +pub const MAX_SERIAL_VIRTIO_QUEUE: usize = 64; pub const FAST_UNPLUG_ON: &str = "1"; pub const FAST_UNPLUG_OFF: &str = "0"; pub const MAX_NODES: u32 = 128; diff --git a/virtio/src/device/block.rs b/virtio/src/device/block.rs index 0d6cfd52a97facf90ff6d7f2d84427c829da3daf..db35478cbc51d9e348ac9bbbd0abbb18f43cf5a7 100644 --- a/virtio/src/device/block.rs +++ b/virtio/src/device/block.rs @@ -24,6 +24,7 @@ use anyhow::{anyhow, bail, Context, Result}; use byteorder::{ByteOrder, LittleEndian}; use clap::Parser; use log::{error, info, warn}; +use serde::{Deserialize, Serialize}; use vmm_sys_util::{epoll::EventSet, eventfd::EventFd}; use crate::{ @@ -49,10 +50,9 @@ use machine_manager::config::{ use machine_manager::event_loop::{register_event_helper, unregister_event_helper, EventLoop}; use machine_manager::notifier::{register_vm_pause_notifier, unregister_vm_pause_notifier}; use migration::{ - migration::Migratable, DeviceStateDesc, FieldDesc, MigrationHook, MigrationManager, - StateTransfer, + migration::Migratable, DeviceStateDesc, MigrationHook, MigrationManager, StateTransfer, }; -use migration_derive::{ByteCode, Desc}; +use migration_derive::DescSerde; use util::aio::{ iov_from_buf_direct, iov_to_buf_direct, raw_datasync, Aio, AioCb, AioEngine, AioReqResult, Iovec, OpCode, WriteZeroesState, @@ -982,7 +982,7 @@ impl EventNotifierHelper for BlockIoHandler { } #[repr(C, packed)] -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] struct VirtioBlkGeometry { cylinders: u16, heads: u8, @@ -992,7 +992,7 @@ struct VirtioBlkGeometry { impl ByteCode for VirtioBlkGeometry {} #[repr(C, packed)] -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] pub struct VirtioBlkConfig { /// The capacity in 512 byte sectors. capacity: u64, @@ -1037,9 +1037,8 @@ pub struct VirtioBlkConfig { impl ByteCode for VirtioBlkConfig {} /// State of block device. -#[repr(C)] -#[derive(Clone, Copy, Desc, ByteCode)] -#[desc_version(compat_version = "0.1.0")] +#[derive(Clone, Copy, DescSerde, Serialize, Deserialize)] +#[desc_version(current_version = "0.1.0")] pub struct BlockState { /// Bitmask of features supported by the backend. pub device_features: u64, @@ -1503,11 +1502,11 @@ impl StateTransfer for Block { config_space: self.config_space, broken: self.base.broken.load(Ordering::SeqCst), }; - Ok(state.as_bytes().to_vec()) + Ok(serde_json::to_vec(&state)?) } fn set_state_mut(&mut self, state: &[u8]) -> Result<()> { - let state = BlockState::from_bytes(state) + let state: BlockState = serde_json::from_slice(state) .with_context(|| migration::error::MigrationError::FromBytesError("BLOCK"))?; self.base.device_features = state.device_features; self.base.driver_features = state.driver_features; diff --git a/virtio/src/device/serial.rs b/virtio/src/device/serial.rs index 631bd0df143e941c97697335cfdbf5d6bd47dc45..b37961ead56c5ce866398c91732d2694ac5c1a4b 100644 --- a/virtio/src/device/serial.rs +++ b/virtio/src/device/serial.rs @@ -21,6 +21,8 @@ use std::thread::yield_now; use anyhow::{anyhow, bail, Context, Result}; use byteorder::{ByteOrder, LittleEndian}; use log::{error, info, warn}; +use serde::{Deserialize, Serialize}; + use machine_manager::config::ChardevConfig; use machine_manager::notifier::{register_vm_pause_notifier, unregister_vm_pause_notifier}; use vmm_sys_util::epoll::EventSet; @@ -34,15 +36,12 @@ use crate::{ use address_space::{AddressAttr, AddressSpace}; use chardev_backend::chardev::{Chardev, ChardevNotifyDevice, ChardevStatus, InputReceiver}; use machine_manager::{ - config::{ - ChardevType, VirtioSerialInfo, VirtioSerialPortCfg, DEFAULT_SERIAL_PORTS_NUMBER, - DEFAULT_VIRTQUEUE_SIZE, - }, + config::{ChardevType, VirtioSerialInfo, VirtioSerialPortCfg, DEFAULT_VIRTQUEUE_SIZE}, event_loop::EventLoop, event_loop::{register_event_helper, unregister_event_helper}, }; -use migration::{DeviceStateDesc, FieldDesc, MigrationHook, MigrationManager, StateTransfer}; -use migration_derive::{ByteCode, Desc}; +use migration::{DeviceStateDesc, MigrationHook, MigrationManager, StateTransfer}; +use migration_derive::DescSerde; use util::aio::iov_from_buf_direct; use util::byte_code::ByteCode; use util::gen_base_func; @@ -92,7 +91,7 @@ struct VirtioConsoleControl { impl ByteCode for VirtioConsoleControl {} #[repr(C)] -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)] struct VirtioConsoleConfig { // The size of the console is supplied if VIRTIO_CONSOLE_F_SIZE feature is set. cols: u16, @@ -119,9 +118,7 @@ impl VirtioConsoleConfig { } } -#[repr(C)] -#[derive(Copy, Clone, Desc, ByteCode)] -#[desc_version(compat_version = "0.1.0")] +#[derive(Copy, Clone, Default, Serialize, Deserialize)] struct PortState { /// Number id. nr: u32, @@ -132,9 +129,8 @@ struct PortState { } /// Status of serial device. -#[repr(C)] -#[derive(Copy, Clone, Desc, ByteCode)] -#[desc_version(compat_version = "0.1.0")] +#[derive(Clone, Default, DescSerde, Serialize, Deserialize)] +#[desc_version(current_version = "0.1.0")] pub struct VirtioSerialState { /// Bit mask of features supported by the backend. device_features: u64, @@ -142,10 +138,10 @@ pub struct VirtioSerialState { driver_features: u64, /// Virtio serial config space. config_space: VirtioConsoleConfig, - /// Number of serial port. - nr_ports: u32, /// State of serial port. - port_state: [PortState; DEFAULT_SERIAL_PORTS_NUMBER], + port_state: Vec, + /// Device broken status. + broken: bool, } /// Virtio serial device structure. @@ -393,32 +389,31 @@ impl StateTransfer for Serial { device_features: self.base.device_features, driver_features: self.base.driver_features, config_space: self.config_space, + broken: self.base.broken.load(Ordering::SeqCst), ..Default::default() }; - for (index, port) in self.ports.lock().unwrap().iter().enumerate() { + for port in self.ports.lock().unwrap().iter() { let locked_port = port.lock().unwrap(); - state.port_state[index] = PortState { + state.port_state.push(PortState { nr: locked_port.nr, guest_connected: locked_port.guest_connected, host_connected: locked_port.host_connected, - }; - state.nr_ports += 1; + }); } - Ok(state.as_bytes().to_vec()) + Ok(serde_json::to_vec(&state)?) } fn set_state_mut(&mut self, state: &[u8]) -> Result<()> { - let state = VirtioSerialState::from_bytes(state) + let state: VirtioSerialState = serde_json::from_slice(state) .with_context(|| migration::error::MigrationError::FromBytesError("SERIAL"))?; self.base.device_features = state.device_features; self.base.driver_features = state.driver_features; + self.base.broken.store(state.broken, Ordering::SeqCst); self.config_space = state.config_space; - let nr_ports = state.nr_ports as usize; - for i in 0..nr_ports { - let port_state = state.port_state[i]; + for port_state in state.port_state.iter() { let port = find_port_by_nr(&self.ports, port_state.nr) .with_context(|| format!("Don't find port {}", port_state.nr))?; let mut locked_port = port.lock().unwrap(); @@ -1142,6 +1137,7 @@ impl ChardevNotifyDevice for SerialPort { #[cfg(test)] mod tests { use super::*; + use machine_manager::notifier::pause_notify; #[test] fn test_set_driver_features() { @@ -1234,4 +1230,62 @@ mod tests { assert!(serial.read_config(offset, &mut read_data).is_ok()); assert_eq!(read_data, expect_data); } + + // Test register/unregister pause notifier. + #[test] + fn test_pause_notifier() { + let max_ports: u8 = 31; + let mut serial = Serial::new(VirtioSerialInfo { + classtype: "virtio-serial-pci".to_string(), + id: "serial".to_string(), + multifunction: Some(false), + max_ports: u32::from(max_ports), + bus: Some("pcie.0".to_string()), + addr: Some((0, 0)), + }); + + // The realize() will call register_pause_notifier. + serial.realize().unwrap(); + assert_ne!(serial.pause_notifier_id, 0); + + pause_notify(true); + assert_eq!(serial.vm_paused.load(Ordering::SeqCst), true); + + pause_notify(false); + assert_eq!(serial.vm_paused.load(Ordering::SeqCst), false); + + serial.unregister_pause_notifier(); + assert_eq!(serial.pause_notifier_id, 0); + } + + // Test get/set device state. + #[test] + fn test_state_transfer() { + let max_ports: u8 = 31; + let mut serial = Serial::new(VirtioSerialInfo { + classtype: "virtio-serial-pci".to_string(), + id: "serial".to_string(), + multifunction: Some(false), + max_ports: u32::from(max_ports), + bus: Some("pcie.0".to_string()), + addr: Some((0, 0)), + }); + serial.realize().unwrap(); + + let device_features = serial.base.device_features; + let driver_features = serial.base.driver_features; + let broken = serial.base.broken.load(Ordering::SeqCst); + + // Get and modify the device state. + let init_state = serial.get_state_vec().unwrap(); + serial.base.device_features = 0; + serial.base.driver_features = 0; + serial.base.broken.store(true, Ordering::SeqCst); + + // Set and check the device state. + serial.set_state_mut(&init_state).unwrap(); + assert_eq!(device_features, serial.base.device_features); + assert_eq!(driver_features, serial.base.driver_features); + assert_eq!(broken, serial.base.broken.load(Ordering::SeqCst)); + } } diff --git a/virtio/src/lib.rs b/virtio/src/lib.rs index bfef587e889de4e53abf15c5dc80c77380bf1f38..7bd9550b38185cbe24e2382f43110320f48ed080 100644 --- a/virtio/src/lib.rs +++ b/virtio/src/lib.rs @@ -60,13 +60,13 @@ use std::sync::{Arc, Mutex}; use anyhow::{anyhow, bail, Context, Result}; use log::{error, warn}; +use serde::{Deserialize, Serialize}; use vmm_sys_util::eventfd::EventFd; use address_space::{AddressSpace, RegionCache}; use devices::pci::register_pcidevops_type; use devices::sysbus::register_sysbusdevops_type; -use machine_manager::config::ConfigCheck; -use migration_derive::ByteCode; +use machine_manager::config::{ConfigCheck, MAX_SERIAL_VIRTIO_QUEUE, MAX_VIRTIO_QUEUE}; use util::aio::{iov_from_buf_direct, mem_to_buf, Iovec}; use util::byte_code::ByteCode; use util::num_ops::{read_u32, write_u32}; @@ -378,7 +378,7 @@ pub struct VirtioBase { broken: Arc, } -#[derive(Copy, Clone, ByteCode)] +#[derive(Clone, Default, Serialize, Deserialize)] struct VirtioBaseState { device_activated: bool, hfeatures_sel: u32, @@ -388,7 +388,7 @@ struct VirtioBaseState { config_generation: u8, queue_select: u16, config_vector: u16, - queues_config: [QueueConfig; 64], + queues_config: Vec, /// The number of activated queues. queue_num: usize, queue_type: u16, @@ -427,6 +427,7 @@ impl VirtioBase { } fn get_state(&self) -> VirtioBaseState { + let max_queues = std::cmp::max(MAX_VIRTIO_QUEUE, MAX_SERIAL_VIRTIO_QUEUE); let mut state = VirtioBaseState { device_activated: self.device_activated.load(Ordering::Acquire), hfeatures_sel: self.hfeatures_sel, @@ -436,7 +437,7 @@ impl VirtioBase { config_generation: self.config_generation.load(Ordering::Acquire), queue_select: self.queue_select, config_vector: self.config_vector.load(Ordering::Acquire), - queues_config: [QueueConfig::default(); 64], + queues_config: vec![QueueConfig::default(); max_queues], queue_num: 0, queue_type: self.queue_type, }; diff --git a/virtio/src/queue/split.rs b/virtio/src/queue/split.rs index 30a906ffc827a672762620acbeb8fa3068c52327..c0112d77faded4c635e15b84b9554a9567c33490 100644 --- a/virtio/src/queue/split.rs +++ b/virtio/src/queue/split.rs @@ -20,6 +20,7 @@ use std::sync::Arc; use anyhow::{anyhow, bail, Context, Result}; use log::{error, warn}; +use serde::{Deserialize, Serialize}; use super::{ checked_offset_mem, ElemIovec, Element, VringOps, INVALID_VECTOR_NUM, VIRTQ_DESC_F_INDIRECT, @@ -99,7 +100,7 @@ unsafe fn write_object_direct(data: &T, host_addr: u64) -> Result<( .with_context(|| "Failed to write object via host address") } -#[derive(Default, Clone, Copy)] +#[derive(Default, Clone, Copy, Serialize, Deserialize)] pub struct VirtioAddrCache { /// Host virtual address of the descriptor table. pub desc_table_host: u64, @@ -110,7 +111,7 @@ pub struct VirtioAddrCache { } /// The configuration of virtqueue. -#[derive(Default, Clone, Copy)] +#[derive(Default, Clone, Copy, Serialize, Deserialize)] pub struct QueueConfig { /// Guest physical address of the descriptor table. pub desc_table: GuestAddress, diff --git a/virtio/src/transport/virtio_mmio.rs b/virtio/src/transport/virtio_mmio.rs index eb081e1338cbc5fa879577de3afeda1480f4ddf2..c0c56783bee68edf5a9cd318d4026b2e5ba2cf92 100644 --- a/virtio/src/transport/virtio_mmio.rs +++ b/virtio/src/transport/virtio_mmio.rs @@ -16,6 +16,7 @@ use std::sync::{Arc, Mutex}; use anyhow::{anyhow, bail, Context, Result}; use byteorder::{ByteOrder, LittleEndian}; use log::{debug, error, info, warn}; +use serde::{Deserialize, Serialize}; use vmm_sys_util::eventfd::EventFd; use crate::error::VirtioError; @@ -28,9 +29,8 @@ use crate::{ use address_space::{AddressRange, AddressSpace, GuestAddress, RegionIoEventFd}; use devices::sysbus::{SysBus, SysBusDevBase, SysBusDevOps, SysBusDevType}; use devices::{convert_bus_mut, Device, DeviceBase, MUT_SYS_BUS}; -use migration::{DeviceStateDesc, FieldDesc, MigrationHook, MigrationManager, StateTransfer}; -use migration_derive::{ByteCode, Desc}; -use util::byte_code::ByteCode; +use migration::{DeviceStateDesc, MigrationHook, MigrationManager, StateTransfer}; +use migration_derive::DescSerde; use util::gen_base_func; use util::loop_context::create_new_eventfd; @@ -113,9 +113,8 @@ impl HostNotifyInfo { } /// The state of virtio-mmio device. -#[repr(C)] -#[derive(Copy, Clone, Desc, ByteCode)] -#[desc_version(compat_version = "0.1.0")] +#[derive(Clone, Default, DescSerde, Serialize, Deserialize)] +#[desc_version(current_version = "0.1.0")] pub struct VirtioMmioState { virtio_base: VirtioBaseState, } @@ -517,17 +516,12 @@ impl StateTransfer for VirtioMmioDevice { let state = VirtioMmioState { virtio_base: self.device.lock().unwrap().virtio_base().get_state(), }; - Ok(state.as_bytes().to_vec()) + Ok(serde_json::to_vec(&state)?) } fn set_state_mut(&mut self, state: &[u8]) -> Result<()> { - let s_len = std::mem::size_of::(); - if state.len() != s_len { - bail!("Invalid state length {}, expected {}", state.len(), s_len); - } - - let mut mmio_state = VirtioMmioState::default(); - mmio_state.as_mut_bytes().copy_from_slice(state); + let mmio_state: VirtioMmioState = serde_json::from_slice(state) + .with_context(|| migration::error::MigrationError::FromBytesError("MMIO_DEVICE"))?; let mut locked_dev = self.device.lock().unwrap(); locked_dev.virtio_base_mut().set_state( diff --git a/virtio/src/transport/virtio_pci.rs b/virtio/src/transport/virtio_pci.rs index 2bf945ddf83d8163ef8936b6bdffd34f7934913a..17e9d52eebd0938b3d8026c18258d366f7213083 100644 --- a/virtio/src/transport/virtio_pci.rs +++ b/virtio/src/transport/virtio_pci.rs @@ -18,6 +18,7 @@ use std::sync::{Arc, Mutex, Weak}; use anyhow::{anyhow, bail, Context, Result}; use byteorder::{ByteOrder, LittleEndian}; use log::{debug, error, info, warn}; +use serde::{Deserialize, Serialize}; use vmm_sys_util::eventfd::EventFd; #[cfg(feature = "virtio_gpu")] @@ -52,8 +53,8 @@ use devices::pci::{ use devices::{convert_bus_ref, Bus, Device, DeviceBase, PCI_BUS}; #[cfg(feature = "virtio_gpu")] use machine_manager::config::VIRTIO_GPU_ENABLE_BAR0_SIZE; -use migration::{DeviceStateDesc, FieldDesc, MigrationHook, MigrationManager, StateTransfer}; -use migration_derive::{ByteCode, Desc}; +use migration::{DeviceStateDesc, MigrationHook, MigrationManager, StateTransfer}; +use migration_derive::DescSerde; use util::byte_code::ByteCode; use util::num_ops::{ranges_overlap, read_data_u32, write_data_u32}; use util::{gen_base_func, offset_of}; @@ -283,9 +284,8 @@ impl VirtioPciNotifyCap { } /// The state of virtio-pci device. -#[repr(C)] -#[derive(Copy, Clone, Desc, ByteCode)] -#[desc_version(compat_version = "0.1.0")] +#[derive(Clone, Default, DescSerde, Serialize, Deserialize)] +#[desc_version(current_version = "0.1.0")] struct VirtioPciState { dev_id: u16, pcie_state: PcieState, @@ -1276,18 +1276,18 @@ impl StateTransfer for VirtioPciDevice { // Save virtio pci common config state. state.virtio_base = self.device.lock().unwrap().virtio_base().get_state(); - Ok(state.as_bytes().to_vec()) + Ok(serde_json::to_vec(&state)?) } fn set_state_mut(&mut self, state: &[u8]) -> Result<()> { - let virito_pci_state = VirtioPciState::from_bytes(state) + let virito_pci_state: VirtioPciState = serde_json::from_slice(state) .with_context(|| migration::error::MigrationError::FromBytesError("PCI_DEVICE"))?; self.dev_id .store(virito_pci_state.dev_id, Ordering::Release); // Set virtio pci config state. - self.base.set_pcie_state(&virito_pci_state.pcie_state)?; + self.base.set_pcie_state(&virito_pci_state.pcie_state); // Set virtio pci common config state. let mut locked_device = self.device.lock().unwrap();