@@ -20,6 +20,8 @@ use ioctls::{KvmRunWrapper, Result};
20
20
use kvm_ioctls:: * ;
21
21
use vmm_sys_util:: errno;
22
22
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;
23
25
use vmm_sys_util:: ioctl:: { ioctl, ioctl_with_mut_ref, ioctl_with_ref, ioctl_with_val} ;
24
26
25
27
/// An address either in programmable I/O space or in memory mapped I/O space.
@@ -1237,6 +1239,91 @@ impl VmFd {
1237
1239
pub fn check_extension ( & self , c : Cap ) -> bool {
1238
1240
self . check_extension_int ( c) > 0
1239
1241
}
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
+ }
1240
1327
}
1241
1328
1242
1329
/// Helper function to create a new `VmFd`.
@@ -1804,4 +1891,15 @@ mod tests {
1804
1891
let vm = kvm. create_vm ( ) . unwrap ( ) ;
1805
1892
assert ! ( vm. check_extension( Cap :: MpState ) ) ;
1806
1893
}
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
+ }
1807
1905
}
0 commit comments