Skip to content

Commit ddd5c58

Browse files
committed
Merge tag 'kvmarm-fixes-6.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 fixes for 6.12, take #2 - Fix the guest view of the ID registers, making the relevant fields writable from userspace (affecting ID_AA64DFR0_EL1 and ID_AA64PFR1_EL1) - Correcly expose S1PIE to guests, fixing a regression introduced in 6.12-rc1 with the S1POE support - Fix the recycling of stage-2 shadow MMUs by tracking the context (are we allowed to block or not) as well as the recycling state - Address a couple of issues with the vgic when userspace misconfigures the emulation, resulting in various splats. Headaches courtesy of our Syzkaller friends
2 parents 3ec4350 + df5fd75 commit ddd5c58

File tree

10 files changed

+183
-35
lines changed

10 files changed

+183
-35
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5)
5252
#define KVM_REQ_SUSPEND KVM_ARCH_REQ(6)
5353
#define KVM_REQ_RESYNC_PMU_EL0 KVM_ARCH_REQ(7)
54+
#define KVM_REQ_NESTED_S2_UNMAP KVM_ARCH_REQ(8)
5455

5556
#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
5657
KVM_DIRTY_LOG_INITIALLY_SET)
@@ -211,6 +212,12 @@ struct kvm_s2_mmu {
211212
*/
212213
bool nested_stage2_enabled;
213214

215+
/*
216+
* true when this MMU needs to be unmapped before being used for a new
217+
* purpose.
218+
*/
219+
bool pending_unmap;
220+
214221
/*
215222
* 0: Nobody is currently using this, check vttbr for validity
216223
* >0: Somebody is actively using this.

arch/arm64/include/asm/kvm_mmu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
166166
int create_hyp_stack(phys_addr_t phys_addr, unsigned long *haddr);
167167
void __init free_hyp_pgds(void);
168168

169-
void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64 size);
169+
void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start,
170+
u64 size, bool may_block);
170171
void kvm_stage2_flush_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end);
171172
void kvm_stage2_wp_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end);
172173

arch/arm64/include/asm/kvm_nested.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ extern void kvm_s2_mmu_iterate_by_vmid(struct kvm *kvm, u16 vmid,
7878
extern void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu);
7979
extern void kvm_vcpu_put_hw_mmu(struct kvm_vcpu *vcpu);
8080

81+
extern void check_nested_vcpu_requests(struct kvm_vcpu *vcpu);
82+
8183
struct kvm_s2_trans {
8284
phys_addr_t output;
8385
unsigned long block_size;
@@ -124,7 +126,7 @@ extern int kvm_s2_handle_perm_fault(struct kvm_vcpu *vcpu,
124126
struct kvm_s2_trans *trans);
125127
extern int kvm_inject_s2_fault(struct kvm_vcpu *vcpu, u64 esr_el2);
126128
extern void kvm_nested_s2_wp(struct kvm *kvm);
127-
extern void kvm_nested_s2_unmap(struct kvm *kvm);
129+
extern void kvm_nested_s2_unmap(struct kvm *kvm, bool may_block);
128130
extern void kvm_nested_s2_flush(struct kvm *kvm);
129131

130132
unsigned long compute_tlb_inval_range(struct kvm_s2_mmu *mmu, u64 val);

arch/arm64/kvm/arm.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,9 @@ static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
997997
static int check_vcpu_requests(struct kvm_vcpu *vcpu)
998998
{
999999
if (kvm_request_pending(vcpu)) {
1000+
if (kvm_check_request(KVM_REQ_VM_DEAD, vcpu))
1001+
return -EIO;
1002+
10001003
if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
10011004
kvm_vcpu_sleep(vcpu);
10021005

@@ -1031,6 +1034,8 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
10311034

10321035
if (kvm_dirty_ring_check_request(vcpu))
10331036
return 0;
1037+
1038+
check_nested_vcpu_requests(vcpu);
10341039
}
10351040

10361041
return 1;

arch/arm64/kvm/hypercalls.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
317317
* to the guest, and hide SSBS so that the
318318
* guest stays protected.
319319
*/
320-
if (cpus_have_final_cap(ARM64_SSBS))
320+
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP))
321321
break;
322322
fallthrough;
323323
case SPECTRE_UNAFFECTED:
@@ -428,7 +428,7 @@ int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
428428
* Convert the workaround level into an easy-to-compare number, where higher
429429
* values mean better protection.
430430
*/
431-
static int get_kernel_wa_level(u64 regid)
431+
static int get_kernel_wa_level(struct kvm_vcpu *vcpu, u64 regid)
432432
{
433433
switch (regid) {
434434
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
@@ -449,7 +449,7 @@ static int get_kernel_wa_level(u64 regid)
449449
* don't have any FW mitigation if SSBS is there at
450450
* all times.
451451
*/
452-
if (cpus_have_final_cap(ARM64_SSBS))
452+
if (kvm_has_feat(vcpu->kvm, ID_AA64PFR1_EL1, SSBS, IMP))
453453
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
454454
fallthrough;
455455
case SPECTRE_UNAFFECTED:
@@ -486,7 +486,7 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
486486
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
487487
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
488488
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
489-
val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
489+
val = get_kernel_wa_level(vcpu, reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
490490
break;
491491
case KVM_REG_ARM_STD_BMAP:
492492
val = READ_ONCE(smccc_feat->std_bmap);
@@ -588,7 +588,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
588588
if (val & ~KVM_REG_FEATURE_LEVEL_MASK)
589589
return -EINVAL;
590590

591-
if (get_kernel_wa_level(reg->id) < val)
591+
if (get_kernel_wa_level(vcpu, reg->id) < val)
592592
return -EINVAL;
593593

594594
return 0;
@@ -624,7 +624,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
624624
* We can deal with NOT_AVAIL on NOT_REQUIRED, but not the
625625
* other way around.
626626
*/
627-
if (get_kernel_wa_level(reg->id) < wa_level)
627+
if (get_kernel_wa_level(vcpu, reg->id) < wa_level)
628628
return -EINVAL;
629629

630630
return 0;

arch/arm64/kvm/mmu.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,10 @@ static void __unmap_stage2_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64
328328
may_block));
329329
}
330330

