clear_fixmap(vncr_fixmap(vt->cpu));
}
+/*
+ * VNCR TLB invalidation occurs from MMU notifiers or TLBI instructions, and
+ * either can race against a vcpu not being onlined yet (no pseudo-TLB
+ * allocated). Similarly, the TLB might be invalid. Skip those, as they
+ * obviously don't participate in the invalidation at this stage.
+ */
+#define kvm_for_each_vncr_tlb(idx, vcpup, tlbp, kvm) \
+ kvm_for_each_vcpu(idx, vcpup, kvm) \
+ if (((tlbp) = vcpup->arch.vncr_tlb) && \
+ (tlbp)->valid)
+
static void kvm_invalidate_vncr_ipa(struct kvm *kvm, u64 start, u64 end)
{
struct kvm_vcpu *vcpu;
+ struct vncr_tlb *vt;
unsigned long i;
lockdep_assert_held_write(&kvm->mmu_lock);
if (!kvm_has_feat(kvm, ID_AA64MMFR4_EL1, NV_frac, NV2_ONLY))
return;
- kvm_for_each_vcpu(i, vcpu, kvm) {
- struct vncr_tlb *vt = vcpu->arch.vncr_tlb;
+ kvm_for_each_vncr_tlb(i, vcpu, vt, kvm) {
u64 ipa_start, ipa_end, ipa_size;
- /*
- * Careful here: We end-up here from an MMU notifier,
- * and this can race against a vcpu not being onlined
- * yet, without the pseudo-TLB being allocated.
- *
- * Skip those, as they obviously don't participate in
- * the invalidation at this stage.
- */
- if (!vt)
- continue;
-
- if (!vt->valid)
- continue;
-
ipa_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift,
vt->wr.level));
ipa_start = vt->wr.pa & ~(ipa_size - 1);
struct s1e2_tlbi_scope *scope)
{
struct kvm_vcpu *vcpu;
+ struct vncr_tlb *vt;
unsigned long i;
lockdep_assert_held_write(&kvm->mmu_lock);
- kvm_for_each_vcpu(i, vcpu, kvm) {
- struct vncr_tlb *vt = vcpu->arch.vncr_tlb;
+ kvm_for_each_vncr_tlb(i, vcpu, vt, kvm) {
u64 va_start, va_end, va_size;
- if (!vt->valid)
- continue;
-
va_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift,
vt->wr.level));
va_start = vt->gva & ~(va_size - 1);