]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: SVM: Use ARRAY_SIZE() to iterate over direct_access_msrs
authorSean Christopherson <seanjc@google.com>
Tue, 10 Jun 2025 22:57:10 +0000 (15:57 -0700)
committerSean Christopherson <seanjc@google.com>
Fri, 20 Jun 2025 20:05:40 +0000 (13:05 -0700)
Drop the unnecessary and dangerous value-terminated behavior of
direct_access_msrs, and simply iterate over the actual size of the array.
The use in svm_set_x2apic_msr_interception() is especially sketchy, as it
relies on unused capacity being zero-initialized, and '0' being outside
the range of x2APIC MSRs.

To ensure the array and shadow_msr_intercept stay synchronized, simply
assert that their sizes are identical (note the six 64-bit-only MSRs).

Note, direct_access_msrs will soon be removed entirely; keeping the assert
synchronized with the array isn't expected to be along-term maintenance
burden.

Reviewed-by: Chao Gao <chao.gao@intel.com>
Link: https://lore.kernel.org/r/20250610225737.156318-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm.h

index 127b54c1bbaf52931584bb013b2e4701192f2311..703aa000c8691f4ac315f8cc3fd251465fe4180e 100644 (file)
@@ -87,7 +87,7 @@ static DEFINE_PER_CPU(u64, current_tsc_ratio);
 static const struct svm_direct_access_msrs {
        u32 index;   /* Index of the MSR */
        bool always; /* True if intercept is initially cleared */
-} direct_access_msrs[MAX_DIRECT_ACCESS_MSRS] = {
+} direct_access_msrs[] = {
        { .index = MSR_STAR,                            .always = true  },
        { .index = MSR_IA32_SYSENTER_CS,                .always = true  },
        { .index = MSR_IA32_SYSENTER_EIP,               .always = false },
@@ -145,9 +145,12 @@ static const struct svm_direct_access_msrs {
        { .index = X2APIC_MSR(APIC_TMICT),              .always = false },
        { .index = X2APIC_MSR(APIC_TMCCT),              .always = false },
        { .index = X2APIC_MSR(APIC_TDCR),               .always = false },
-       { .index = MSR_INVALID,                         .always = false },
 };
 
+static_assert(ARRAY_SIZE(direct_access_msrs) ==
+             MAX_DIRECT_ACCESS_MSRS - 6 * !IS_ENABLED(CONFIG_X86_64));
+#undef MAX_DIRECT_ACCESS_MSRS
+
 /*
  * These 2 parameters are used to config the controls for Pause-Loop Exiting:
  * pause_filter_count: On processors that support Pause filtering(indicated
@@ -761,9 +764,10 @@ static int direct_access_msr_slot(u32 msr)
 {
        u32 i;
 
-       for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++)
+       for (i = 0; i < ARRAY_SIZE(direct_access_msrs); i++) {
                if (direct_access_msrs[i].index == msr)
                        return i;
+       }
 
        return -ENOENT;
 }
@@ -885,7 +889,7 @@ void svm_vcpu_init_msrpm(struct kvm_vcpu *vcpu, u32 *msrpm)
 {
        int i;
 
-       for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
+       for (i = 0; i < ARRAY_SIZE(direct_access_msrs); i++) {
                if (!direct_access_msrs[i].always)
                        continue;
                set_msr_interception(vcpu, msrpm, direct_access_msrs[i].index, 1, 1);
@@ -902,7 +906,7 @@ void svm_set_x2apic_msr_interception(struct vcpu_svm *svm, bool intercept)
        if (!x2avic_enabled)
                return;
 
-       for (i = 0; i < MAX_DIRECT_ACCESS_MSRS; i++) {
+       for (i = 0; i < ARRAY_SIZE(direct_access_msrs); i++) {
                int index = direct_access_msrs[i].index;
 
                if ((index < APIC_BASE_MSR) ||
@@ -930,7 +934,7 @@ static void svm_msr_filter_changed(struct kvm_vcpu *vcpu)
         * will automatically get filtered through the MSR filter, so we are
         * back in sync after this.
         */
-       for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
+       for (i = 0; i < ARRAY_SIZE(direct_access_msrs); i++) {
                u32 msr = direct_access_msrs[i].index;
                u32 read = test_bit(i, svm->shadow_msr_intercept.read);
                u32 write = test_bit(i, svm->shadow_msr_intercept.write);
@@ -968,7 +972,7 @@ static __init int init_msrpm_offsets(void)
 
        memset(msrpm_offsets, 0xff, sizeof(msrpm_offsets));
 
-       for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
+       for (i = 0; i < ARRAY_SIZE(direct_access_msrs); i++) {
                u32 offset;
 
                offset = svm_msrpm_offset(direct_access_msrs[i].index);
index e6f3c6a153a0cf2ce20cd4b3ab99b87b544da5ab..f1e466a10219b18880da56dedd9c9e1347a0ed74 100644 (file)
@@ -44,7 +44,7 @@ static inline struct page *__sme_pa_to_page(unsigned long pa)
 #define        IOPM_SIZE PAGE_SIZE * 3
 #define        MSRPM_SIZE PAGE_SIZE * 2
 
-#define MAX_DIRECT_ACCESS_MSRS 48
+#define MAX_DIRECT_ACCESS_MSRS 47
 #define MSRPM_OFFSETS  32
 extern u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
 extern bool npt_enabled;