]> Git Repo - J-linux.git/commitdiff
Merge tag 'kvmarm-fixes-6.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorPaolo Bonzini <[email protected]>
Sun, 6 Oct 2024 07:59:22 +0000 (03:59 -0400)
committerPaolo Bonzini <[email protected]>
Sun, 6 Oct 2024 07:59:22 +0000 (03:59 -0400)
KVM/arm64 fixes for 6.12, take #1

- Fix pKVM error path on init, making sure we do not change critical
  system registers as we're about to fail

- Make sure that the host's vector length is at capped by a value
  common to all CPUs

- Fix kvm_has_feat*() handling of "negative" features, as the current
  code is pretty broken

- Promote Joey to the status of official reviewer, while James steps
  down -- hopefully only temporarly

1  2 
arch/x86/include/asm/reboot.h
arch/x86/kvm/mmu/mmu.c

index 2d8525a5147843b9d5818f7a735708406863b46e,c02183d3cdd7e8d5c712fb2d04b3b080ea653f80..ecd58ea9a837b194b62fcba3946e7557c007c996
@@@ -26,13 -26,15 +26,15 @@@ void __noreturn machine_real_restart(un
  #define MRR_APM               1
  
  typedef void (cpu_emergency_virt_cb)(void);
 -#if IS_ENABLED(CONFIG_KVM_INTEL) || IS_ENABLED(CONFIG_KVM_AMD)
 +#if IS_ENABLED(CONFIG_KVM_X86)
  void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback);
  void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback);
  void cpu_emergency_disable_virtualization(void);
  #else
+ static inline void cpu_emergency_register_virt_callback(cpu_emergency_virt_cb *callback) {}
+ static inline void cpu_emergency_unregister_virt_callback(cpu_emergency_virt_cb *callback) {}
  static inline void cpu_emergency_disable_virtualization(void) {}
 -#endif /* CONFIG_KVM_INTEL || CONFIG_KVM_AMD */
 +#endif /* CONFIG_KVM_X86 */
  
  typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
  void nmi_shootdown_cpus(nmi_shootdown_cb callback);
diff --combined arch/x86/kvm/mmu/mmu.c
index 912bad4fa88ce7e7dea254617376e88fcb112534,e52f990548df6370a403ac5a19b69fa74caca090..a9a23e058555b92bf12f14ef01557eacb296fe9e
@@@ -1884,14 -1884,10 +1884,14 @@@ static bool sp_has_gptes(struct kvm_mmu
                if (is_obsolete_sp((_kvm), (_sp))) {                    \
                } else
  
 -#define for_each_gfn_valid_sp_with_gptes(_kvm, _sp, _gfn)             \
 +#define for_each_gfn_valid_sp(_kvm, _sp, _gfn)                                \
        for_each_valid_sp(_kvm, _sp,                                    \
          &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)])     \
 -              if ((_sp)->gfn != (_gfn) || !sp_has_gptes(_sp)) {} else
 +              if ((_sp)->gfn != (_gfn)) {} else
 +
 +#define for_each_gfn_valid_sp_with_gptes(_kvm, _sp, _gfn)             \
 +      for_each_gfn_valid_sp(_kvm, _sp, _gfn)                          \
 +              if (!sp_has_gptes(_sp)) {} else
  
  static bool kvm_sync_page_check(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
  {
@@@ -4703,16 -4699,14 +4703,14 @@@ out_unlock
  bool kvm_mmu_may_ignore_guest_pat(void)
  {
        /*
-        * When EPT is enabled (shadow_memtype_mask is non-zero), the CPU does
-        * not support self-snoop (or is affected by an erratum), and the VM
+        * When EPT is enabled (shadow_memtype_mask is non-zero), and the VM
         * has non-coherent DMA (DMA doesn't snoop CPU caches), KVM's ABI is to
         * honor the memtype from the guest's PAT so that guest accesses to
         * memory that is DMA'd aren't cached against the guest's wishes.  As a
         * result, KVM _may_ ignore guest PAT, whereas without non-coherent DMA,
-        * KVM _always_ ignores or honors guest PAT, i.e. doesn't toggle SPTE
-        * bits in response to non-coherent device (un)registration.
+        * KVM _always_ ignores guest PAT (when EPT is enabled).
         */
-       return !static_cpu_has(X86_FEATURE_SELFSNOOP) && shadow_memtype_mask;
+       return shadow_memtype_mask;
  }
  
  int kvm_tdp_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault)
@@@ -7053,42 -7047,14 +7051,42 @@@ void kvm_arch_flush_shadow_all(struct k
        kvm_mmu_zap_all(kvm);
  }
  
 -/*
 - * Zapping leaf SPTEs with memslot range when a memslot is moved/deleted.
 - *
 - * Zapping non-leaf SPTEs, a.k.a. not-last SPTEs, isn't required, worst
 - * case scenario we'll have unused shadow pages lying around until they
 - * are recycled due to age or when the VM is destroyed.
 - */
 -static void kvm_mmu_zap_memslot_leafs(struct kvm *kvm, struct kvm_memory_slot *slot)
 +static void kvm_mmu_zap_memslot_pages_and_flush(struct kvm *kvm,
 +                                              struct kvm_memory_slot *slot,
 +                                              bool flush)
 +{
 +      LIST_HEAD(invalid_list);
 +      unsigned long i;
 +
 +      if (list_empty(&kvm->arch.active_mmu_pages))
 +              goto out_flush;
 +
 +      /*
 +       * Since accounting information is stored in struct kvm_arch_memory_slot,
 +       * shadow pages deletion (e.g. unaccount_shadowed()) requires that all
 +       * gfns with a shadow page have a corresponding memslot.  Do so before
 +       * the memslot goes away.
 +       */
 +      for (i = 0; i < slot->npages; i++) {
 +              struct kvm_mmu_page *sp;
 +              gfn_t gfn = slot->base_gfn + i;
 +
 +              for_each_gfn_valid_sp(kvm, sp, gfn)
 +                      kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list);
 +
 +              if (need_resched() || rwlock_needbreak(&kvm->mmu_lock)) {
 +                      kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
 +                      flush = false;
 +                      cond_resched_rwlock_write(&kvm->mmu_lock);
 +              }
 +      }
 +
 +out_flush:
 +      kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
 +}
 +
 +static void kvm_mmu_zap_memslot(struct kvm *kvm,
 +                              struct kvm_memory_slot *slot)
  {
        struct kvm_gfn_range range = {
                .slot = slot,
                .end = slot->base_gfn + slot->npages,
                .may_block = true,
        };
 +      bool flush;
  
        write_lock(&kvm->mmu_lock);
 -      if (kvm_unmap_gfn_range(kvm, &range))
 -              kvm_flush_remote_tlbs_memslot(kvm, slot);
 -
 +      flush = kvm_unmap_gfn_range(kvm, &range);
 +      kvm_mmu_zap_memslot_pages_and_flush(kvm, slot, flush);
        write_unlock(&kvm->mmu_lock);
  }
  
@@@ -7116,7 -7082,7 +7114,7 @@@ void kvm_arch_flush_shadow_memslot(stru
        if (kvm_memslot_flush_zap_all(kvm))
                kvm_mmu_zap_all_fast(kvm);
        else
 -              kvm_mmu_zap_memslot_leafs(kvm, slot);
 +              kvm_mmu_zap_memslot(kvm, slot);
  }
  
  void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen)
This page took 0.091272 seconds and 4 git commands to generate.