@@ -2677,6 +2677,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_SET_BOOT_CPU_ID:
case KVM_CAP_SPLIT_IRQCHIP:
case KVM_CAP_IMMEDIATE_EXIT:
+ case KVM_CAP_X86_DIRTY_LOG_WITHOUT_WRITE_PROTECT:
r = 1;
break;
case KVM_CAP_ADJUST_CLOCK:
@@ -443,9 +443,12 @@ struct kvm_interrupt {
};
/* for KVM_GET_DIRTY_LOG */
+
+#define KVM_DIRTY_LOG_WITHOUT_WRITE_PROTECT 0x1
+
struct kvm_dirty_log {
__u32 slot;
- __u32 padding1;
+ __u32 flags;
union {
void __user *dirty_bitmap; /* one bit per page */
__u64 padding2;
@@ -896,6 +899,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_X86_GUEST_MWAIT 143
#define KVM_CAP_ARM_USER_IRQ 144
#define KVM_CAP_X86_WRITE_PROTECT_ALL_MEM 145
+#define KVM_CAP_X86_DIRTY_LOG_WITHOUT_WRITE_PROTECT 146
#ifdef KVM_CAP_IRQ_ROUTING
@@ -1157,6 +1157,12 @@ int kvm_get_dirty_log_protect(struct kvm *kvm,
unsigned long n;
unsigned long *dirty_bitmap;
unsigned long *dirty_bitmap_buffer;
+ bool write_protect;
+
+ if (log->flags & ~KVM_DIRTY_LOG_WITHOUT_WRITE_PROTECT)
+ return -EINVAL;
+
+ write_protect = !(log->flags & KVM_DIRTY_LOG_WITHOUT_WRITE_PROTECT);
as_id = log->slot >> 16;
id = (u16)log->slot;
@@ -1184,11 +1190,14 @@ int kvm_get_dirty_log_protect(struct kvm *kvm,
if (!dirty_bitmap[i])
continue;
- *is_dirty = true;
-
mask = xchg(&dirty_bitmap[i], 0);
dirty_bitmap_buffer[i] = mask;
+ if (!write_protect)
+ continue;
+
+ *is_dirty = true;
+
if (mask) {
offset = i * BITS_PER_LONG;
kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot,
@@ -3140,7 +3149,7 @@ static long kvm_vm_compat_ioctl(struct file *filp,
sizeof(compat_log)))
return -EFAULT;
log.slot = compat_log.slot;
- log.padding1 = compat_log.padding1;
+ log.flags = compat_log.padding1;
log.padding2 = compat_log.padding2;
log.dirty_bitmap = compat_ptr(compat_log.dirty_bitmap);