Skip to content

Commit

Permalink
Add support for bus lock detection
Browse files Browse the repository at this point in the history
Add support for bus lock detection. The feature can be enabled via
KVM_CAP_X86_BUS_LOCK_EXIT, which enables a new exit
(KVM_EXIT_X86_BUS_LOCK) and a new flag (KVM_RUN_X86_BUS_LOCK) in the
kvm_run->flags field.

Add two tests as well to verify that enabling the feature works.

Signed-off-by: Carlos López <[email protected]>
  • Loading branch information
00xc committed Nov 23, 2023
1 parent e44fcd4 commit 4d98d7e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ reg_size as a public method.
for SMI injection via `Vcpu::smi()` (`KVM_SMI` ioctl).
- [[#241](https://github.com/rust-vmm/kvm-ioctls/pull/241)] Add support for
userspace MSR handling.
- [[#245](https://github.com/rust-vmm/kvm-ioctls/pull/245)] x86: add support
for bus lock detection (`KVM_CAP_X86_BUS_LOCK_EXIT` capability).

# v0.15.0

Expand Down
2 changes: 2 additions & 0 deletions src/cap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,6 @@ pub enum Cap {
ArmPtrAuthGeneric = KVM_CAP_ARM_PTRAUTH_GENERIC,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
X86UserSpaceMsr = KVM_CAP_X86_USER_SPACE_MSR,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
X86BusLockExit = KVM_CAP_X86_BUS_LOCK_EXIT,
}
51 changes: 51 additions & 0 deletions src/ioctls/vcpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ pub enum VcpuExit<'a> {
X86Rdmsr(ReadMsrExit<'a>),
/// Corresponds to KVM_EXIT_X86_WRMSR.
X86Wrmsr(WriteMsrExit<'a>),
/// Corresponds to KVM_EXIT_X86_BUS_LOCK.
X86BusLock,
/// Corresponds to an exit reason that is unknown from the current version
/// of the kvm-ioctls crate. Let the consumer decide about what to do with
/// it.
Expand Down Expand Up @@ -1544,6 +1546,7 @@ impl VcpuFd {
Ok(VcpuExit::IoapicEoi(eoi.vector))
}
KVM_EXIT_HYPERV => Ok(VcpuExit::Hyperv),
KVM_EXIT_X86_BUS_LOCK => Ok(VcpuExit::X86BusLock),
r => Ok(VcpuExit::Unsupported(r)),
}
} else {
Expand Down Expand Up @@ -1823,6 +1826,19 @@ impl VcpuFd {
_ => Err(errno::Error::last()),
}
}

/// If [`Cap::X86BusLockExit`](crate::Cap::X86BusLockExit) was enabled,
/// checks whether a bus lock was detected on the last VM exit. This may
/// return `true` even if the corresponding exit was not
/// [`VcpuExit::X86BusLock`], as a different VM exit may have preempted
/// it.
///
/// See the API documentation for `KVM_CAP_X86_BUS_LOCK_EXIT`.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn bus_lock_detected(&self) -> bool {
let kvm_run = self.kvm_run_ptr.as_ref();
kvm_run.flags as u32 & KVM_RUN_X86_BUS_LOCK != 0
}
}

/// Helper function to create a new `VcpuFd`.
Expand Down Expand Up @@ -3049,4 +3065,39 @@ mod tests {
e => panic!("Unexpected exit: {:?}", e),
}
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[test]
fn test_enable_bus_lock_detection() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
if !vm.check_extension(Cap::X86BusLockExit) {
return;
}
let args = KVM_BUS_LOCK_DETECTION_EXIT;
let cap = kvm_enable_cap {
cap: Cap::X86BusLockExit as u32,
args: [args as u64, 0, 0, 0],
..Default::default()
};
vm.enable_cap(&cap).unwrap();
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[test]
fn test_enable_bus_lock_detection_invalid() {
let kvm = Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
if !vm.check_extension(Cap::X86BusLockExit) {
return;
}
// These flags should be mutually exclusive
let args = KVM_BUS_LOCK_DETECTION_OFF | KVM_BUS_LOCK_DETECTION_EXIT;
let cap = kvm_enable_cap {
cap: Cap::X86BusLockExit as u32,
args: [args as u64, 0, 0, 0],
..Default::default()
};
vm.enable_cap(&cap).unwrap_err();
}
}

0 comments on commit 4d98d7e

Please sign in to comment.