mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
hypervisor: kvm/x86_64: get and set nested guest state
Since the functionality of [0] was backported to kvm-bindings@v0.12.1 and kvm-ioctls@v0.22.1 [1, 2], we can now save nested KVM state. This way, nesting works across state save/resume and live-migration. [0] https://github.com/rust-vmm/kvm/pull/322 [1] https://github.com/rust-vmm/kvm/pull/349 [2] https://github.com/rust-vmm/kvm/pull/350 Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de> On-behalf-of: SAP philipp.schuster@sap.com
This commit is contained in:
committed by
Rob Bradford
parent
4c16285dde
commit
690741de13
@@ -334,6 +334,10 @@ pub enum HypervisorCpuError {
|
||||
///
|
||||
#[error("Failed to inject NMI")]
|
||||
Nmi(#[source] anyhow::Error),
|
||||
#[error("Failed to get nested guest state")]
|
||||
GetNestedState(#[source] anyhow::Error),
|
||||
#[error("Failed to set nested guest state")]
|
||||
SetNestedState(#[source] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -86,6 +86,8 @@ use std::mem;
|
||||
///
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
pub use kvm_bindings::kvm_vcpu_events as VcpuEvents;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use kvm_bindings::nested::KvmNestedStateBuffer;
|
||||
pub use kvm_bindings::{
|
||||
KVM_GUESTDBG_ENABLE, KVM_GUESTDBG_SINGLESTEP, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI,
|
||||
KVM_MEM_LOG_DIRTY_PAGES, KVM_MEM_READONLY, KVM_MSI_VALID_DEVID, kvm_clock_data,
|
||||
@@ -2442,6 +2444,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let xcrs = self.get_xcrs()?;
|
||||
let lapic_state = self.get_lapic()?;
|
||||
let fpu = self.get_fpu()?;
|
||||
let nested_state = self.nested_state()?;
|
||||
|
||||
// Try to get all MSRs based on the list previously retrieved from KVM.
|
||||
// If the number of MSRs obtained from GET_MSRS is different from the
|
||||
@@ -2516,6 +2519,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
xcrs,
|
||||
mp_state,
|
||||
tsc_khz,
|
||||
nested_state,
|
||||
}
|
||||
.into())
|
||||
}
|
||||
@@ -2683,6 +2687,9 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
self.set_xcrs(&state.xcrs)?;
|
||||
self.set_lapic(&state.lapic_state)?;
|
||||
self.set_fpu(&state.fpu)?;
|
||||
if let Some(nested_state) = state.nested_state {
|
||||
self.set_nested_state(&nested_state)?;
|
||||
}
|
||||
|
||||
if let Some(freq) = state.tsc_khz {
|
||||
self.set_tsc_khz(freq)?;
|
||||
@@ -3036,6 +3043,36 @@ impl KvmVcpu {
|
||||
.set_vcpu_events(events)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into()))
|
||||
}
|
||||
|
||||
/// Get the state of the nested guest from the current vCPU,
|
||||
/// if there is any.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn nested_state(&self) -> cpu::Result<Option<KvmNestedStateBuffer>> {
|
||||
let mut buffer = KvmNestedStateBuffer::empty();
|
||||
|
||||
let maybe_size = self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_nested_state(&mut buffer)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetNestedState(e.into()))?;
|
||||
|
||||
if let Some(_size) = maybe_size {
|
||||
Ok(Some(buffer))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the state of the nested guest for the current vCPU.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn set_nested_state(&self, state: &KvmNestedStateBuffer) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_nested_state(state)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetNestedState(e.into()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -19,6 +19,7 @@ pub use {
|
||||
kvm_bindings::kvm_msr_entry, kvm_bindings::kvm_regs, kvm_bindings::kvm_segment,
|
||||
kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events as VcpuEvents,
|
||||
kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave,
|
||||
kvm_bindings::nested::KvmNestedStateBuffer,
|
||||
};
|
||||
|
||||
use crate::arch::x86::{
|
||||
@@ -75,6 +76,9 @@ pub struct VcpuKvmState {
|
||||
pub xcrs: ExtendedControlRegisters,
|
||||
pub mp_state: MpState,
|
||||
pub tsc_khz: Option<u32>,
|
||||
// Option to prevent useless 8K (de)serialization when no nested
|
||||
// state exists.
|
||||
pub nested_state: Option<KvmNestedStateBuffer>,
|
||||
}
|
||||
|
||||
impl From<SegmentRegister> for kvm_segment {
|
||||
|
||||
Reference in New Issue
Block a user