On 04/01/2017 21:41, Cao, Lei wrote: > Introduce new memory tracking ioctls to support performant > checkpointing solutions. > > See patch 4 for details on the new ioctls. > > Signed-off-by: Lei Cao <lei.cao@xxxxxxxxxxx> > --- > arch/x86/include/asm/kvm_host.h | 2 ++ > arch/x86/kvm/x86.c | 3 +++ > include/uapi/linux/kvm.h | 8 +++++++ > virt/kvm/kvm_main.c | 47 ++++++++++++++++++++++++++++++++++++++++- > 4 files changed, 59 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 2e25038..6dfb14a 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -45,6 +45,8 @@ > > #define KVM_PIO_PAGE_OFFSET 1 > #define KVM_COALESCED_MMIO_PAGE_OFFSET 2 > +#define KVM_DIRTY_LOG_PAGE_OFFSET 3 Because this part of the mmap area is variable-sized, let's move it up (e.g. to 1024). > + > #define KVM_HALT_POLL_NS_DEFAULT 400000 > > #define KVM_IRQCHIP_NUM_PINS KVM_IOAPIC_NUM_PINS > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 0b387d6..5707129 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -2688,6 +2688,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) > case KVM_CAP_X2APIC_API: > r = KVM_X2APIC_API_VALID_FLAGS; > break; > + case KVM_CAP_DIRTY_LOG_LIST: > + r = KVM_DIRTY_LOG_PAGE_OFFSET; > + break; This can be in virt/kvm/kvm_main.c kvm_vm_ioctl_check_extension_generic (predicated by #ifdef KVM_DIRTY_LOG_PAGE_OFFSET). > default: > r = 0; > break; > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h > index cac48ed..05332de 100644 > --- a/include/uapi/linux/kvm.h > +++ b/include/uapi/linux/kvm.h > @@ -871,6 +871,7 @@ struct kvm_ppc_smmu_info { > #define KVM_CAP_S390_USER_INSTR0 130 > #define KVM_CAP_MSI_DEVID 131 > #define KVM_CAP_PPC_HTM 132 > +#define KVM_CAP_DIRTY_LOG_LIST 133 > > #ifdef KVM_CAP_IRQ_ROUTING > > @@ -1282,6 +1283,13 @@ struct kvm_s390_ucas_mapping { > /* Available with KVM_CAP_X86_SMM */ > #define KVM_SMI _IO(KVMIO, 0xb7) > > +/* Set the per-vcpu dirty log size */ > +#define KVM_SET_DIRTY_LOG_SIZE _IOW(KVMIO, 0xc0, __u32) > +/* Rearm traps for all dirty pages */ > +#define KVM_RESET_DIRTY_PAGES _IO(KVMIO, 0xc1) > +/* Get the current dirty count */ > +#define KVM_GET_DIRTY_COUNT _IOR(KVMIO, 0xc2, __u32) > + > #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) > #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) > #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2) > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 823544c..8e6f2b1 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -2945,6 +2945,23 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) > return kvm_vm_ioctl_check_extension(kvm, arg); > } > > +#ifdef KVM_DIRTY_LOG_PAGE_OFFSET > +static int kvm_mt_set_dirty_log_size(struct kvm *kvm, u32 size) > +{ > + return -EINVAL; > +} Please rename to kvm_vm_ioctl_enable_dirty_log_list. > +static int kvm_mt_reset_all_gfns(struct kvm *kvm) > +{ > + return -EINVAL; > +} Please rename to kvm_vm_ioctl_reset_dirty_pages. > +static int kvm_mt_get_dirty_count(struct kvm *kvm, u32 *count) > +{ > + return -EINVAL; > +} This should not be necessary, as discussed in the cover letter. > +#endif /* KVM_DIRTY_LOG_PAGE_OFFSET*/ > + > static long kvm_vm_ioctl(struct file *filp, > unsigned int ioctl, unsigned long arg) > { > @@ -3101,9 +3118,37 @@ static long kvm_vm_ioctl(struct file *filp, > r = 0; > break; > } > - case KVM_CHECK_EXTENSION: > + case KVM_CHECK_EXTENSION: { > r = kvm_vm_ioctl_check_extension_generic(kvm, arg); > break; > + } > +#ifdef KVM_DIRTY_LOG_PAGE_OFFSET > + case KVM_SET_DIRTY_LOG_SIZE: { > + u32 size; > + > + r = -EFAULT; > + if (copy_from_user(&size, argp, sizeof(u32))) > + goto out; > + r = kvm_mt_set_dirty_log_size(kvm, size); > + break; > + } Please use KVM_ENABLE_CAP for this functionality. I'm attaching a patch to introduce a new function kvm_vcpu_ioctl_enable_cap_generic, you can extend it with support for enabling KVM_CAP_DIRTY_LOG_LIST. Thanks, Paolo > + case KVM_RESET_DIRTY_PAGES: { > + r = kvm_mt_reset_all_gfns(kvm); > + break; > + } > + case KVM_GET_DIRTY_COUNT: { > + u32 count; > + > + r = kvm_mt_get_dirty_count(kvm, &count); > + if (r) > + goto out; > + r = -EFAULT; > + if (copy_to_user(argp, &count, sizeof(count))) > + goto out; > + r = 0; > + break; > + } > +#endif /* KVM_DIRTY_LOG_PAGE_OFFSET */ > default: > r = kvm_arch_vm_ioctl(filp, ioctl, arg); > } >
From: Paolo Bonzini <pbonzini@xxxxxxxxxx> Subject: [PATCH] kvm: move KVM_CAP_ENABLE_CAP_VM handling to virt/kvm/ We will shortly add a capability that can be enabled in a generic way. Add a new function kvm_vcpu_ioctl_enable_cap_generic to hold the KVM_ENABLE_CAP support for that kind of capability. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 03145b7cafaa..3a2721d2470e 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -1006,10 +1006,15 @@ documentation when it pops into existence). 4.37 KVM_ENABLE_CAP -Capability: KVM_CAP_ENABLE_CAP, KVM_CAP_ENABLE_CAP_VM -Architectures: x86 (only KVM_CAP_ENABLE_CAP_VM), - mips (only KVM_CAP_ENABLE_CAP), ppc, s390 -Type: vcpu ioctl, vm ioctl (with KVM_CAP_ENABLE_CAP_VM) +Capability: KVM_CAP_ENABLE_CAP +Architectures: mips, ppc, s390 +Type: vcpu ioctl +Parameters: struct kvm_enable_cap (in) +Returns: 0 on success; -1 on error + +Capability: KVM_CAP_ENABLE_CAP_VM +Architectures: all +Type: vcpu ioctl Parameters: struct kvm_enable_cap (in) Returns: 0 on success; -1 on error diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index efd1183a6b16..10dd88a4eee0 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -507,7 +507,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_PPC_UNSET_IRQ: case KVM_CAP_PPC_IRQ_LEVEL: case KVM_CAP_ENABLE_CAP: - case KVM_CAP_ENABLE_CAP_VM: case KVM_CAP_ONE_REG: case KVM_CAP_IOEVENTFD: case KVM_CAP_DEVICE_CTRL: @@ -1358,8 +1357,8 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, } -static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, - struct kvm_enable_cap *cap) +int kvm_vm_ioctl_enable_cap(struct kvm *kvm, + struct kvm_enable_cap *cap) { int r; @@ -1412,15 +1411,6 @@ long kvm_arch_vm_ioctl(struct file *filp, break; } - case KVM_ENABLE_CAP: - { - struct kvm_enable_cap cap; - r = -EFAULT; - if (copy_from_user(&cap, argp, sizeof(cap))) - goto out; - r = kvm_vm_ioctl_enable_cap(kvm, &cap); - break; - } #ifdef CONFIG_PPC_BOOK3S_64 case KVM_CREATE_SPAPR_TCE_64: { struct kvm_create_spapr_tce_64 create_tce_64; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index bec71e902be3..cc231075b783 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -366,7 +366,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_S390_CSS_SUPPORT: case KVM_CAP_IOEVENTFD: case KVM_CAP_DEVICE_CTRL: - case KVM_CAP_ENABLE_CAP_VM: case KVM_CAP_S390_IRQCHIP: case KVM_CAP_VM_ATTRIBUTES: case KVM_CAP_MP_STATE: @@ -480,7 +479,7 @@ static void icpt_operexc_on_all_vcpus(struct kvm *kvm) } } -static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap) +int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap) { int r; @@ -1232,14 +1231,6 @@ long kvm_arch_vm_ioctl(struct file *filp, r = kvm_s390_inject_vm(kvm, &s390int); break; } - case KVM_ENABLE_CAP: { - struct kvm_enable_cap cap; - r = -EFAULT; - if (copy_from_user(&cap, argp, sizeof(cap))) - break; - r = kvm_vm_ioctl_enable_cap(kvm, &cap); - break; - } case KVM_CREATE_IRQCHIP: { struct kvm_irq_routing_entry routing; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2de017e98b13..0aea15aee272 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2628,7 +2628,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_HYPERV_TIME: case KVM_CAP_IOAPIC_POLARITY_IGNORED: case KVM_CAP_TSC_DEADLINE_TIMER: - case KVM_CAP_ENABLE_CAP_VM: case KVM_CAP_DISABLE_QUIRKS: case KVM_CAP_SET_BOOT_CPU_ID: case KVM_CAP_SPLIT_IRQCHIP: @@ -3829,8 +3828,8 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, return 0; } -static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, - struct kvm_enable_cap *cap) +int kvm_vm_ioctl_enable_cap(struct kvm *kvm, + struct kvm_enable_cap *cap) { int r; @@ -4138,15 +4137,6 @@ long kvm_arch_vm_ioctl(struct file *filp, r = 0; break; } - case KVM_ENABLE_CAP: { - struct kvm_enable_cap cap; - - r = -EFAULT; - if (copy_from_user(&cap, argp, sizeof(cap))) - goto out; - r = kvm_vm_ioctl_enable_cap(kvm, &cap); - break; - } default: r = kvm_vm_ioctl_assigned_device(kvm, ioctl, arg); } diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 1c5190dab2c1..33d9974f9125 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -718,6 +718,8 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, bool line_status); +int kvm_vm_ioctl_enable_cap(struct kvm *kvm, + struct kvm_enable_cap *cap); long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 823544c166be..b051f1cfc5da 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2928,6 +2928,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) #endif case KVM_CAP_IOEVENTFD_ANY_LENGTH: case KVM_CAP_CHECK_EXTENSION_VM: + case KVM_CAP_ENABLE_CAP_VM: return 1; #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING case KVM_CAP_IRQ_ROUTING: @@ -2945,6 +2946,18 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) return kvm_vm_ioctl_check_extension(kvm, arg); } +int __attribute__((weak)) kvm_vm_ioctl_enable_cap(struct kvm *kvm, + struct kvm_enable_cap *cap) +{ + return -EINVAL; +} + +static int kvm_vm_ioctl_enable_cap_generic(struct kvm *kvm, + struct kvm_enable_cap *cap) +{ + return kvm_vm_ioctl_enable_cap(kvm, cap); +} + static long kvm_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) { @@ -2958,6 +2971,15 @@ static long kvm_vm_ioctl(struct file *filp, case KVM_CREATE_VCPU: r = kvm_vm_ioctl_create_vcpu(kvm, arg); break; + case KVM_ENABLE_CAP: { + struct kvm_enable_cap cap; + + r = -EFAULT; + if (copy_from_user(&cap, argp, sizeof(cap))) + goto out; + r = kvm_vm_ioctl_enable_cap_generic(kvm, &cap); + break; + } case KVM_SET_USER_MEMORY_REGION: { struct kvm_userspace_memory_region kvm_userspace_mem;