linux/tools/testing/selftests/kvm/x86/feature_msrs_test.c
Sean Christopherson 67730e6c53 KVM: selftests: Use canonical $(ARCH) paths for KVM selftests directories
Use the kernel's canonical $(ARCH) paths instead of the raw target triple
for KVM selftests directories.  KVM selftests are quite nearly the only
place in the entire kernel that using the target triple for directories,
tools/testing/selftests/drivers/s390x being the lone holdout.

Using the kernel's preferred nomenclature eliminates the minor, but
annoying, friction of having to translate to KVM's selftests directories,
e.g. for pattern matching, opening files, running selftests, etc.

Opportunsitically delete file comments that reference the full path of the
file, as they are obviously prone to becoming stale, and serve no known
purpose.

Reviewed-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
Acked-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Acked-by: Andrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/20241128005547.4077116-16-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
2024-12-18 14:15:04 -08:00

113 lines
3.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020, Red Hat, Inc.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "test_util.h"
#include "kvm_util.h"
#include "processor.h"
static bool is_kvm_controlled_msr(uint32_t msr)
{
return msr == MSR_IA32_VMX_CR0_FIXED1 || msr == MSR_IA32_VMX_CR4_FIXED1;
}
/*
* For VMX MSRs with a "true" variant, KVM requires userspace to set the "true"
* MSR, and doesn't allow setting the hidden version.
*/
static bool is_hidden_vmx_msr(uint32_t msr)
{
switch (msr) {
case MSR_IA32_VMX_PINBASED_CTLS:
case MSR_IA32_VMX_PROCBASED_CTLS:
case MSR_IA32_VMX_EXIT_CTLS:
case MSR_IA32_VMX_ENTRY_CTLS:
return true;
default:
return false;
}
}
static bool is_quirked_msr(uint32_t msr)
{
return msr != MSR_AMD64_DE_CFG;
}
static void test_feature_msr(uint32_t msr)
{
const uint64_t supported_mask = kvm_get_feature_msr(msr);
uint64_t reset_value = is_quirked_msr(msr) ? supported_mask : 0;
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
/*
* Don't bother testing KVM-controlled MSRs beyond verifying that the
* MSR can be read from userspace. Any value is effectively legal, as
* KVM is bound by x86 architecture, not by ABI.
*/
if (is_kvm_controlled_msr(msr))
return;
/*
* More goofy behavior. KVM reports the host CPU's actual revision ID,
* but initializes the vCPU's revision ID to an arbitrary value.
*/
if (msr == MSR_IA32_UCODE_REV)
reset_value = host_cpu_is_intel ? 0x100000000ULL : 0x01000065;
/*
* For quirked MSRs, KVM's ABI is to initialize the vCPU's value to the
* full set of features supported by KVM. For non-quirked MSRs, and
* when the quirk is disabled, KVM must zero-initialize the MSR and let
* userspace do the configuration.
*/
vm = vm_create_with_one_vcpu(&vcpu, NULL);
TEST_ASSERT(vcpu_get_msr(vcpu, msr) == reset_value,
"Wanted 0x%lx for %squirked MSR 0x%x, got 0x%lx",
reset_value, is_quirked_msr(msr) ? "" : "non-", msr,
vcpu_get_msr(vcpu, msr));
if (!is_hidden_vmx_msr(msr))
vcpu_set_msr(vcpu, msr, supported_mask);
kvm_vm_free(vm);
if (is_hidden_vmx_msr(msr))
return;
if (!kvm_has_cap(KVM_CAP_DISABLE_QUIRKS2) ||
!(kvm_check_cap(KVM_CAP_DISABLE_QUIRKS2) & KVM_X86_QUIRK_STUFF_FEATURE_MSRS))
return;
vm = vm_create(1);
vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, KVM_X86_QUIRK_STUFF_FEATURE_MSRS);
vcpu = vm_vcpu_add(vm, 0, NULL);
TEST_ASSERT(!vcpu_get_msr(vcpu, msr),
"Quirk disabled, wanted '0' for MSR 0x%x, got 0x%lx",
msr, vcpu_get_msr(vcpu, msr));
kvm_vm_free(vm);
}
int main(int argc, char *argv[])
{
const struct kvm_msr_list *feature_list;
int i;
/*
* Skip the entire test if MSR_FEATURES isn't supported, other tests
* will cover the "regular" list of MSRs, the coverage here is purely
* opportunistic and not interesting on its own.
*/
TEST_REQUIRE(kvm_has_cap(KVM_CAP_GET_MSR_FEATURES));
(void)kvm_get_msr_index_list();
feature_list = kvm_get_feature_msr_index_list();
for (i = 0; i < feature_list->nmsrs; i++)
test_feature_msr(feature_list->indices[i]);
}