Skip to content

Commit 7ed4701

Browse files
rvolosatovsandreeaflorescu
authored andcommitted
Add support for KVM_MEMORY_ENCRYPT_OP
Signed-off-by: Roman Volosatovs <[email protected]>
1 parent de9b419 commit 7ed4701

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

src/ioctls/vm.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use ioctls::{KvmRunWrapper, Result};
2020
use kvm_ioctls::*;
2121
use vmm_sys_util::errno;
2222
use vmm_sys_util::eventfd::EventFd;
23+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
24+
use vmm_sys_util::ioctl::ioctl_with_mut_ptr;
2325
use vmm_sys_util::ioctl::{ioctl, ioctl_with_mut_ref, ioctl_with_ref, ioctl_with_val};
2426

2527
/// An address either in programmable I/O space or in memory mapped I/O space.
@@ -1237,6 +1239,91 @@ impl VmFd {
12371239
pub fn check_extension(&self, c: Cap) -> bool {
12381240
self.check_extension_int(c) > 0
12391241
}
1242+
1243+
/// Issues platform-specific memory encryption commands to manage encrypted VMs if
1244+
/// the platform supports creating those encrypted VMs.
1245+
///
1246+
/// Currently, this ioctl is used for issuing Secure Encrypted Virtualization
1247+
/// (SEV) commands on AMD Processors.
1248+
///
1249+
/// See the documentation for `KVM_MEMORY_ENCRYPT_OP` in the
1250+
/// [KVM API doc](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt).
1251+
///
1252+
/// For SEV-specific functionality, prefer safe wrapper:
1253+
/// - [`encrypt_op_sev`](Self::encrypt_op_sev)
1254+
///
1255+
/// # Safety
1256+
///
1257+
/// This function is unsafe because there is no guarantee `T` is valid in this context, how
1258+
/// much data kernel will read from memory and where it will write data on error.
1259+
///
1260+
/// # Arguments
1261+
///
1262+
/// * `op` - an opaque platform specific structure.
1263+
///
1264+
/// # Example
1265+
#[cfg_attr(has_sev, doc = "```rust")]
1266+
#[cfg_attr(not(has_sev), doc = "```rust,no_run")]
1267+
/// # extern crate kvm_ioctls;
1268+
/// # extern crate kvm_bindings;
1269+
/// use kvm_bindings::bindings::kvm_sev_cmd;
1270+
/// # use kvm_ioctls::Kvm;
1271+
///
1272+
/// let kvm = Kvm::new().unwrap();
1273+
/// let vm = kvm.create_vm().unwrap();
1274+
///
1275+
/// // Initialize the SEV platform context.
1276+
/// let mut init: kvm_sev_cmd = Default::default();
1277+
/// unsafe { vm.encrypt_op(&mut init).unwrap() };
1278+
/// ```
1279+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1280+
pub unsafe fn encrypt_op<T>(&self, op: *mut T) -> Result<()> {
1281+
let ret = ioctl_with_mut_ptr(self, KVM_MEMORY_ENCRYPT_OP(), op);
1282+
if ret == 0 {
1283+
Ok(())
1284+
} else {
1285+
Err(errno::Error::last())
1286+
}
1287+
}
1288+
1289+
/// Issue common lifecycle events of SEV guests, such as launching, running, snapshotting,
1290+
/// migrating and decommissioning via `KVM_MEMORY_ENCRYPT_OP` ioctl.
1291+
///
1292+
/// Kernel documentation states that this ioctl can be used for testing whether SEV is enabled
1293+
/// by sending `NULL`. To do that, pass [`std::ptr::null_mut`](std::ptr::null_mut) to [`encrypt_op`](Self::encrypt_op).
1294+
///
1295+
/// See the documentation for Secure Encrypted Virtualization (SEV).
1296+
///
1297+
/// # Arguments
1298+
///
1299+
/// * `op` - SEV-specific structure. For details check the
1300+
/// [Secure Encrypted Virtualization (SEV) doc](https://www.kernel.org/doc/Documentation/virtual/kvm/amd-memory-encryption.rst).
1301+
///
1302+
/// # Example
1303+
#[cfg_attr(has_sev, doc = "```rust")]
1304+
#[cfg_attr(not(has_sev), doc = "```rust,no_run")]
1305+
/// # extern crate kvm_ioctls;
1306+
/// # extern crate kvm_bindings;
1307+
/// # use std::{os::raw::c_void, ptr::null_mut};
1308+
/// use kvm_bindings::bindings::kvm_sev_cmd;
1309+
/// # use kvm_ioctls::Kvm;
1310+
///
1311+
/// let kvm = Kvm::new().unwrap();
1312+
/// let vm = kvm.create_vm().unwrap();
1313+
///
1314+
/// // Check whether SEV is enabled, optional.
1315+
/// assert!(unsafe { vm.encrypt_op(null_mut() as *mut c_void) }.is_ok());
1316+
///
1317+
/// // Initialize the SEV platform context.
1318+
/// let mut init: kvm_sev_cmd = Default::default();
1319+
/// vm.encrypt_op_sev(&mut init).unwrap();
1320+
/// ```
1321+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1322+
pub fn encrypt_op_sev(&self, op: &mut kvm_sev_cmd) -> Result<()> {
1323+
// Safe because we know that kernel will only read the correct amount of memory from our pointer
1324+
// and we know where it will write it (op.error).
1325+
unsafe { self.encrypt_op(op) }
1326+
}
12401327
}
12411328

12421329
/// Helper function to create a new `VmFd`.
@@ -1804,4 +1891,15 @@ mod tests {
18041891
let vm = kvm.create_vm().unwrap();
18051892
assert!(vm.check_extension(Cap::MpState));
18061893
}
1894+
1895+
#[test]
1896+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1897+
#[cfg_attr(not(has_sev), ignore)]
1898+
fn test_encrypt_op_sev() {
1899+
let kvm = Kvm::new().unwrap();
1900+
let vm = kvm.create_vm().unwrap();
1901+
1902+
let mut init: kvm_sev_cmd = Default::default();
1903+
assert!(vm.encrypt_op_sev(&mut init).is_ok());
1904+
}
18071905
}

0 commit comments

Comments
 (0)