Message ID | 20240710085259.2125131-5-ilstam@amazon.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: Improve MMIO Coalescing API | expand |
On 10/07/2024 10:52, Ilias Stamatis wrote: > Add 2 new ioctls, KVM_REGISTER_COALESCED_MMIO2 and > KVM_UNREGISTER_COALESCED_MMIO2. These do the same thing as their v1 > equivalents except an fd returned by KVM_CREATE_COALESCED_MMIO_BUFFER > needs to be passed as an argument to them. > > The fd representing a ring buffer is associated with an MMIO region > registered for coalescing and all writes to that region are accumulated > there. This is in contrast to the v1 API where all regions have to share > the same buffer. Nevertheless, userspace code can still use the same > ring buffer for multiple zones if it wishes to do so. > > Userspace can check for the availability of the new API by checking if > the KVM_CAP_COALESCED_MMIO2 capability is supported. > > Signed-off-by: Ilias Stamatis <ilstam@amazon.com> > --- > include/uapi/linux/kvm.h | 16 ++++++++++++++++ > virt/kvm/coalesced_mmio.c | 36 ++++++++++++++++++++++++++++++------ > virt/kvm/coalesced_mmio.h | 7 ++++--- > virt/kvm/kvm_main.c | 36 +++++++++++++++++++++++++++++++++++- > 4 files changed, 85 insertions(+), 10 deletions(-) > Reviewed-by: Paul Durrant <paul@xen.org>
Hi Ilias, kernel test robot noticed the following build errors: [auto build test ERROR on kvm/queue] [also build test ERROR on mst-vhost/linux-next linus/master v6.10-rc7] [cannot apply to kvm/linux-next next-20240712] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Ilias-Stamatis/KVM-Fix-coalesced_mmio_has_room/20240710-222059 base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git queue patch link: https://lore.kernel.org/r/20240710085259.2125131-5-ilstam%40amazon.com patch subject: [PATCH 4/6] KVM: Add KVM_(UN)REGISTER_COALESCED_MMIO2 ioctls config: loongarch-randconfig-001-20240713 (https://download.01.org/0day-ci/archive/20240714/202407140049.CuVivD5M-lkp@intel.com/config) compiler: loongarch64-linux-gcc (GCC) 14.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240714/202407140049.CuVivD5M-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202407140049.CuVivD5M-lkp@intel.com/ All errors (new ones prefixed by >>): arch/loongarch/kvm/../../../virt/kvm/coalesced_mmio.c: In function 'kvm_vm_ioctl_register_coalesced_mmio': >> arch/loongarch/kvm/../../../virt/kvm/coalesced_mmio.c:292:24: error: implicit declaration of function 'fget'; did you mean 'sget'? [-Wimplicit-function-declaration] 292 | file = fget(zone->buffer_fd); | ^~~~ | sget >> arch/loongarch/kvm/../../../virt/kvm/coalesced_mmio.c:292:22: error: assignment to 'struct file *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 292 | file = fget(zone->buffer_fd); | ^ >> arch/loongarch/kvm/../../../virt/kvm/coalesced_mmio.c:297:25: error: implicit declaration of function 'fput'; did you mean 'iput'? [-Wimplicit-function-declaration] 297 | fput(file); | ^~~~ | iput vim +292 arch/loongarch/kvm/../../../virt/kvm/coalesced_mmio.c 278 279 int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, 280 struct kvm_coalesced_mmio_zone2 *zone, 281 bool use_buffer_fd) 282 { 283 int ret = 0; 284 struct file *file; 285 struct kvm_coalesced_mmio_dev *dev; 286 struct kvm_coalesced_mmio_buffer_dev *buffer_dev = NULL; 287 288 if (zone->pio != 1 && zone->pio != 0) 289 return -EINVAL; 290 291 if (use_buffer_fd) { > 292 file = fget(zone->buffer_fd); 293 if (!file) 294 return -EBADF; 295 296 if (file->f_op != &coalesced_mmio_buffer_ops) { > 297 fput(file); 298 return -EINVAL; 299 } 300 301 buffer_dev = file->private_data; 302 if (!buffer_dev->ring) { 303 fput(file); 304 return -ENOBUFS; 305 } 306 } 307 308 dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), 309 GFP_KERNEL_ACCOUNT); 310 if (!dev) { 311 ret = -ENOMEM; 312 goto out_free_file; 313 } 314 315 kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops); 316 dev->kvm = kvm; 317 dev->zone = *zone; 318 dev->buffer_dev = buffer_dev; 319 320 mutex_lock(&kvm->slots_lock); 321 ret = kvm_io_bus_register_dev(kvm, 322 zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, 323 zone->addr, zone->size, &dev->dev); 324 if (ret < 0) 325 goto out_free_dev; 326 list_add_tail(&dev->list, &kvm->coalesced_zones); 327 mutex_unlock(&kvm->slots_lock); 328 329 goto out_free_file; 330 331 out_free_dev: 332 mutex_unlock(&kvm->slots_lock); 333 kfree(dev); 334 out_free_file: 335 if (use_buffer_fd) 336 fput(file); 337 338 return ret; 339 } 340
Hi Ilias, kernel test robot noticed the following build errors: [auto build test ERROR on kvm/queue] [also build test ERROR on mst-vhost/linux-next linus/master v6.10-rc7] [cannot apply to kvm/linux-next next-20240712] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Ilias-Stamatis/KVM-Fix-coalesced_mmio_has_room/20240710-222059 base: https://git.kernel.org/pub/scm/virt/kvm/kvm.git queue patch link: https://lore.kernel.org/r/20240710085259.2125131-5-ilstam%40amazon.com patch subject: [PATCH 4/6] KVM: Add KVM_(UN)REGISTER_COALESCED_MMIO2 ioctls config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20240714/202407140405.VJSETXg3-lkp@intel.com/config) compiler: powerpc64-linux-gcc (GCC) 14.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240714/202407140405.VJSETXg3-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202407140405.VJSETXg3-lkp@intel.com/ All errors (new ones prefixed by >>): arch/powerpc/kvm/../../../virt/kvm/coalesced_mmio.c: In function 'kvm_vm_ioctl_register_coalesced_mmio': >> arch/powerpc/kvm/../../../virt/kvm/coalesced_mmio.c:292:24: error: implicit declaration of function 'fget'; did you mean 'sget'? [-Wimplicit-function-declaration] 292 | file = fget(zone->buffer_fd); | ^~~~ | sget >> arch/powerpc/kvm/../../../virt/kvm/coalesced_mmio.c:292:22: error: assignment to 'struct file *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 292 | file = fget(zone->buffer_fd); | ^ >> arch/powerpc/kvm/../../../virt/kvm/coalesced_mmio.c:297:25: error: implicit declaration of function 'fput'; did you mean 'iput'? [-Wimplicit-function-declaration] 297 | fput(file); | ^~~~ | iput vim +292 arch/powerpc/kvm/../../../virt/kvm/coalesced_mmio.c 278 279 int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, 280 struct kvm_coalesced_mmio_zone2 *zone, 281 bool use_buffer_fd) 282 { 283 int ret = 0; 284 struct file *file; 285 struct kvm_coalesced_mmio_dev *dev; 286 struct kvm_coalesced_mmio_buffer_dev *buffer_dev = NULL; 287 288 if (zone->pio != 1 && zone->pio != 0) 289 return -EINVAL; 290 291 if (use_buffer_fd) { > 292 file = fget(zone->buffer_fd); 293 if (!file) 294 return -EBADF; 295 296 if (file->f_op != &coalesced_mmio_buffer_ops) { > 297 fput(file); 298 return -EINVAL; 299 } 300 301 buffer_dev = file->private_data; 302 if (!buffer_dev->ring) { 303 fput(file); 304 return -ENOBUFS; 305 } 306 } 307 308 dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), 309 GFP_KERNEL_ACCOUNT); 310 if (!dev) { 311 ret = -ENOMEM; 312 goto out_free_file; 313 } 314 315 kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops); 316 dev->kvm = kvm; 317 dev->zone = *zone; 318 dev->buffer_dev = buffer_dev; 319 320 mutex_lock(&kvm->slots_lock); 321 ret = kvm_io_bus_register_dev(kvm, 322 zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, 323 zone->addr, zone->size, &dev->dev); 324 if (ret < 0) 325 goto out_free_dev; 326 list_add_tail(&dev->list, &kvm->coalesced_zones); 327 mutex_unlock(&kvm->slots_lock); 328 329 goto out_free_file; 330 331 out_free_dev: 332 mutex_unlock(&kvm->slots_lock); 333 kfree(dev); 334 out_free_file: 335 if (use_buffer_fd) 336 fput(file); 337 338 return ret; 339 } 340
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 6d6f132e6203..e49dda50b639 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -467,6 +467,16 @@ struct kvm_coalesced_mmio_zone { }; }; +struct kvm_coalesced_mmio_zone2 { + __u64 addr; + __u32 size; + union { + __u32 pad; + __u32 pio; + }; + int buffer_fd; +}; + struct kvm_coalesced_mmio { __u64 phys_addr; __u32 len; @@ -917,6 +927,7 @@ struct kvm_enable_cap { #define KVM_CAP_MEMORY_ATTRIBUTES 233 #define KVM_CAP_GUEST_MEMFD 234 #define KVM_CAP_VM_TYPES 235 +#define KVM_CAP_COALESCED_MMIO2 236 struct kvm_irq_routing_irqchip { __u32 irqchip; @@ -1548,6 +1559,11 @@ struct kvm_create_guest_memfd { __u64 reserved[6]; }; +/* Available with KVM_CAP_COALESCED_MMIO2 */ #define KVM_CREATE_COALESCED_MMIO_BUFFER _IO(KVMIO, 0xd5) +#define KVM_REGISTER_COALESCED_MMIO2 \ + _IOW(KVMIO, 0xd6, struct kvm_coalesced_mmio_zone2) +#define KVM_UNREGISTER_COALESCED_MMIO2 \ + _IOW(KVMIO, 0xd7, struct kvm_coalesced_mmio_zone2) #endif /* __LINUX_KVM_H */ diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c index 00439e035d74..8d6d98c01f6e 100644 --- a/virt/kvm/coalesced_mmio.c +++ b/virt/kvm/coalesced_mmio.c @@ -277,19 +277,40 @@ int kvm_vm_ioctl_create_coalesced_mmio_buffer(struct kvm *kvm) } int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, - struct kvm_coalesced_mmio_zone *zone) + struct kvm_coalesced_mmio_zone2 *zone, + bool use_buffer_fd) { - int ret; + int ret = 0; + struct file *file; struct kvm_coalesced_mmio_dev *dev; struct kvm_coalesced_mmio_buffer_dev *buffer_dev = NULL; if (zone->pio != 1 && zone->pio != 0) return -EINVAL; + if (use_buffer_fd) { + file = fget(zone->buffer_fd); + if (!file) + return -EBADF; + + if (file->f_op != &coalesced_mmio_buffer_ops) { + fput(file); + return -EINVAL; + } + + buffer_dev = file->private_data; + if (!buffer_dev->ring) { + fput(file); + return -ENOBUFS; + } + } + dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL_ACCOUNT); - if (!dev) - return -ENOMEM; + if (!dev) { + ret = -ENOMEM; + goto out_free_file; + } kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops); dev->kvm = kvm; @@ -305,17 +326,20 @@ int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, list_add_tail(&dev->list, &kvm->coalesced_zones); mutex_unlock(&kvm->slots_lock); - return 0; + goto out_free_file; out_free_dev: mutex_unlock(&kvm->slots_lock); kfree(dev); +out_free_file: + if (use_buffer_fd) + fput(file); return ret; } int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm, - struct kvm_coalesced_mmio_zone *zone) + struct kvm_coalesced_mmio_zone2 *zone) { struct kvm_coalesced_mmio_dev *dev, *tmp; int r; diff --git a/virt/kvm/coalesced_mmio.h b/virt/kvm/coalesced_mmio.h index d1807ce26464..32792adb7cb4 100644 --- a/virt/kvm/coalesced_mmio.h +++ b/virt/kvm/coalesced_mmio.h @@ -19,7 +19,7 @@ struct kvm_coalesced_mmio_dev { struct list_head list; struct kvm_io_device dev; struct kvm *kvm; - struct kvm_coalesced_mmio_zone zone; + struct kvm_coalesced_mmio_zone2 zone; struct kvm_coalesced_mmio_buffer_dev *buffer_dev; }; @@ -34,9 +34,10 @@ struct kvm_coalesced_mmio_buffer_dev { int kvm_coalesced_mmio_init(struct kvm *kvm); void kvm_coalesced_mmio_free(struct kvm *kvm); int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, - struct kvm_coalesced_mmio_zone *zone); + struct kvm_coalesced_mmio_zone2 *zone, + bool use_buffer_fd); int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm, - struct kvm_coalesced_mmio_zone *zone); + struct kvm_coalesced_mmio_zone2 *zone); int kvm_vm_ioctl_create_coalesced_mmio_buffer(struct kvm *kvm); #else diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 54df2e88d4f4..683b5d392b5f 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -4815,6 +4815,7 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) #ifdef CONFIG_KVM_MMIO case KVM_CAP_COALESCED_MMIO: return KVM_COALESCED_MMIO_PAGE_OFFSET; + case KVM_CAP_COALESCED_MMIO2: case KVM_CAP_COALESCED_PIO: return 1; #endif @@ -5153,15 +5154,48 @@ static long kvm_vm_ioctl(struct file *filp, #ifdef CONFIG_KVM_MMIO case KVM_REGISTER_COALESCED_MMIO: { struct kvm_coalesced_mmio_zone zone; + struct kvm_coalesced_mmio_zone2 zone2; r = -EFAULT; if (copy_from_user(&zone, argp, sizeof(zone))) goto out; - r = kvm_vm_ioctl_register_coalesced_mmio(kvm, &zone); + + zone2.addr = zone.addr; + zone2.size = zone.size; + zone2.pio = zone.pio; + zone2.buffer_fd = -1; + + r = kvm_vm_ioctl_register_coalesced_mmio(kvm, &zone2, false); + break; + } + case KVM_REGISTER_COALESCED_MMIO2: { + struct kvm_coalesced_mmio_zone2 zone; + + r = -EFAULT; + if (copy_from_user(&zone, argp, sizeof(zone))) + goto out; + + r = kvm_vm_ioctl_register_coalesced_mmio(kvm, &zone, true); break; } case KVM_UNREGISTER_COALESCED_MMIO: { struct kvm_coalesced_mmio_zone zone; + struct kvm_coalesced_mmio_zone2 zone2; + + r = -EFAULT; + if (copy_from_user(&zone, argp, sizeof(zone))) + goto out; + + zone2.addr = zone.addr; + zone2.size = zone.size; + zone2.pio = zone.pio; + zone2.buffer_fd = -1; + + r = kvm_vm_ioctl_unregister_coalesced_mmio(kvm, &zone2); + break; + } + case KVM_UNREGISTER_COALESCED_MMIO2: { + struct kvm_coalesced_mmio_zone2 zone; r = -EFAULT; if (copy_from_user(&zone, argp, sizeof(zone)))
Add 2 new ioctls, KVM_REGISTER_COALESCED_MMIO2 and KVM_UNREGISTER_COALESCED_MMIO2. These do the same thing as their v1 equivalents except an fd returned by KVM_CREATE_COALESCED_MMIO_BUFFER needs to be passed as an argument to them. The fd representing a ring buffer is associated with an MMIO region registered for coalescing and all writes to that region are accumulated there. This is in contrast to the v1 API where all regions have to share the same buffer. Nevertheless, userspace code can still use the same ring buffer for multiple zones if it wishes to do so. Userspace can check for the availability of the new API by checking if the KVM_CAP_COALESCED_MMIO2 capability is supported. Signed-off-by: Ilias Stamatis <ilstam@amazon.com> --- include/uapi/linux/kvm.h | 16 ++++++++++++++++ virt/kvm/coalesced_mmio.c | 36 ++++++++++++++++++++++++++++++------ virt/kvm/coalesced_mmio.h | 7 ++++--- virt/kvm/kvm_main.c | 36 +++++++++++++++++++++++++++++++++++- 4 files changed, 85 insertions(+), 10 deletions(-)