From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Borislav Petkov <bp@alien8.de>, Xin Li <xin@zytor.com>,
Chao Gao <chao.gao@intel.com>,
Dapeng Mi <dapeng1.mi@linux.intel.com>
Subject: Re: [PATCH 11/28] KVM: SVM: Add helpers for accessing MSR bitmap that don't rely on offsets
Date: Wed, 4 Jun 2025 10:35:15 -0700 [thread overview]
Message-ID: <aECD09sxnFAA2Te5@google.com> (raw)
In-Reply-To: <1392db34-0c37-49db-8ece-68c02ff3520d@redhat.com>
On Wed, Jun 04, 2025, Paolo Bonzini wrote:
> On 5/30/25 01:39, Sean Christopherson wrote:
> > diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> > index 47a36a9a7fe5..e432cd7a7889 100644
> > --- a/arch/x86/kvm/svm/svm.h
> > +++ b/arch/x86/kvm/svm/svm.h
> > @@ -628,6 +628,50 @@ static_assert(SVM_MSRS_PER_RANGE == 8192);
> > #define SVM_MSRPM_RANGE_1_BASE_MSR 0xc0000000
> > #define SVM_MSRPM_RANGE_2_BASE_MSR 0xc0010000
> > +#define SVM_MSRPM_FIRST_MSR(range_nr) \
> > + (SVM_MSRPM_RANGE_## range_nr ##_BASE_MSR)
> > +#define SVM_MSRPM_LAST_MSR(range_nr) \
> > + (SVM_MSRPM_RANGE_## range_nr ##_BASE_MSR + SVM_MSRS_PER_RANGE - 1)
> > +
> > +#define SVM_MSRPM_BIT_NR(range_nr, msr) \
> > + (range_nr * SVM_MSRPM_BYTES_PER_RANGE * BITS_PER_BYTE + \
> > + (msr - SVM_MSRPM_RANGE_## range_nr ##_BASE_MSR) * SVM_BITS_PER_MSR)
> > +
> > +#define SVM_MSRPM_SANITY_CHECK_BITS(range_nr) \
> > +static_assert(SVM_MSRPM_BIT_NR(range_nr, SVM_MSRPM_FIRST_MSR(range_nr) + 1) == \
> > + range_nr * 2048 * 8 + 2); \
> > +static_assert(SVM_MSRPM_BIT_NR(range_nr, SVM_MSRPM_FIRST_MSR(range_nr) + 7) == \
> > + range_nr * 2048 * 8 + 14);
> > +
> > +SVM_MSRPM_SANITY_CHECK_BITS(0);
> > +SVM_MSRPM_SANITY_CHECK_BITS(1);
> > +SVM_MSRPM_SANITY_CHECK_BITS(2);
>
> Replying here for patches 11/25/26. None of this is needed, just write a
> function like this:
>
> static inline u32 svm_msr_bit(u32 msr)
> {
> u32 msr_base = msr & ~(SVM_MSRS_PER_RANGE - 1);
Ooh, clever.
> if (msr_base == SVM_MSRPM_RANGE_0_BASE_MSR)
> return SVM_MSRPM_BIT_NR(0, msr);
> if (msr_base == SVM_MSRPM_RANGE_1_BASE_MSR)
> return SVM_MSRPM_BIT_NR(1, msr);
> if (msr_base == SVM_MSRPM_RANGE_2_BASE_MSR)
> return SVM_MSRPM_BIT_NR(2, msr);
> return MSR_INVALID;
I initially had something like this, but I don't like the potential for typos,
e.g. to fat finger something like:
if (msr_base == SVM_MSRPM_RANGE_2_BASE_MSR)
return SVM_MSRPM_BIT_NR(1, msr);
Which is how I ended up with the (admittedly ugly) CASE macros. Would you be ok
keeping that wrinkle? E.g.
#define SVM_MSR_BIT_NR_CASE(range_nr, msr) \
case SVM_MSRPM_RANGE_## range_nr ##_BASE_MSR: \
return range_nr * SVM_MSRPM_BYTES_PER_RANGE * BITS_PER_BYTE + \
(msr - SVM_MSRPM_RANGE_## range_nr ##_BASE_MSR) * SVM_BITS_PER_MSR);
static __always_inline int svm_msrpm_bit_nr(u32 msr)
{
switch (msr & ~(SVM_MSRS_PER_RANGE - 1)) {
SVM_BUILD_MSR_BITMAP_CASE(0, msr)
SVM_BUILD_MSR_BITMAP_CASE(1, msr)
SVM_BUILD_MSR_BITMAP_CASE(2, msr)
default:
return -EINVAL;
}
}
Actually, better idea! Hopefully. With your masking trick, there's no need to
do subtraction to get the offset within a range, which means getting the bit/byte
number for an MSR can be done entirely programmatically. And if we do that, then
the SVM_MSRPM_RANGE_xxx_BASE_MSR defines can go away, and the (very trivial)
copy+paste that I dislike also goes away.
Completely untested, but how about this?
#define SVM_MSRPM_OFFSET_MASK (SVM_MSRS_PER_RANGE - 1)
static __always_inline int svm_msrpm_bit_nr(u32 msr)
{
int range_nr;
switch (msr & ~SVM_MSRPM_OFFSET_MASK) {
case 0:
range_nr = 0;
break;
case 0xc0000000:
range_nr = 1;
break;
case 0xc0010000:
range_nr = 2;
break;
default:
return -EINVAL;
}
return range_nr * SVM_MSRPM_BYTES_PER_RANGE * BITS_PER_BYTE +
(msr & SVM_MSRPM_OFFSET_MASK) * SVM_BITS_PER_MSR)
}
static inline svm_msrpm_byte_nr(u32 msr)
{
return svm_msrpm_bit_nr(msr) / BITS_PER_BYTE;
}
The open coded literals aren't pretty, but VMX does the same thing, precisely
because I didn't want any code besides the innermost helper dealing with the
msr => offset math.
> }
>
> and you can throw away most of the other macros. For example:
>
> > +#define SVM_BUILD_MSR_BITMAP_CASE(bitmap, range_nr, msr, bitop, bit_rw) \
> > + case SVM_MSRPM_FIRST_MSR(range_nr) ... SVM_MSRPM_LAST_MSR(range_nr): \
> > + return bitop##_bit(SVM_MSRPM_BIT_NR(range_nr, msr) + bit_rw, bitmap);
>
> ... becomes a lot more lowercase:
>
> static inline rtype svm_##action##_msr_bitmap_##access(
> unsigned long *bitmap, u32 msr)
> {
> u32 bit = svm_msr_bit(msr);
> if (bit == MSR_INVALID)
> return true;
> return bitop##_bit(bit + bit_rw, bitmap);
Yeah, much cleaner.
> }
>
>
> In patch 25, also, you just get
>
> static u32 svm_msrpm_offset(u32 msr)
> {
> u32 bit = svm_msr_bit(msr);
> if (bit == MSR_INVALID)
> return MSR_INVALID;
> return bit / BITS_PER_BYTE;
> }
>
> And you change everything to -EINVAL in patch 26 to kill MSR_INVALID.
>
> Another nit...
>
> > +#define BUILD_SVM_MSR_BITMAP_HELPERS(ret_type, action, bitop) \
> > + __BUILD_SVM_MSR_BITMAP_HELPER(ret_type, action, bitop, read, 0) \
> > + __BUILD_SVM_MSR_BITMAP_HELPER(ret_type, action, bitop, write, 1)
> > +
> > +BUILD_SVM_MSR_BITMAP_HELPERS(bool, test, test)
> > +BUILD_SVM_MSR_BITMAP_HELPERS(void, clear, __clear)
> > +BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set)
> Yes it's a bit duplication, but no need for the nesting, just do:
I don't have a super strong preference, but I do want to be consistent between
VMX and SVM, and VMX has the nesting (unsurprisingly, also written by me). And
for that, the nested macros add a bit more value due to reads vs writes being in
entirely different areas of the bitmap.
#define BUILD_VMX_MSR_BITMAP_HELPERS(ret_type, action, bitop) \
__BUILD_VMX_MSR_BITMAP_HELPER(ret_type, action, bitop, read, 0x0) \
__BUILD_VMX_MSR_BITMAP_HELPER(ret_type, action, bitop, write, 0x800)
BUILD_VMX_MSR_BITMAP_HELPERS(bool, test, test)
BUILD_VMX_MSR_BITMAP_HELPERS(void, clear, __clear)
BUILD_VMX_MSR_BITMAP_HELPERS(void, set, __set)
That could be mitigated to some extent by adding a #define to communicate the
offset, but IMO the nested macros are less ugly than that.
> BUILD_SVM_MSR_BITMAP_HELPERS(bool, test, test, read, 0)
> BUILD_SVM_MSR_BITMAP_HELPERS(bool, test, test, write, 1)
> BUILD_SVM_MSR_BITMAP_HELPERS(void, clear, __clear, read, 0)
> BUILD_SVM_MSR_BITMAP_HELPERS(void, clear, __clear, write, 1)
> BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set, read, 0)
> BUILD_SVM_MSR_BITMAP_HELPERS(void, set, __set, write, 1)
>
> Otherwise, really nice.
>
> Paolo
>
next prev parent reply other threads:[~2025-06-04 17:35 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-29 23:39 [PATCH 00/28] KVM: x86: Clean up MSR interception code Sean Christopherson
2025-05-29 23:39 ` [PATCH 01/28] KVM: SVM: Don't BUG if setting up the MSR intercept bitmaps fails Sean Christopherson
2025-06-03 7:17 ` Chao Gao
2025-06-03 15:28 ` Sean Christopherson
2025-05-29 23:39 ` [PATCH 02/28] KVM: SVM: Tag MSR bitmap initialization helpers with __init Sean Christopherson
2025-06-03 7:18 ` Chao Gao
2025-05-29 23:39 ` [PATCH 03/28] KVM: SVM: Use ARRAY_SIZE() to iterate over direct_access_msrs Sean Christopherson
2025-06-03 7:57 ` Chao Gao
2025-05-29 23:39 ` [PATCH 04/28] KVM: SVM: Kill the VM instead of the host if MSR interception is buggy Sean Christopherson
2025-06-03 8:06 ` Chao Gao
2025-06-03 13:26 ` Sean Christopherson
2025-05-29 23:39 ` [PATCH 05/28] KVM: x86: Use non-atomic bit ops to manipulate "shadow" MSR intercepts Sean Christopherson
2025-06-03 2:53 ` Mi, Dapeng
2025-05-29 23:39 ` [PATCH 06/28] KVM: SVM: Massage name and param of helper that merges vmcb01 and vmcb12 MSRPMs Sean Christopherson
2025-06-03 2:32 ` Mi, Dapeng
2025-05-29 23:39 ` [PATCH 07/28] KVM: SVM: Clean up macros related to architectural MSRPM definitions Sean Christopherson
2025-05-29 23:39 ` [PATCH 08/28] KVM: nSVM: Use dedicated array of MSRPM offsets to merge L0 and L1 bitmaps Sean Christopherson
2025-06-04 5:43 ` Chao Gao
2025-06-04 13:56 ` Sean Christopherson
2025-06-05 8:08 ` Chao Gao
2025-06-04 15:35 ` Paolo Bonzini
2025-06-04 15:49 ` Sean Christopherson
2025-06-04 15:35 ` Paolo Bonzini
2025-05-29 23:39 ` [PATCH 09/28] KVM: nSVM: Omit SEV-ES specific passthrough MSRs from L0+L1 bitmap merge Sean Christopherson
2025-05-29 23:39 ` [PATCH 10/28] KVM: nSVM: Don't initialize vmcb02 MSRPM with vmcb01's "always passthrough" Sean Christopherson
2025-05-29 23:39 ` [PATCH 11/28] KVM: SVM: Add helpers for accessing MSR bitmap that don't rely on offsets Sean Christopherson
2025-06-04 16:11 ` Paolo Bonzini
2025-06-04 17:35 ` Sean Christopherson [this message]
2025-06-04 19:13 ` Paolo Bonzini
2025-05-29 23:39 ` [PATCH 12/28] KVM: SVM: Implement and adopt VMX style MSR intercepts APIs Sean Christopherson
2025-06-05 8:19 ` Chao Gao
2025-05-29 23:39 ` [PATCH 13/28] KVM: SVM: Pass through GHCB MSR if and only if VM is an SEV-ES guest Sean Christopherson
2025-05-29 23:39 ` [PATCH 14/28] KVM: SVM: Drop "always" flag from list of possible passthrough MSRs Sean Christopherson
2025-05-29 23:40 ` [PATCH 15/28] KVM: x86: Move definition of X2APIC_MSR() to lapic.h Sean Christopherson
2025-05-29 23:40 ` [PATCH 16/28] KVM: VMX: Manually recalc all MSR intercepts on userspace MSR filter change Sean Christopherson
2025-05-30 23:38 ` Xin Li
2025-06-02 17:10 ` Sean Christopherson
2025-06-03 3:52 ` Mi, Dapeng
2025-06-05 6:59 ` Chao Gao
2025-05-29 23:40 ` [PATCH 17/28] KVM: SVM: " Sean Christopherson
2025-05-31 18:01 ` Francesco Lavra
2025-06-02 17:08 ` Sean Christopherson
2025-06-05 6:24 ` Chao Gao
2025-06-05 16:39 ` Sean Christopherson
2025-05-29 23:40 ` [PATCH 18/28] KVM: x86: Rename msr_filter_changed() => recalc_msr_intercepts() Sean Christopherson
2025-05-30 23:47 ` Xin Li
2025-05-29 23:40 ` [PATCH 19/28] KVM: SVM: Rename init_vmcb_after_set_cpuid() to make it intercepts specific Sean Christopherson
2025-05-29 23:40 ` [PATCH 20/28] KVM: SVM: Fold svm_vcpu_init_msrpm() into its sole caller Sean Christopherson
2025-05-29 23:40 ` [PATCH 21/28] KVM: SVM: Merge "after set CPUID" intercept recalc helpers Sean Christopherson
2025-05-29 23:40 ` [PATCH 22/28] KVM: SVM: Drop explicit check on MSRPM offset when emulating SEV-ES accesses Sean Christopherson
2025-05-29 23:40 ` [PATCH 23/28] KVM: SVM: Move svm_msrpm_offset() to nested.c Sean Christopherson
2025-05-29 23:40 ` [PATCH 24/28] KVM: SVM: Store MSRPM pointer as "void *" instead of "u32 *" Sean Christopherson
2025-05-29 23:40 ` [PATCH 25/28] KVM: nSVM: Access MSRPM in 4-byte chunks only for merging L0 and L1 bitmaps Sean Christopherson
2025-06-04 16:19 ` Paolo Bonzini
2025-06-04 16:28 ` Sean Christopherson
2025-05-29 23:40 ` [PATCH 26/28] KVM: SVM: Return -EINVAL instead of MSR_INVALID to signal out-of-range MSR Sean Christopherson
2025-05-29 23:40 ` [PATCH 27/28] KVM: nSVM: Merge MSRPM in 64-bit chunks on 64-bit kernels Sean Christopherson
2025-05-29 23:40 ` [PATCH 28/28] KVM: selftests: Verify KVM disable interception (for userspace) on filter change Sean Christopherson
2025-06-03 5:47 ` Mi, Dapeng
2025-06-04 4:43 ` Manali Shukla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aECD09sxnFAA2Te5@google.com \
--to=seanjc@google.com \
--cc=bp@alien8.de \
--cc=chao.gao@intel.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=xin@zytor.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.