Skip to content

Commit 52f8217

Browse files
committed
KVM: nSVM: Access MSRPM in 4-byte chunks only for merging L0 and L1 bitmaps
Access the MSRPM using u32/4-byte chunks (and appropriately adjusted offsets) only when merging L0 and L1 bitmaps as part of emulating VMRUN. The only reason to batch accesses to MSRPMs is to avoid the overhead of uaccess operations (e.g. STAC/CLAC and bounds checks) when reading L1's bitmap pointed at by vmcb12. For all other uses, either per-bit accesses are more than fast enough (no uaccess), or KVM is only accessing a single bit (nested_svm_exit_handled_msr()) and so there's nothing to batch. In addition to (hopefully) documenting the uniqueness of the merging code, restricting chunked access to _just_ the merging code will allow for increasing the chunk size (to unsigned long) with minimal risk. Link: https://lore.kernel.org/r/20250610225737.156318-28-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 7fe0578 commit 52f8217

File tree

1 file changed

+18
-34
lines changed

1 file changed

+18
-34
lines changed

arch/x86/kvm/svm/nested.c

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -197,29 +197,6 @@ void recalc_intercepts(struct vcpu_svm *svm)
197197
static int nested_svm_msrpm_merge_offsets[6] __ro_after_init;
198198
static int nested_svm_nr_msrpm_merge_offsets __ro_after_init;
199199

200-
static const u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
201-
202-
static u32 svm_msrpm_offset(u32 msr)
203-
{
204-
u32 offset;
205-
int i;
206-
207-
for (i = 0; i < ARRAY_SIZE(msrpm_ranges); i++) {
208-
if (msr < msrpm_ranges[i] ||
209-
msr >= msrpm_ranges[i] + SVM_MSRS_PER_RANGE)
210-
continue;
211-
212-
offset = (msr - msrpm_ranges[i]) / SVM_MSRS_PER_BYTE;
213-
offset += (i * SVM_MSRPM_BYTES_PER_RANGE); /* add range offset */
214-
215-
/* Now we have the u8 offset - but need the u32 offset */
216-
return offset / 4;
217-
}
218-
219-
/* MSR not in any range */
220-
return MSR_INVALID;
221-
}
222-
223200
int __init nested_svm_init_msrpm_merge_offsets(void)
224201
{
225202
static const u32 merge_msrs[] __initconst = {
@@ -246,11 +223,18 @@ int __init nested_svm_init_msrpm_merge_offsets(void)
246223
int i, j;
247224

248225
for (i = 0; i < ARRAY_SIZE(merge_msrs); i++) {
249-
u32 offset = svm_msrpm_offset(merge_msrs[i]);
226+
u32 bit_nr = svm_msrpm_bit_nr(merge_msrs[i]);
227+
u32 offset;
250228

251-
if (WARN_ON(offset == MSR_INVALID))
229+
if (WARN_ON(bit_nr == MSR_INVALID))
252230
return -EIO;
253231

232+
/*
233+
* Merging is done in 32-bit chunks to reduce the number of
234+
* accesses to L1's bitmap.
235+
*/
236+
offset = bit_nr / BITS_PER_BYTE / sizeof(u32);
237+
254238
for (j = 0; j < nested_svm_nr_msrpm_merge_offsets; j++) {
255239
if (nested_svm_msrpm_merge_offsets[j] == offset)
256240
break;
@@ -1369,26 +1353,26 @@ void svm_leave_nested(struct kvm_vcpu *vcpu)
13691353

13701354
static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
13711355
{
1372-
u32 offset, msr, value;
1373-
int write, mask;
1356+
gpa_t base = svm->nested.ctl.msrpm_base_pa;
1357+
u32 msr, bit_nr;
1358+
u8 value, mask;
1359+
int write;
13741360

13751361
if (!(vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT)))
13761362
return NESTED_EXIT_HOST;
13771363

13781364
msr = svm->vcpu.arch.regs[VCPU_REGS_RCX];
1379-
offset = svm_msrpm_offset(msr);
1365+
bit_nr = svm_msrpm_bit_nr(msr);
13801366
write = svm->vmcb->control.exit_info_1 & 1;
1381-
mask = 1 << ((2 * (msr & 0xf)) + write);
13821367

1383-
if (offset == MSR_INVALID)
1368+
if (bit_nr == MSR_INVALID)
13841369
return NESTED_EXIT_DONE;
13851370

1386-
/* Offset is in 32 bit units but need in 8 bit units */
1387-
offset *= 4;
1388-
1389-
if (kvm_vcpu_read_guest(&svm->vcpu, svm->nested.ctl.msrpm_base_pa + offset, &value, 4))
1371+
if (kvm_vcpu_read_guest(&svm->vcpu, base + bit_nr / BITS_PER_BYTE,
1372+
&value, sizeof(value)))
13901373
return NESTED_EXIT_DONE;
13911374

1375+
mask = BIT(write) << (bit_nr & (BITS_PER_BYTE - 1));
13921376
return (value & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
13931377
}
13941378

0 commit comments

Comments
 (0)