enum kvm_mr_change change)
 {
        int needs_flush;
+       u32 old_flags = old ? old->flags : 0;
+       u32 new_flags = new ? new->flags : 0;
+       bool log_dirty_pages = new_flags & KVM_MEM_LOG_DIRTY_PAGES;
+
+       /* Only track memslot flags changed */
+       if (change != KVM_MR_FLAGS_ONLY)
+               return;
+
+       /* Discard dirty page tracking on readonly memslot */
+       if ((old_flags & new_flags) & KVM_MEM_READONLY)
+               return;
 
        /*
         * If dirty page logging is enabled, write protect all pages in the slot
         * MOVE/DELETE: The old mappings will already have been cleaned up by
         *              kvm_arch_flush_shadow_memslot()
         */
-       if (change == KVM_MR_FLAGS_ONLY &&
-           (!(old->flags & KVM_MEM_LOG_DIRTY_PAGES) &&
-            new->flags & KVM_MEM_LOG_DIRTY_PAGES)) {
+       if (!(old_flags & KVM_MEM_LOG_DIRTY_PAGES) && log_dirty_pages) {
                spin_lock(&kvm->mmu_lock);
                /* Write protect GPA page table entries */
                needs_flush = kvm_mkclean_gpa_pt(kvm, new->base_gfn,