[PATCH v2 6/7] selftests: KVM: Add test for BNDCFGS VMX control MSR bits

Oliver Upton
2022-02-04T20:47:19Z

Test that the default behavior of KVM is to ignore userspace MSR writes
and conditionally expose the "{load,clear} IA32_BNDCFGS" bits in the VMX
control MSRs if the guest CPUID exposes MPX. Additionally, test that
when the corresponding quirk is disabled, userspace can still clear
these bits regardless of what is exposed in CPUID.

Signed-off-by: Oliver Upton <oupton@google.com>
---
.../selftests/kvm/include/x86_64/vmx.h | 2 +
.../kvm/x86_64/vmx_control_msrs_test.c | 53 +++++++++++++++++++
2 files changed, 55 insertions(+)

diff --git a/tools/testing/selftests/kvm/include/x86_64/vmx.h b/tools/testing/selftests/kvm/include/x86_64/vmx.h
index 583ceb0d1457..811c66d9be74 100644
--- a/tools/testing/selftests/kvm/include/x86_64/vmx.h
+++ b/tools/testing/selftests/kvm/include/x86_64/vmx.h
@@ -80,6 +80,7 @@
#define VM_EXIT_SAVE_IA32_EFER 0x00100000
#define VM_EXIT_LOAD_IA32_EFER 0x00200000
#define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000
+#define VM_EXIT_CLEAR_BNDCFGS 0x00800000

#define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff

@@ -90,6 +91,7 @@
#define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000
#define VM_ENTRY_LOAD_IA32_PAT 0x00004000
#define VM_ENTRY_LOAD_IA32_EFER 0x00008000
+#define VM_ENTRY_LOAD_BNDCFGS 0x00010000

#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff

diff --git a/tools/testing/selftests/kvm/x86_64/vmx_control_msrs_test.c b/tools/testing/selftests/kvm/x86_64/vmx_control_msrs_test.c
index ac5fdeb50eee..21e1dee0f83f 100644
--- a/tools/testing/selftests/kvm/x86_64/vmx_control_msrs_test.c
+++ b/tools/testing/selftests/kvm/x86_64/vmx_control_msrs_test.c
@@ -96,6 +96,58 @@ static void load_perf_global_ctrl_test(struct kvm_vm *vm)
VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL,
0,
VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+
+ /* cleanup, enable the quirk again */
+ cap.args[0] = 0;
+ vm_enable_cap(vm, &cap);
+}
+
+static void bndcfgs_test(struct kvm_vm *vm)
+{
+ uint32_t entry_low, entry_high, exit_low, exit_high;
+ struct kvm_enable_cap cap = {0};
+
+ get_vmx_control_msr(vm, MSR_IA32_VMX_TRUE_ENTRY_CTLS, &entry_low, &entry_high);
+ get_vmx_control_msr(vm, MSR_IA32_VMX_TRUE_EXIT_CTLS, &exit_low, &exit_high);
+
+ if (!(entry_high & VM_ENTRY_LOAD_BNDCFGS) ||
+ !(exit_high & VM_EXIT_CLEAR_BNDCFGS)) {
+ print_skip("\"load/clear IA32_BNDCFGS\" VM-{Entry,Exit} controls not supported");
+ return;
+ }
+
+ /*
+ * Test that KVM will set these bits regardless of userspace if the
+ * guest CPUID exposes MPX.
+ */
+ test_vmx_control_msr(vm, MSR_IA32_VMX_TRUE_ENTRY_CTLS, 0,
+ VM_ENTRY_LOAD_BNDCFGS,
+ VM_ENTRY_LOAD_BNDCFGS,
+ 0);
+ test_vmx_control_msr(vm, MSR_IA32_VMX_TRUE_EXIT_CTLS, 0,
+ VM_EXIT_CLEAR_BNDCFGS,
+ VM_EXIT_CLEAR_BNDCFGS,
+ 0);
+
+ /*
+ * Disable the quirk, giving userspace control of the VMX capability
+ * MSRs.
+ */
+ cap.cap = KVM_CAP_DISABLE_QUIRKS;
+ cap.args[0] = KVM_X86_QUIRK_TWEAK_VMX_CTRL_MSRS;
+ vm_enable_cap(vm, &cap);
+
+ /*
+ * Test that userspace can clear these bits, even if it exposes MPX.
+ */
+ test_vmx_control_msr(vm, MSR_IA32_VMX_TRUE_ENTRY_CTLS, 0,
+ VM_ENTRY_LOAD_BNDCFGS,
+ 0,
+ VM_ENTRY_LOAD_BNDCFGS);
+ test_vmx_control_msr(vm, MSR_IA32_VMX_TRUE_EXIT_CTLS, 0,
+ VM_EXIT_CLEAR_BNDCFGS,
+ 0,
+ VM_EXIT_CLEAR_BNDCFGS);
}

int main(void)
@@ -108,6 +160,7 @@ int main(void)
vm = vm_create_default(VCPU_ID, 0, NULL);

load_perf_global_ctrl_test(vm);
+ bndcfgs_test(vm);

kvm_vm_free(vm);
}
--
2.35.0.263.gb82422642f-goog