Skip to content

Commit 7f88ef8

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 <carlos.lopez@suse.com>
1 parent bfb036f commit 7f88ef8

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ reg_size as a public method.
1111
for SMI injection via `Vcpu::smi()` (`KVM_SMI` ioctl).
1212
- [[#241](https://github.com/rust-vmm/kvm-ioctls/pull/241)] Add support for
1313
userspace MSR handling.
14+
- [[#245](https://github.com/rust-vmm/kvm-ioctls/pull/245)] x86: add support
15+
for bus lock detection (`KVM_CAP_X86_BUS_LOCK_EXIT` capability).
1416

1517
# v0.15.0
1618

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: 51 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 {
@@ -1823,6 +1826,19 @@ impl VcpuFd {
18231826
_ => Err(errno::Error::last()),
18241827
}
18251828
}
1829+
1830+
/// If [`Cap::X86BusLockExit`](crate::Cap::X86BusLockExit) was enabled,
1831+
/// checks whether a bus lock was detected on the last VM exit. This may
1832+
/// return `true` even if the corresponding exit was not
1833+
/// [`VcpuExit::X86BusLock`], as a different VM exit may have preempted
1834+
/// it.
1835+
///
1836+
/// See the API documentation for `KVM_CAP_X86_BUS_LOCK_EXIT`.
1837+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1838+
pub fn bus_lock_detected(&self) -> bool {
1839+
let kvm_run = self.kvm_run_ptr.as_ref();
1840+
kvm_run.flags as u32 & KVM_RUN_X86_BUS_LOCK != 0
1841+
}
18261842
}
18271843

18281844
/// Helper function to create a new `VcpuFd`.
@@ -3049,4 +3065,39 @@ mod tests {
30493065
e => panic!("Unexpected exit: {:?}", e),
30503066
}
30513067
}
3068+
3069+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3070+
#[test]
3071+
fn test_enable_bus_lock_detection() {
3072+
let kvm = Kvm::new().unwrap();
3073+
let vm = kvm.create_vm().unwrap();
3074+
if !vm.check_extension(Cap::X86BusLockExit) {
3075+
return;
3076+
}
3077+
let args = KVM_BUS_LOCK_DETECTION_EXIT;
3078+
let cap = kvm_enable_cap {
3079+
cap: Cap::X86BusLockExit as u32,
3080+
args: [args as u64, 0, 0, 0],
3081+
..Default::default()
3082+
};
3083+
vm.enable_cap(&cap).unwrap();
3084+
}
3085+
3086+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3087+
#[test]
3088+
fn test_enable_bus_lock_detection_invalid() {
3089+
let kvm = Kvm::new().unwrap();
3090+
let vm = kvm.create_vm().unwrap();
3091+
if !vm.check_extension(Cap::X86BusLockExit) {
3092+
return;
3093+
}
3094+
// These flags should be mutually exclusive
3095+
let args = KVM_BUS_LOCK_DETECTION_OFF | KVM_BUS_LOCK_DETECTION_EXIT;
3096+
let cap = kvm_enable_cap {
3097+
cap: Cap::X86BusLockExit as u32,
3098+
args: [args as u64, 0, 0, 0],
3099+
..Default::default()
3100+
};
3101+
vm.enable_cap(&cap).unwrap_err();
3102+
}
30523103
}

0 commit comments

Comments
 (0)