mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e01933c8ea | ||
|
|
c6307865eb | ||
|
|
6275d4f87e | ||
|
|
4dfe1ff77a | ||
|
|
bbda07c388 | ||
|
|
366223c9f4 | ||
|
|
375356a097 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -148,7 +148,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cloud-hypervisor"
|
||||
version = "21.0.0"
|
||||
version = "21.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"api_client",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cloud-hypervisor"
|
||||
version = "21.0.0"
|
||||
version = "21.1.0"
|
||||
authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2018"
|
||||
default-run = "cloud-hypervisor"
|
||||
|
||||
@@ -443,4 +443,9 @@ pub trait Vcpu: Send + Sync {
|
||||
/// Return suspend registers(explicit and intercept suspend registers)
|
||||
///
|
||||
fn get_suspend_regs(&self) -> Result<SuspendRegisters>;
|
||||
#[cfg(feature = "kvm")]
|
||||
///
|
||||
/// Set the "immediate_exit" state
|
||||
///
|
||||
fn set_immediate_exit(&self, exit: bool);
|
||||
}
|
||||
|
||||
@@ -1574,6 +1574,13 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
tdx_command(&self.fd.as_raw_fd(), TdxCommand::InitVcpu, 0, hob_address)
|
||||
.map_err(cpu::HypervisorCpuError::InitializeTdx)
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the "immediate_exit" state
|
||||
///
|
||||
fn set_immediate_exit(&self, exit: bool) {
|
||||
self.fd.set_kvm_immediate_exit(exit.into());
|
||||
}
|
||||
}
|
||||
|
||||
/// Device struct for KVM
|
||||
|
||||
@@ -130,6 +130,9 @@ pub fn check_required_kvm_extensions(kvm: &Kvm) -> KvmResult<()> {
|
||||
if !kvm.check_extension(Cap::SetTssAddr) {
|
||||
return Err(KvmError::CapabilityMissing(Cap::SetTssAddr));
|
||||
}
|
||||
if !kvm.check_extension(Cap::ImmediateExit) {
|
||||
return Err(KvmError::CapabilityMissing(Cap::ImmediateExit));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
|
||||
@@ -740,6 +740,11 @@ impl PciConfiguration {
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_msg_ctl(LittleEndian::read_u16(data));
|
||||
} else if msix_cap_reg_idx == reg_idx && offset == 0 && data.len() == 4 {
|
||||
msix_config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_msg_ctl((LittleEndian::read_u32(data) >> 16) as u16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
- [v21.1](#v211)
|
||||
- [v21.0](#v210)
|
||||
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade)
|
||||
- [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
|
||||
@@ -183,6 +184,16 @@
|
||||
- [Unit testing](#unit-testing)
|
||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||
|
||||
# v21.1
|
||||
|
||||
This is a bug fix release. The following issues have been addressed:
|
||||
|
||||
* Missing `openat()` syscall from seccomp filter (#3609)
|
||||
* Ensure MMIO/PIO exits complete before pausing (#3658)
|
||||
* Support DWORD writes to MSI-X control register (#3714)
|
||||
* VFIO ioctl reordering to fix MSI on AMD platforms (#3827)
|
||||
* Fix `virtio-net` control queue (#3829)
|
||||
|
||||
# v21.0
|
||||
|
||||
This release has been tracked through the [v21.0
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
Name: cloud-hypervisor
|
||||
Summary: Cloud Hypervisor is an open source Virtual Machine Monitor (VMM) that runs on top of KVM.
|
||||
Version: 21.0
|
||||
Version: 21.1
|
||||
Release: 0%{?dist}
|
||||
License: ASL 2.0 or BSD-3-clause
|
||||
Group: Applications/System
|
||||
@@ -112,6 +112,9 @@ rm -rf %{buildroot}
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Mar 10 2022 Rob Bradford <robert.bradford@intel.com> 21.1-0
|
||||
- Update to 21.1
|
||||
|
||||
* Thu Jan 20 2022 Rob Bradford <robert.bradford@intel.com> 21.0-0
|
||||
- Update to 21.0
|
||||
|
||||
|
||||
@@ -563,10 +563,13 @@ impl VirtioDevice for Net {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
|
||||
let queue_num = queues.len();
|
||||
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
|
||||
if self.common.feature_acked(VIRTIO_NET_F_CTRL_VQ.into()) && queue_num % 2 != 0 {
|
||||
let cvq_queue = queues.remove(queue_num - 1);
|
||||
let mut cvq_queue = queues.remove(queue_num - 1);
|
||||
let cvq_queue_evt = queue_evts.remove(queue_num - 1);
|
||||
|
||||
cvq_queue.set_event_idx(event_idx);
|
||||
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
let mut ctrl_handler = NetCtrlEpollHandler {
|
||||
kill_evt,
|
||||
@@ -599,8 +602,6 @@ impl VirtioDevice for Net {
|
||||
self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
|
||||
}
|
||||
|
||||
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
|
||||
|
||||
let mut epoll_threads = Vec::new();
|
||||
let mut taps = self.taps.clone();
|
||||
for i in 0..queues.len() / 2 {
|
||||
|
||||
@@ -90,7 +90,6 @@ fn virtio_block_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
(libc::SYS_io_uring_enter, vec![]),
|
||||
(libc::SYS_lseek, vec![]),
|
||||
(libc::SYS_mprotect, vec![]),
|
||||
(libc::SYS_openat, vec![]),
|
||||
(libc::SYS_prctl, vec![]),
|
||||
(libc::SYS_pread64, vec![]),
|
||||
(libc::SYS_preadv, vec![]),
|
||||
@@ -130,7 +129,6 @@ fn virtio_mem_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
|
||||
fn virtio_net_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
vec![
|
||||
(libc::SYS_openat, vec![]),
|
||||
(libc::SYS_readv, vec![]),
|
||||
(libc::SYS_timerfd_settime, vec![]),
|
||||
(libc::SYS_writev, vec![]),
|
||||
@@ -258,6 +256,7 @@ fn virtio_thread_common() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
(libc::SYS_madvise, vec![]),
|
||||
(libc::SYS_mmap, vec![]),
|
||||
(libc::SYS_munmap, vec![]),
|
||||
(libc::SYS_openat, vec![]),
|
||||
(libc::SYS_read, vec![]),
|
||||
(libc::SYS_rt_sigprocmask, vec![]),
|
||||
(libc::SYS_sigaltstack, vec![]),
|
||||
|
||||
@@ -792,6 +792,31 @@ impl CpuManager {
|
||||
// to see them in a consistent order in all threads
|
||||
|
||||
if vcpu_pause_signalled.load(Ordering::SeqCst) {
|
||||
// As a pause can be caused by PIO & MMIO exits then we need to ensure they are
|
||||
// completed by returning to KVM_RUN. From the kernel docs:
|
||||
//
|
||||
// For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR, KVM_EXIT_XEN,
|
||||
// KVM_EXIT_EPR, KVM_EXIT_X86_RDMSR and KVM_EXIT_X86_WRMSR the corresponding
|
||||
// operations are complete (and guest state is consistent) only after userspace
|
||||
// has re-entered the kernel with KVM_RUN. The kernel side will first finish
|
||||
// incomplete operations and then check for pending signals.
|
||||
// The pending state of the operation is not preserved in state which is
|
||||
// visible to userspace, thus userspace should ensure that the operation is
|
||||
// completed before performing a live migration. Userspace can re-enter the
|
||||
// guest with an unmasked signal pending or with the immediate_exit field set
|
||||
// to complete pending operations without allowing any further instructions
|
||||
// to be executed.
|
||||
|
||||
#[cfg(feature = "kvm")]
|
||||
{
|
||||
vcpu.lock().as_ref().unwrap().vcpu.set_immediate_exit(true);
|
||||
if !matches!(vcpu.lock().unwrap().run(), Ok(VmExit::Ignore)) {
|
||||
error!("Unexpected VM exit on \"immediate_exit\" run");
|
||||
break;
|
||||
}
|
||||
vcpu.lock().as_ref().unwrap().vcpu.set_immediate_exit(false);
|
||||
}
|
||||
|
||||
vcpu_run_interrupted.store(true, Ordering::SeqCst);
|
||||
while vcpu_pause_signalled.load(Ordering::SeqCst) {
|
||||
thread::park();
|
||||
|
||||
@@ -190,8 +190,8 @@ impl InterruptSourceGroup for MsiInterruptGroup<IrqRoutingEntry> {
|
||||
format!("mask: No existing route for interrupt index {}", index),
|
||||
));
|
||||
}
|
||||
self.set_gsi_routes(&routes)?;
|
||||
return route.disable(&self.vm);
|
||||
route.disable(&self.vm)?;
|
||||
return self.set_gsi_routes(&routes);
|
||||
}
|
||||
|
||||
Err(io::Error::new(
|
||||
@@ -211,8 +211,8 @@ impl InterruptSourceGroup for MsiInterruptGroup<IrqRoutingEntry> {
|
||||
format!("mask: No existing route for interrupt index {}", index),
|
||||
));
|
||||
}
|
||||
self.set_gsi_routes(&routes)?;
|
||||
return route.enable(&self.vm);
|
||||
route.enable(&self.vm)?;
|
||||
return self.set_gsi_routes(&routes);
|
||||
}
|
||||
|
||||
Err(io::Error::new(
|
||||
|
||||
Reference in New Issue
Block a user