331-
void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start, u64 size)
331+
void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start,
332+
u64 size, bool may_block)
332333
{
333-
__unmap_stage2_range(mmu, start, size, true);
334+
__unmap_stage2_range(mmu, start, size, may_block);
334335
}
335336

336337
void kvm_stage2_flush_range(struct kvm_s2_mmu *mmu, phys_addr_t addr, phys_addr_t end)
@@ -1015,7 +1016,7 @@ static void stage2_unmap_memslot(struct kvm *kvm,
10151016

10161017
if (!(vma->vm_flags & VM_PFNMAP)) {
10171018
gpa_t gpa = addr + (vm_start - memslot->userspace_addr);
1018-
kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, vm_end - vm_start);
1019+
kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, vm_end - vm_start, true);
10191020
}
10201021
hva = vm_end;
10211022
} while (hva < reg_end);
@@ -1042,7 +1043,7 @@ void stage2_unmap_vm(struct kvm *kvm)
10421043
kvm_for_each_memslot(memslot, bkt, slots)
10431044
stage2_unmap_memslot(kvm, memslot);
10441045

1045-
kvm_nested_s2_unmap(kvm);
1046+
kvm_nested_s2_unmap(kvm, true);
10461047

10471048
write_unlock(&kvm->mmu_lock);
10481049
mmap_read_unlock(current->mm);
@@ -1912,7 +1913,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
19121913
(range->end - range->start) << PAGE_SHIFT,
19131914
range->may_block);
19141915

1915-
kvm_nested_s2_unmap(kvm);
1916+
kvm_nested_s2_unmap(kvm, range->may_block);
19161917
return false;
19171918
}
19181919

@@ -2179,8 +2180,8 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
21792180
phys_addr_t size = slot->npages << PAGE_SHIFT;
21802181

21812182
write_lock(&kvm->mmu_lock);
2182-
kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, size);
2183-
kvm_nested_s2_unmap(kvm);
2183+
kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, size, true);
2184+
kvm_nested_s2_unmap(kvm, true);
21842185
write_unlock(&kvm->mmu_lock);
21852186
}
21862187

arch/arm64/kvm/nested.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -632,9 +632,9 @@ static struct kvm_s2_mmu *get_s2_mmu_nested(struct kvm_vcpu *vcpu)
632632
/* Set the scene for the next search */
633633
kvm->arch.nested_mmus_next = (i + 1) % kvm->arch.nested_mmus_size;
634634

