Skip to content

Commit a65ed11

Browse files
committed
Add support for bus lock detection
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]>
1 parent a1d0ef4 commit a65ed11

File tree

3 files changed

+54
-0
lines changed

3 files changed

+54
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ reg_size as a public method.
1313
userspace MSR handling.
1414
- [[#246](https://github.com/rust-vmm/kvm-ioctls/pull/246)] Add support for
1515
userspace NMI injection (`KVM_NMI` ioctl).
16+
- [[#245](https://github.com/rust-vmm/kvm-ioctls/pull/245)] x86: add support
17+
for bus lock detection (`KVM_CAP_X86_BUS_LOCK_EXIT` capability).
1618

1719
# v0.15.0
1820

src/cap.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,6 @@ pub enum Cap {
166166
ArmPtrAuthGeneric = KVM_CAP_ARM_PTRAUTH_GENERIC,
167167
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
168168
X86UserSpaceMsr = KVM_CAP_X86_USER_SPACE_MSR,
169+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
170+
X86BusLockExit = KVM_CAP_X86_BUS_LOCK_EXIT,
169171
}

src/ioctls/vcpu.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ pub enum VcpuExit<'a> {
158158
X86Rdmsr(ReadMsrExit<'a>),
159159
/// Corresponds to KVM_EXIT_X86_WRMSR.
160160
X86Wrmsr(WriteMsrExit<'a>),
161+
/// Corresponds to KVM_EXIT_X86_BUS_LOCK.
162+
X86BusLock,
161163
/// Corresponds to an exit reason that is unknown from the current version
162164
/// of the kvm-ioctls crate. Let the consumer decide about what to do with
163165
/// it.
@@ -1544,6 +1546,7 @@ impl VcpuFd {
15441546
Ok(VcpuExit::IoapicEoi(eoi.vector))
15451547
}
15461548
KVM_EXIT_HYPERV => Ok(VcpuExit::Hyperv),
1549+
KVM_EXIT_X86_BUS_LOCK => Ok(VcpuExit::X86BusLock),
15471550
r => Ok(VcpuExit::Unsupported(r)),
15481551
}
15491552
} else {
@@ -1848,6 +1851,18 @@ impl VcpuFd {
18481851
0 => Ok(()),
18491852
_ => Err(errno::Error::last()),
18501853
}
1854+
1855+
/// If [`Cap::X86BusLockExit`](crate::Cap::X86BusLockExit) was enabled,
1856+
/// checks whether a bus lock was detected on the last VM exit. This may
1857+
/// return `true` even if the corresponding exit was not
1858+
/// [`VcpuExit::X86BusLock`], as a different VM exit may have preempted
1859+
/// it.
1860+
///
1861+
/// See the API documentation for `KVM_CAP_X86_BUS_LOCK_EXIT`.
1862+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1863+
pub fn bus_lock_detected(&self) -> bool {
1864+
let kvm_run = self.kvm_run_ptr.as_ref();
1865+
kvm_run.flags as u32 & KVM_RUN_X86_BUS_LOCK != 0
18511866
}
18521867
}
18531868

@@ -3075,4 +3090,39 @@ mod tests {
30753090
e => panic!("Unexpected exit: {:?}", e),
30763091
}
30773092
}
3093+
3094+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3095+
#[test]
3096+
fn test_enable_bus_lock_detection() {
3097+
let kvm = Kvm::new().unwrap();
3098+
let vm = kvm.create_vm().unwrap();
3099+
if !vm.check_extension(Cap::X86BusLockExit) {
3100+
return;
3101+
}
3102+
let args = KVM_BUS_LOCK_DETECTION_EXIT;
3103+
let cap = kvm_enable_cap {
3104+
cap: Cap::X86BusLockExit as u32,
3105+
args: [args as u64, 0, 0, 0],
3106+
..Default::default()
3107+
};
3108+
vm.enable_cap(&cap).unwrap();
3109+
}
3110+
3111+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3112+
#[test]
3113+
fn test_enable_bus_lock_detection_invalid() {
3114+
let kvm = Kvm::new().unwrap();
3115+
let vm = kvm.create_vm().unwrap();
3116+
if !vm.check_extension(Cap::X86BusLockExit) {
3117+
return;
3118+
}
3119+
// These flags should be mutually exclusive
3120+
let args = KVM_BUS_LOCK_DETECTION_OFF | KVM_BUS_LOCK_DETECTION_EXIT;
3121+
let cap = kvm_enable_cap {
3122+
cap: Cap::X86BusLockExit as u32,
3123+
args: [args as u64, 0, 0, 0],
3124+
..Default::default()
3125+
};
3126+
vm.enable_cap(&cap).unwrap_err();
3127+
}
30783128
}

0 commit comments

Comments
 (0)