Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kvm-ioctls/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Upcoming Release

- Plumb through KVM_CAP_DIRTY_LOG_RING as DirtyLogRing cap.
- [[#359]](https://github.com/rust-vmm/kvm/pull/359) Add support for `KVM_SET_MSR_FILTER` vm ioctl on x86_64.

## v0.24.0

Expand Down
2 changes: 2 additions & 0 deletions kvm-ioctls/src/cap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ pub enum Cap {
#[cfg(target_arch = "x86_64")]
X86UserSpaceMsr = KVM_CAP_X86_USER_SPACE_MSR,
#[cfg(target_arch = "x86_64")]
X86MsrFilter = KVM_CAP_X86_MSR_FILTER,
#[cfg(target_arch = "x86_64")]
ExitHypercall = KVM_CAP_EXIT_HYPERCALL,
#[cfg(target_arch = "x86_64")]
MemoryFaultInfo = KVM_CAP_MEMORY_FAULT_INFO,
Expand Down
78 changes: 78 additions & 0 deletions kvm-ioctls/src/ioctls/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,44 @@ impl VmFd {
}
}

/// Sets the MSR filter as per the `KVM_X86_SET_MSR_FILTER` ioctl.
///
/// See the documentation for `KVM_X86_SET_MSR_FILTER` in the
/// [KVM API doc](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt).
///
/// # Arguments
///
/// * `filter` - MSR filter configuration to be set.
///
/// # Safety
///
/// The caller must ensure that the given `kvm_msr_filter` is valid. Specifically any `bitmap` pointers in the `kvm_msr_filter_range`
/// structures within `filter.ranges` must point to valid memory of sufficient size.
/// # Example
///
/// ```rust
/// # extern crate kvm_bindings;
/// # extern crate kvm_ioctls;
/// # use kvm_bindings::kvm_msr_filter;
/// # use kvm_ioctls::Kvm;
/// let kvm = Kvm::new().unwrap();
/// let vm = kvm.create_vm().unwrap();
/// let mut filter = kvm_msr_filter::default();
/// // Safety: filter is valid
/// unsafe { vm.set_msr_filter(&mut filter).unwrap() };
/// ```
#[cfg(target_arch = "x86_64")]
pub unsafe fn set_msr_filter(&self, filter: &kvm_msr_filter) -> Result<()> {
// SAFETY: Safe because we call this with a Vm fd and we trust the kernel, and the caller
// has promised validity of the filter structure.
let ret = unsafe { ioctl_with_ref(self, KVM_SET_MSR_FILTER(), filter) };
if ret == 0 {
Ok(())
} else {
Err(errno::Error::last())
}
}

/// Directly injects a MSI message as per the `KVM_SIGNAL_MSI` ioctl.
///
/// See the documentation for `KVM_SIGNAL_MSI`.
Expand Down Expand Up @@ -2900,4 +2938,44 @@ mod tests {
vm.has_device_attr(&dist_attr).unwrap();
vm.set_device_attr(&dist_attr).unwrap();
}

#[test]
#[cfg(target_arch = "x86_64")]
fn test_set_msr_filter() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();

if !kvm.check_extension(Cap::X86MsrFilter) {
return;
}

let empty_filter = kvm_msr_filter {
flags: KVM_MSR_FILTER_DEFAULT_ALLOW,
ranges: [kvm_msr_filter_range::default(); 16],
};
// Safety: empty_filter is valid
unsafe { vm.set_msr_filter(&empty_filter).unwrap() };

// From KVM API:
// Calling this ioctl with an empty set of ranges (all nmsrs == 0) disables MSR filtering. In that mode, KVM_MSR_FILTER_DEFAULT_DENY is invalid and causes an error.
let empty_deny_filter = kvm_msr_filter {
flags: KVM_MSR_FILTER_DEFAULT_DENY,
ranges: [kvm_msr_filter_range::default(); 16],
};
// Safety: empty_deny_filter is invalid
unsafe { vm.set_msr_filter(&empty_deny_filter).unwrap_err() };

// disable access to all except 1 MSR
let mut filter = kvm_msr_filter {
flags: KVM_MSR_FILTER_DEFAULT_DENY,
ranges: [kvm_msr_filter_range::default(); 16],
};
let mut bitmap = 0b1u8;
filter.ranges[0].base = 0x10; // IA32_TIME_STAMP_COUNTER
filter.ranges[0].flags = KVM_MSR_FILTER_READ | KVM_MSR_FILTER_WRITE;
filter.ranges[0].nmsrs = 1;
filter.ranges[0].bitmap = &mut bitmap;
// Safety: bitmap is valid 8 bits, and nmsrs is 1
unsafe { vm.set_msr_filter(&filter).unwrap() };
}
}
3 changes: 3 additions & 0 deletions kvm-ioctls/src/kvm_ioctls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ ioctl_ior_nr!(KVM_MEMORY_ENCRYPT_REG_REGION, KVMIO, 0xbb, kvm_enc_region);
/* Available on SEV-enabled guests. */
#[cfg(target_arch = "x86_64")]
ioctl_ior_nr!(KVM_MEMORY_ENCRYPT_UNREG_REGION, KVMIO, 0xbc, kvm_enc_region);
/* Available with KVM_CAP_X86_MSR_FILTER */
#[cfg(target_arch = "x86_64")]
ioctl_iow_nr!(KVM_SET_MSR_FILTER, KVMIO, 0xc6, kvm_msr_filter);

// Ioctls for VCPU fds.

Expand Down