635-
/* Clear the old state */
635+
/* Make sure we don't forget to do the laundry */
636636
if (kvm_s2_mmu_valid(s2_mmu))
637-
kvm_stage2_unmap_range(s2_mmu, 0, kvm_phys_size(s2_mmu));
637+
s2_mmu->pending_unmap = true;
638638

639639
/*
640640
* The virtual VMID (modulo CnP) will be used as a key when matching
@@ -650,6 +650,16 @@ static struct kvm_s2_mmu *get_s2_mmu_nested(struct kvm_vcpu *vcpu)
650650

651651
out:
652652
atomic_inc(&s2_mmu->refcnt);
653+
654+
/*
655+
* Set the vCPU request to perform an unmap, even if the pending unmap
656+
* originates from another vCPU. This guarantees that the MMU has been
657+
* completely unmapped before any vCPU actually uses it, and allows
658+
* multiple vCPUs to lend a hand with completing the unmap.
659+
*/
660+
if (s2_mmu->pending_unmap)
661+
kvm_make_request(KVM_REQ_NESTED_S2_UNMAP, vcpu);
662+
653663
return s2_mmu;
654664
}
655665

@@ -663,6 +673,13 @@ void kvm_init_nested_s2_mmu(struct kvm_s2_mmu *mmu)
663673

664674
void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu)
665675
{
676+
/*
677+
* The vCPU kept its reference on the MMU after the last put, keep
678+
* rolling with it.
679+
*/
680+
if (vcpu->arch.hw_mmu)
681+
return;
682+
666683
if (is_hyp_ctxt(vcpu)) {
667684
vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu;
668685
} else {
@@ -674,10 +691,18 @@ void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu)
674691

675692
void kvm_vcpu_put_hw_mmu(struct kvm_vcpu *vcpu)
676693
{
677-
if (kvm_is_nested_s2_mmu(vcpu->kvm, vcpu->arch.hw_mmu)) {
694+
/*
695+
* Keep a reference on the associated stage-2 MMU if the vCPU is
696+
* scheduling out and not in WFI emulation, suggesting it is likely to
697+
* reuse the MMU sometime soon.
698+
*/
699+
if (vcpu->scheduled_out && !vcpu_get_flag(vcpu, IN_WFI))
700+
return;
701+
702+
if (kvm_is_nested_s2_mmu(vcpu->kvm, vcpu->arch.hw_mmu))
678703
atomic_dec(&vcpu->arch.hw_mmu->refcnt);
679-
vcpu->arch.hw_mmu = NULL;
680-
}
704+
705+
vcpu->arch.hw_mmu = NULL;
681706
}
682707

683708
/*
@@ -730,7 +755,7 @@ void kvm_nested_s2_wp(struct kvm *kvm)
730755
}
731756
}
732757

733-
void kvm_nested_s2_unmap(struct kvm *kvm)
758+
void kvm_nested_s2_unmap(struct kvm *kvm, bool may_block)
734759
{
735760
int i;
736761

@@ -740,7 +765,7 @@ void kvm_nested_s2_unmap(struct kvm *kvm)
740765
struct kvm_s2_mmu *mmu = &kvm->arch.nested_mmus[i];
741766

742767
if (kvm_s2_mmu_valid(mmu))
743-
kvm_stage2_unmap_range(mmu, 0, kvm_phys_size(mmu));
768+
kvm_stage2_unmap_range(mmu, 0, kvm_phys_size(mmu), may_block);
744769
}
745770
}
746771

@@ -1184,3 +1209,17 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
11841209

11851210
return 0;
11861211
}
1212+
1213+
void check_nested_vcpu_requests(struct kvm_vcpu *vcpu)
1214+
{
1215+
if (kvm_check_request(KVM_REQ_NESTED_S2_UNMAP, vcpu)) {
1216+
struct kvm_s2_mmu *mmu = vcpu->arch.hw_mmu;
1217+
1218+
write_lock(&vcpu->kvm->mmu_lock);
1219+
if (mmu->pending_unmap) {
1220+
kvm_stage2_unmap_range(mmu, 0, kvm_phys_size(mmu), true);
1221+
mmu->pending_unmap = false;
1222+
}
1223+
write_unlock(&vcpu->kvm->mmu_lock);
1224+
}
1225+
}

0 commit comments

Comments
 (0)