// Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. // // StratoVirt is licensed under Mulan PSL v2. // You can use this software according to the terms and conditions of the Mulan // PSL v2. // You may obtain a copy of Mulan PSL v2 at: // http://license.coscl.org.cn/MulanPSL2 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. use anyhow::Context; use kvm_bindings::{kvm_clock_data, kvm_irqchip, kvm_pit_state2, KVM_IRQCHIP_IOAPIC}; use hypervisor::kvm::KVM_FDS; use migration::{ DeviceStateDesc, FieldDesc, MigrationError, MigrationHook, MigrationManager, StateTransfer, }; use migration_derive::{ByteCode, Desc}; use util::byte_code::ByteCode; /// Structure to wrapper kvm_device related function. pub struct KvmDevice {} /// Status of kvm device. /// Kvm device include pit, kvm_clock, irq on x86_64 platform. #[repr(C)] #[derive(Copy, Clone, Desc, ByteCode)] #[desc_version(compat_version = "0.1.0")] pub struct KvmDeviceState { pit_state: kvm_pit_state2, kvm_clock: kvm_clock_data, ioapic: kvm_irqchip, } impl StateTransfer for KvmDevice { fn get_state_vec(&self) -> migration::Result<Vec<u8>> { let kvm_fds = KVM_FDS.load(); let vm_fd = kvm_fds.vm_fd.as_ref().unwrap(); // save pit let pit_state = vm_fd.get_pit2()?; // save kvm_clock let mut kvm_clock = vm_fd.get_clock()?; // Reset kvm clock flag. kvm_clock.flags = 0; // save ioapic let mut ioapic = kvm_irqchip { chip_id: KVM_IRQCHIP_IOAPIC, ..Default::default() }; vm_fd.get_irqchip(&mut ioapic)?; Ok(KvmDeviceState { pit_state, kvm_clock, ioapic, } .as_bytes() .to_vec()) } fn set_state(&self, state: &[u8]) -> migration::Result<()> { let kvm_fds = KVM_FDS.load(); let vm_fd = kvm_fds.vm_fd.as_ref().unwrap(); let kvm_state = KvmDeviceState::from_bytes(state) .with_context(|| MigrationError::FromBytesError("KVM_DEVICE"))?; vm_fd.set_pit2(&kvm_state.pit_state)?; vm_fd.set_clock(&kvm_state.kvm_clock)?; vm_fd.set_irqchip(&kvm_state.ioapic)?; Ok(()) } fn get_device_alias(&self) -> u64 { MigrationManager::get_desc_alias(&KvmDeviceState::descriptor().name).unwrap_or(!0) } } impl MigrationHook for KvmDevice {}