From 42d194de3f8211746c9d37f3ee4e35a4fffaac48 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 22 Feb 2018 11:35:05 -0800 Subject: [PATCH] kvm: plumb in KVM_SET_SIGNAL_MASK ioctl We need this ioctl to implement race-free support for kicking/pausing VCPUs. TEST=cargo test --features plugin; cargo test -p kvm; ./build_test BUG=chromium:800626 Change-Id: I5dcff54f7eb34568a8d8503e0dde86b6a36ac693 Signed-off-by: Dmitry Torokhov Reviewed-on: https://chromium-review.googlesource.com/932443 Reviewed-by: Zach Reizner --- kvm/src/lib.rs | 36 +++++++++++++++++++++++++++++++++++- sys_util/src/lib.rs | 2 +- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs index 7eb290ef28..d1488d655b 100644 --- a/kvm/src/lib.rs +++ b/kvm/src/lib.rs @@ -19,10 +19,12 @@ use std::os::raw::*; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use libc::{open, O_RDWR, O_CLOEXEC, EINVAL, ENOSPC, ENOENT}; +use libc::sigset_t; use kvm_sys::*; -use sys_util::{GuestAddress, GuestMemory, MemoryMapping, EventFd, Error, Result, pagesize}; +use sys_util::{GuestAddress, GuestMemory, MemoryMapping, EventFd, + signal, Error, Result, pagesize}; #[allow(unused_imports)] use sys_util::{ioctl, ioctl_with_val, ioctl_with_ref, ioctl_with_mut_ref, ioctl_with_ptr, ioctl_with_mut_ptr}; @@ -939,6 +941,38 @@ impl Vcpu { } Ok(()) } + + /// Specifies set of signals that are blocked during execution of KVM_RUN. + /// Signals that are not blocked will will cause KVM_RUN to return + /// with -EINTR. + /// + /// See the documentation for KVM_SET_SIGNAL_MASK + pub fn set_signal_mask(&self, signals: &[c_int]) -> Result<()> { + let sigset = signal::create_sigset(signals)?; + + let vec_size_bytes = size_of::() + size_of::(); + let vec: Vec = vec![0; vec_size_bytes]; + let kvm_sigmask: &mut kvm_signal_mask = unsafe { + // Converting the vector's memory to a struct is unsafe. + // Carefully using the read-only vector to size and set the members + // ensures no out-of-bounds errors below. + &mut *(vec.as_ptr() as *mut kvm_signal_mask) + }; + kvm_sigmask.len = size_of::() as u32; + unsafe { + std::ptr::copy(&sigset, kvm_sigmask.sigset.as_mut_ptr() as *mut sigset_t, 1); + } + + let ret = unsafe { + // The ioctl is safe because the kernel will only read from the + // kvm_signal_mask structure. + ioctl_with_ref(self, KVM_SET_SIGNAL_MASK(), kvm_sigmask) + }; + if ret < 0 { + return errno_result(); + } + Ok(()) + } } impl AsRawFd for Vcpu { diff --git a/sys_util/src/lib.rs b/sys_util/src/lib.rs index e4547bb410..15c279d56e 100644 --- a/sys_util/src/lib.rs +++ b/sys_util/src/lib.rs @@ -24,7 +24,7 @@ mod poll; mod struct_util; mod tempdir; mod terminal; -mod signal; +pub mod signal; mod fork; mod signalfd; mod sock_ctrl_msg;