Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'vfio-v4.10-rc3' of git://github.com/awilliam/linux-vfio

Pull VFIO fixes from Alex Williamson:
- Add mtty sample driver properly into build system (Alex Williamson)
- Restore type1 mapping performance after mdev (Alex Williamson)
- Fix mdev device race (Alex Williamson)
- Cleanups to the mdev ABI used by vendor drivers (Alex Williamson)
- Build fix for old compilers (Arnd Bergmann)
- Fix sample driver error path (Dan Carpenter)
- Handle pci_iomap() error (Arvind Yadav)
- Fix mdev ioctl return type (Paul Gortmaker)

* tag 'vfio-v4.10-rc3' of git://github.com/awilliam/linux-vfio:
vfio-mdev: fix non-standard ioctl return val causing i386 build fail
vfio-pci: Handle error from pci_iomap
vfio-mdev: fix some error codes in the sample code
vfio-pci: use 32-bit comparisons for register address for gcc-4.5
vfio-mdev: Make mdev_device private and abstract interfaces
vfio-mdev: Make mdev_parent private
vfio-mdev: de-polute the namespace, rename parent_device & parent_ops
vfio-mdev: Fix remove race
vfio/type1: Restore mapping performance with mdev support
vfio-mdev: Fix mtty sample driver building

+247 -172
+15 -12
Documentation/vfio-mediated-device.txt
··· 127 127 Physical Device Driver Interface 128 128 -------------------------------- 129 129 130 - The physical device driver interface provides the parent_ops[3] structure to 131 - define the APIs to manage work in the mediated core driver that is related to 132 - the physical device. 130 + The physical device driver interface provides the mdev_parent_ops[3] structure 131 + to define the APIs to manage work in the mediated core driver that is related 132 + to the physical device. 133 133 134 - The structures in the parent_ops structure are as follows: 134 + The structures in the mdev_parent_ops structure are as follows: 135 135 136 136 * dev_attr_groups: attributes of the parent device 137 137 * mdev_attr_groups: attributes of the mediated device 138 138 * supported_config: attributes to define supported configurations 139 139 140 - The functions in the parent_ops structure are as follows: 140 + The functions in the mdev_parent_ops structure are as follows: 141 141 142 142 * create: allocate basic resources in a driver for a mediated device 143 143 * remove: free resources in a driver when a mediated device is destroyed 144 144 145 - The callbacks in the parent_ops structure are as follows: 145 + The callbacks in the mdev_parent_ops structure are as follows: 146 146 147 147 * open: open callback of mediated device 148 148 * close: close callback of mediated device ··· 151 151 * write: write emulation callback 152 152 * mmap: mmap emulation callback 153 153 154 - A driver should use the parent_ops structure in the function call to register 155 - itself with the mdev core driver: 154 + A driver should use the mdev_parent_ops structure in the function call to 155 + register itself with the mdev core driver: 156 156 157 157 extern int mdev_register_device(struct device *dev, 158 - const struct parent_ops *ops); 158 + const struct mdev_parent_ops *ops); 159 159 160 - However, the parent_ops structure is not required in the function call that a 161 - driver should use to unregister itself with the mdev core driver: 160 + However, the mdev_parent_ops structure is not required in the function call 161 + that a driver should use to unregister itself with the mdev core driver: 162 162 163 163 extern void mdev_unregister_device(struct device *dev); 164 164 ··· 222 222 is as follows: 223 223 224 224 sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name); 225 + 226 + (or using mdev_parent_dev(mdev) to arrive at the parent device outside 227 + of the core mdev code) 225 228 226 229 * device_api 227 230 ··· 397 394 398 395 [1] See Documentation/vfio.txt for more information on VFIO. 399 396 [2] struct mdev_driver in include/linux/mdev.h 400 - [3] struct parent_ops in include/linux/mdev.h 397 + [3] struct mdev_parent_ops in include/linux/mdev.h 401 398 [4] struct vfio_iommu_driver_ops in include/linux/vfio.h
+12 -12
drivers/gpu/drm/i915/gvt/kvmgt.c
··· 169 169 170 170 static void gvt_cache_remove(struct intel_vgpu *vgpu, gfn_t gfn) 171 171 { 172 - struct device *dev = &vgpu->vdev.mdev->dev; 172 + struct device *dev = mdev_dev(vgpu->vdev.mdev); 173 173 struct gvt_dma *this; 174 174 unsigned long g1; 175 175 int rc; ··· 198 198 { 199 199 struct gvt_dma *dma; 200 200 struct rb_node *node = NULL; 201 - struct device *dev = &vgpu->vdev.mdev->dev; 201 + struct device *dev = mdev_dev(vgpu->vdev.mdev); 202 202 unsigned long gfn; 203 203 204 204 mutex_lock(&vgpu->vdev.cache_lock); ··· 399 399 struct device *pdev; 400 400 void *gvt; 401 401 402 - pdev = mdev->parent->dev; 402 + pdev = mdev_parent_dev(mdev); 403 403 gvt = kdev_to_i915(pdev)->gvt; 404 404 405 405 type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj)); ··· 421 421 mdev_set_drvdata(mdev, vgpu); 422 422 423 423 gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n", 424 - dev_name(&mdev->dev)); 424 + dev_name(mdev_dev(mdev))); 425 425 return 0; 426 426 } 427 427 ··· 485 485 vgpu->vdev.group_notifier.notifier_call = intel_vgpu_group_notifier; 486 486 487 487 events = VFIO_IOMMU_NOTIFY_DMA_UNMAP; 488 - ret = vfio_register_notifier(&mdev->dev, VFIO_IOMMU_NOTIFY, &events, 488 + ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, &events, 489 489 &vgpu->vdev.iommu_notifier); 490 490 if (ret != 0) { 491 491 gvt_err("vfio_register_notifier for iommu failed: %d\n", ret); ··· 493 493 } 494 494 495 495 events = VFIO_GROUP_NOTIFY_SET_KVM; 496 - ret = vfio_register_notifier(&mdev->dev, VFIO_GROUP_NOTIFY, &events, 496 + ret = vfio_register_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY, &events, 497 497 &vgpu->vdev.group_notifier); 498 498 if (ret != 0) { 499 499 gvt_err("vfio_register_notifier for group failed: %d\n", ret); ··· 508 508 return ret; 509 509 510 510 undo_group: 511 - vfio_unregister_notifier(&mdev->dev, VFIO_GROUP_NOTIFY, 511 + vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY, 512 512 &vgpu->vdev.group_notifier); 513 513 514 514 undo_iommu: 515 - vfio_unregister_notifier(&mdev->dev, VFIO_IOMMU_NOTIFY, 515 + vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, 516 516 &vgpu->vdev.iommu_notifier); 517 517 out: 518 518 return ret; ··· 529 529 if (atomic_cmpxchg(&vgpu->vdev.released, 0, 1)) 530 530 return; 531 531 532 - ret = vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_IOMMU_NOTIFY, 532 + ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_IOMMU_NOTIFY, 533 533 &vgpu->vdev.iommu_notifier); 534 534 WARN(ret, "vfio_unregister_notifier for iommu failed: %d\n", ret); 535 535 536 - ret = vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_GROUP_NOTIFY, 536 + ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_GROUP_NOTIFY, 537 537 &vgpu->vdev.group_notifier); 538 538 WARN(ret, "vfio_unregister_notifier for group failed: %d\n", ret); 539 539 ··· 1111 1111 return 0; 1112 1112 } 1113 1113 1114 - static const struct parent_ops intel_vgpu_ops = { 1114 + static const struct mdev_parent_ops intel_vgpu_ops = { 1115 1115 .supported_type_groups = intel_vgpu_type_groups, 1116 1116 .create = intel_vgpu_create, 1117 1117 .remove = intel_vgpu_remove, ··· 1398 1398 return pfn; 1399 1399 1400 1400 pfn = INTEL_GVT_INVALID_ADDR; 1401 - dev = &info->vgpu->vdev.mdev->dev; 1401 + dev = mdev_dev(info->vgpu->vdev.mdev); 1402 1402 rc = vfio_pin_pages(dev, &gfn, 1, IOMMU_READ | IOMMU_WRITE, &pfn); 1403 1403 if (rc != 1) { 1404 1404 gvt_err("vfio_pin_pages failed for gfn 0x%lx: %d\n", gfn, rc);
+84 -16
drivers/vfio/mdev/mdev_core.c
··· 27 27 static DEFINE_MUTEX(parent_list_lock); 28 28 static struct class_compat *mdev_bus_compat_class; 29 29 30 + static LIST_HEAD(mdev_list); 31 + static DEFINE_MUTEX(mdev_list_lock); 32 + 33 + struct device *mdev_parent_dev(struct mdev_device *mdev) 34 + { 35 + return mdev->parent->dev; 36 + } 37 + EXPORT_SYMBOL(mdev_parent_dev); 38 + 39 + void *mdev_get_drvdata(struct mdev_device *mdev) 40 + { 41 + return mdev->driver_data; 42 + } 43 + EXPORT_SYMBOL(mdev_get_drvdata); 44 + 45 + void mdev_set_drvdata(struct mdev_device *mdev, void *data) 46 + { 47 + mdev->driver_data = data; 48 + } 49 + EXPORT_SYMBOL(mdev_set_drvdata); 50 + 51 + struct device *mdev_dev(struct mdev_device *mdev) 52 + { 53 + return &mdev->dev; 54 + } 55 + EXPORT_SYMBOL(mdev_dev); 56 + 57 + struct mdev_device *mdev_from_dev(struct device *dev) 58 + { 59 + return dev_is_mdev(dev) ? to_mdev_device(dev) : NULL; 60 + } 61 + EXPORT_SYMBOL(mdev_from_dev); 62 + 63 + uuid_le mdev_uuid(struct mdev_device *mdev) 64 + { 65 + return mdev->uuid; 66 + } 67 + EXPORT_SYMBOL(mdev_uuid); 68 + 30 69 static int _find_mdev_device(struct device *dev, void *data) 31 70 { 32 71 struct mdev_device *mdev; ··· 81 42 return 0; 82 43 } 83 44 84 - static bool mdev_device_exist(struct parent_device *parent, uuid_le uuid) 45 + static bool mdev_device_exist(struct mdev_parent *parent, uuid_le uuid) 85 46 { 86 47 struct device *dev; 87 48 ··· 95 56 } 96 57 97 58 /* Should be called holding parent_list_lock */ 98 - static struct parent_device *__find_parent_device(struct device *dev) 59 + static struct mdev_parent *__find_parent_device(struct device *dev) 99 60 { 100 - struct parent_device *parent; 61 + struct mdev_parent *parent; 101 62 102 63 list_for_each_entry(parent, &parent_list, next) { 103 64 if (parent->dev == dev) ··· 108 69 109 70 static void mdev_release_parent(struct kref *kref) 110 71 { 111 - struct parent_device *parent = container_of(kref, struct parent_device, 112 - ref); 72 + struct mdev_parent *parent = container_of(kref, struct mdev_parent, 73 + ref); 113 74 struct device *dev = parent->dev; 114 75 115 76 kfree(parent); ··· 117 78 } 118 79 119 80 static 120 - inline struct parent_device *mdev_get_parent(struct parent_device *parent) 81 + inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent) 121 82 { 122 83 if (parent) 123 84 kref_get(&parent->ref); ··· 125 86 return parent; 126 87 } 127 88 128 - static inline void mdev_put_parent(struct parent_device *parent) 89 + static inline void mdev_put_parent(struct mdev_parent *parent) 129 90 { 130 91 if (parent) 131 92 kref_put(&parent->ref, mdev_release_parent); ··· 134 95 static int mdev_device_create_ops(struct kobject *kobj, 135 96 struct mdev_device *mdev) 136 97 { 137 - struct parent_device *parent = mdev->parent; 98 + struct mdev_parent *parent = mdev->parent; 138 99 int ret; 139 100 140 101 ret = parent->ops->create(kobj, mdev); ··· 161 122 */ 162 123 static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove) 163 124 { 164 - struct parent_device *parent = mdev->parent; 125 + struct mdev_parent *parent = mdev->parent; 165 126 int ret; 166 127 167 128 /* ··· 192 153 * Add device to list of registered parent devices. 193 154 * Returns a negative value on error, otherwise 0. 194 155 */ 195 - int mdev_register_device(struct device *dev, const struct parent_ops *ops) 156 + int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops) 196 157 { 197 158 int ret; 198 - struct parent_device *parent; 159 + struct mdev_parent *parent; 199 160 200 161 /* check for mandatory ops */ 201 162 if (!ops || !ops->create || !ops->remove || !ops->supported_type_groups) ··· 268 229 269 230 void mdev_unregister_device(struct device *dev) 270 231 { 271 - struct parent_device *parent; 232 + struct mdev_parent *parent; 272 233 bool force_remove = true; 273 234 274 235 mutex_lock(&parent_list_lock); ··· 305 266 { 306 267 int ret; 307 268 struct mdev_device *mdev; 308 - struct parent_device *parent; 269 + struct mdev_parent *parent; 309 270 struct mdev_type *type = to_mdev_type(kobj); 310 271 311 272 parent = mdev_get_parent(type->parent); ··· 355 316 dev_dbg(&mdev->dev, "MDEV: created\n"); 356 317 357 318 mutex_unlock(&parent->lock); 319 + 320 + mutex_lock(&mdev_list_lock); 321 + list_add(&mdev->next, &mdev_list); 322 + mutex_unlock(&mdev_list_lock); 323 + 358 324 return ret; 359 325 360 326 create_failed: ··· 373 329 374 330 int mdev_device_remove(struct device *dev, bool force_remove) 375 331 { 376 - struct mdev_device *mdev; 377 - struct parent_device *parent; 332 + struct mdev_device *mdev, *tmp; 333 + struct mdev_parent *parent; 378 334 struct mdev_type *type; 379 335 int ret; 336 + bool found = false; 380 337 381 338 mdev = to_mdev_device(dev); 339 + 340 + mutex_lock(&mdev_list_lock); 341 + list_for_each_entry(tmp, &mdev_list, next) { 342 + if (tmp == mdev) { 343 + found = true; 344 + break; 345 + } 346 + } 347 + 348 + if (found) 349 + list_del(&mdev->next); 350 + 351 + mutex_unlock(&mdev_list_lock); 352 + 353 + if (!found) 354 + return -ENODEV; 355 + 382 356 type = to_mdev_type(mdev->type_kobj); 383 357 parent = mdev->parent; 384 358 mutex_lock(&parent->lock); ··· 404 342 ret = mdev_device_remove_ops(mdev, force_remove); 405 343 if (ret) { 406 344 mutex_unlock(&parent->lock); 345 + 346 + mutex_lock(&mdev_list_lock); 347 + list_add(&mdev->next, &mdev_list); 348 + mutex_unlock(&mdev_list_lock); 349 + 407 350 return ret; 408 351 } 409 352 ··· 416 349 device_unregister(dev); 417 350 mutex_unlock(&parent->lock); 418 351 mdev_put_parent(parent); 419 - return ret; 352 + 353 + return 0; 420 354 } 421 355 422 356 static int __init mdev_init(void)
+26 -3
drivers/vfio/mdev/mdev_private.h
··· 16 16 int mdev_bus_register(void); 17 17 void mdev_bus_unregister(void); 18 18 19 + struct mdev_parent { 20 + struct device *dev; 21 + const struct mdev_parent_ops *ops; 22 + struct kref ref; 23 + struct mutex lock; 24 + struct list_head next; 25 + struct kset *mdev_types_kset; 26 + struct list_head type_list; 27 + }; 28 + 29 + struct mdev_device { 30 + struct device dev; 31 + struct mdev_parent *parent; 32 + uuid_le uuid; 33 + void *driver_data; 34 + struct kref ref; 35 + struct list_head next; 36 + struct kobject *type_kobj; 37 + }; 38 + 39 + #define to_mdev_device(dev) container_of(dev, struct mdev_device, dev) 40 + #define dev_is_mdev(d) ((d)->bus == &mdev_bus_type) 41 + 19 42 struct mdev_type { 20 43 struct kobject kobj; 21 44 struct kobject *devices_kobj; 22 - struct parent_device *parent; 45 + struct mdev_parent *parent; 23 46 struct list_head next; 24 47 struct attribute_group *group; 25 48 }; ··· 52 29 #define to_mdev_type(_kobj) \ 53 30 container_of(_kobj, struct mdev_type, kobj) 54 31 55 - int parent_create_sysfs_files(struct parent_device *parent); 56 - void parent_remove_sysfs_files(struct parent_device *parent); 32 + int parent_create_sysfs_files(struct mdev_parent *parent); 33 + void parent_remove_sysfs_files(struct mdev_parent *parent); 57 34 58 35 int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type); 59 36 void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type);
+4 -4
drivers/vfio/mdev/mdev_sysfs.c
··· 92 92 .release = mdev_type_release, 93 93 }; 94 94 95 - struct mdev_type *add_mdev_supported_type(struct parent_device *parent, 95 + struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent, 96 96 struct attribute_group *group) 97 97 { 98 98 struct mdev_type *type; ··· 158 158 kobject_put(&type->kobj); 159 159 } 160 160 161 - static int add_mdev_supported_type_groups(struct parent_device *parent) 161 + static int add_mdev_supported_type_groups(struct mdev_parent *parent) 162 162 { 163 163 int i; 164 164 ··· 183 183 } 184 184 185 185 /* mdev sysfs functions */ 186 - void parent_remove_sysfs_files(struct parent_device *parent) 186 + void parent_remove_sysfs_files(struct mdev_parent *parent) 187 187 { 188 188 struct mdev_type *type, *tmp; 189 189 ··· 196 196 kset_unregister(parent->mdev_types_kset); 197 197 } 198 198 199 - int parent_create_sysfs_files(struct parent_device *parent) 199 + int parent_create_sysfs_files(struct mdev_parent *parent) 200 200 { 201 201 int ret; 202 202
+6 -6
drivers/vfio/mdev/vfio_mdev.c
··· 27 27 static int vfio_mdev_open(void *device_data) 28 28 { 29 29 struct mdev_device *mdev = device_data; 30 - struct parent_device *parent = mdev->parent; 30 + struct mdev_parent *parent = mdev->parent; 31 31 int ret; 32 32 33 33 if (unlikely(!parent->ops->open)) ··· 46 46 static void vfio_mdev_release(void *device_data) 47 47 { 48 48 struct mdev_device *mdev = device_data; 49 - struct parent_device *parent = mdev->parent; 49 + struct mdev_parent *parent = mdev->parent; 50 50 51 51 if (likely(parent->ops->release)) 52 52 parent->ops->release(mdev); ··· 58 58 unsigned int cmd, unsigned long arg) 59 59 { 60 60 struct mdev_device *mdev = device_data; 61 - struct parent_device *parent = mdev->parent; 61 + struct mdev_parent *parent = mdev->parent; 62 62 63 63 if (unlikely(!parent->ops->ioctl)) 64 64 return -EINVAL; ··· 70 70 size_t count, loff_t *ppos) 71 71 { 72 72 struct mdev_device *mdev = device_data; 73 - struct parent_device *parent = mdev->parent; 73 + struct mdev_parent *parent = mdev->parent; 74 74 75 75 if (unlikely(!parent->ops->read)) 76 76 return -EINVAL; ··· 82 82 size_t count, loff_t *ppos) 83 83 { 84 84 struct mdev_device *mdev = device_data; 85 - struct parent_device *parent = mdev->parent; 85 + struct mdev_parent *parent = mdev->parent; 86 86 87 87 if (unlikely(!parent->ops->write)) 88 88 return -EINVAL; ··· 93 93 static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma) 94 94 { 95 95 struct mdev_device *mdev = device_data; 96 - struct parent_device *parent = mdev->parent; 96 + struct mdev_parent *parent = mdev->parent; 97 97 98 98 if (unlikely(!parent->ops->mmap)) 99 99 return -EINVAL;
+4
drivers/vfio/pci/vfio_pci.c
··· 1142 1142 return ret; 1143 1143 1144 1144 vdev->barmap[index] = pci_iomap(pdev, index, 0); 1145 + if (!vdev->barmap[index]) { 1146 + pci_release_selected_regions(pdev, 1 << index); 1147 + return -ENOMEM; 1148 + } 1145 1149 } 1146 1150 1147 1151 vma->vm_private_data = vdev;
+4 -1
drivers/vfio/pci/vfio_pci_rdwr.c
··· 193 193 if (!vdev->has_vga) 194 194 return -EINVAL; 195 195 196 - switch (pos) { 196 + if (pos > 0xbfffful) 197 + return -EINVAL; 198 + 199 + switch ((u32)pos) { 197 200 case 0xa0000 ... 0xbffff: 198 201 count = min(count, (size_t)(0xc0000 - pos)); 199 202 iomem = ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1);
+51 -47
drivers/vfio/vfio_iommu_type1.c
··· 268 268 { 269 269 struct vwork *vwork; 270 270 struct mm_struct *mm; 271 + bool is_current; 271 272 272 273 if (!npage) 273 274 return; 274 275 275 - mm = get_task_mm(task); 276 + is_current = (task->mm == current->mm); 277 + 278 + mm = is_current ? task->mm : get_task_mm(task); 276 279 if (!mm) 277 - return; /* process exited or nothing to do */ 280 + return; /* process exited */ 278 281 279 282 if (down_write_trylock(&mm->mmap_sem)) { 280 283 mm->locked_vm += npage; 281 284 up_write(&mm->mmap_sem); 282 - mmput(mm); 285 + if (!is_current) 286 + mmput(mm); 283 287 return; 288 + } 289 + 290 + if (is_current) { 291 + mm = get_task_mm(task); 292 + if (!mm) 293 + return; 284 294 } 285 295 286 296 /* ··· 299 289 * wouldn't need this silliness 300 290 */ 301 291 vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL); 302 - if (!vwork) { 292 + if (WARN_ON(!vwork)) { 303 293 mmput(mm); 304 294 return; 305 295 } ··· 403 393 static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, 404 394 long npage, unsigned long *pfn_base) 405 395 { 406 - unsigned long limit; 407 - bool lock_cap = ns_capable(task_active_pid_ns(dma->task)->user_ns, 408 - CAP_IPC_LOCK); 409 - struct mm_struct *mm; 410 - long ret, i = 0, lock_acct = 0; 396 + unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 397 + bool lock_cap = capable(CAP_IPC_LOCK); 398 + long ret, pinned = 0, lock_acct = 0; 411 399 bool rsvd; 412 400 dma_addr_t iova = vaddr - dma->vaddr + dma->iova; 413 401 414 - mm = get_task_mm(dma->task); 415 - if (!mm) 402 + /* This code path is only user initiated */ 403 + if (!current->mm) 416 404 return -ENODEV; 417 405 418 - ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base); 406 + ret = vaddr_get_pfn(current->mm, vaddr, dma->prot, pfn_base); 419 407 if (ret) 420 - goto pin_pg_remote_exit; 408 + return ret; 421 409 410 + pinned++; 422 411 rsvd = is_invalid_reserved_pfn(*pfn_base); 423 - limit = task_rlimit(dma->task, RLIMIT_MEMLOCK) >> PAGE_SHIFT; 424 412 425 413 /* 426 414 * Reserved pages aren't counted against the user, externally pinned 427 415 * pages are already counted against the user. 428 416 */ 429 417 if (!rsvd && !vfio_find_vpfn(dma, iova)) { 430 - if (!lock_cap && mm->locked_vm + 1 > limit) { 418 + if (!lock_cap && current->mm->locked_vm + 1 > limit) { 431 419 put_pfn(*pfn_base, dma->prot); 432 420 pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__, 433 421 limit << PAGE_SHIFT); 434 - ret = -ENOMEM; 435 - goto pin_pg_remote_exit; 422 + return -ENOMEM; 436 423 } 437 424 lock_acct++; 438 425 } 439 426 440 - i++; 441 - if (likely(!disable_hugepages)) { 442 - /* Lock all the consecutive pages from pfn_base */ 443 - for (vaddr += PAGE_SIZE, iova += PAGE_SIZE; i < npage; 444 - i++, vaddr += PAGE_SIZE, iova += PAGE_SIZE) { 445 - unsigned long pfn = 0; 427 + if (unlikely(disable_hugepages)) 428 + goto out; 446 429 447 - ret = vaddr_get_pfn(mm, vaddr, dma->prot, &pfn); 448 - if (ret) 449 - break; 430 + /* Lock all the consecutive pages from pfn_base */ 431 + for (vaddr += PAGE_SIZE, iova += PAGE_SIZE; pinned < npage; 432 + pinned++, vaddr += PAGE_SIZE, iova += PAGE_SIZE) { 433 + unsigned long pfn = 0; 450 434 451 - if (pfn != *pfn_base + i || 452 - rsvd != is_invalid_reserved_pfn(pfn)) { 435 + ret = vaddr_get_pfn(current->mm, vaddr, dma->prot, &pfn); 436 + if (ret) 437 + break; 438 + 439 + if (pfn != *pfn_base + pinned || 440 + rsvd != is_invalid_reserved_pfn(pfn)) { 441 + put_pfn(pfn, dma->prot); 442 + break; 443 + } 444 + 445 + if (!rsvd && !vfio_find_vpfn(dma, iova)) { 446 + if (!lock_cap && 447 + current->mm->locked_vm + lock_acct + 1 > limit) { 453 448 put_pfn(pfn, dma->prot); 449 + pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", 450 + __func__, limit << PAGE_SHIFT); 454 451 break; 455 452 } 456 - 457 - if (!rsvd && !vfio_find_vpfn(dma, iova)) { 458 - if (!lock_cap && 459 - mm->locked_vm + lock_acct + 1 > limit) { 460 - put_pfn(pfn, dma->prot); 461 - pr_warn("%s: RLIMIT_MEMLOCK (%ld) " 462 - "exceeded\n", __func__, 463 - limit << PAGE_SHIFT); 464 - break; 465 - } 466 - lock_acct++; 467 - } 453 + lock_acct++; 468 454 } 469 455 } 470 456 471 - vfio_lock_acct(dma->task, lock_acct); 472 - ret = i; 457 + out: 458 + vfio_lock_acct(current, lock_acct); 473 459 474 - pin_pg_remote_exit: 475 - mmput(mm); 476 - return ret; 460 + return pinned; 477 461 } 478 462 479 463 static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova, ··· 477 473 long unlocked = 0, locked = 0; 478 474 long i; 479 475 480 - for (i = 0; i < npage; i++) { 476 + for (i = 0; i < npage; i++, iova += PAGE_SIZE) { 481 477 if (put_pfn(pfn++, dma->prot)) { 482 478 unlocked++; 483 - if (vfio_find_vpfn(dma, iova + (i << PAGE_SHIFT))) 479 + if (vfio_find_vpfn(dma, iova)) 484 480 locked++; 485 481 } 486 482 }
+13 -43
include/linux/mdev.h
··· 13 13 #ifndef MDEV_H 14 14 #define MDEV_H 15 15 16 - /* Parent device */ 17 - struct parent_device { 18 - struct device *dev; 19 - const struct parent_ops *ops; 20 - 21 - /* internal */ 22 - struct kref ref; 23 - struct mutex lock; 24 - struct list_head next; 25 - struct kset *mdev_types_kset; 26 - struct list_head type_list; 27 - }; 28 - 29 - /* Mediated device */ 30 - struct mdev_device { 31 - struct device dev; 32 - struct parent_device *parent; 33 - uuid_le uuid; 34 - void *driver_data; 35 - 36 - /* internal */ 37 - struct kref ref; 38 - struct list_head next; 39 - struct kobject *type_kobj; 40 - }; 16 + struct mdev_device; 41 17 42 18 /** 43 - * struct parent_ops - Structure to be registered for each parent device to 19 + * struct mdev_parent_ops - Structure to be registered for each parent device to 44 20 * register the device to mdev module. 45 21 * 46 22 * @owner: The module owner. ··· 62 86 * @mdev: mediated device structure 63 87 * @vma: vma structure 64 88 * Parent device that support mediated device should be registered with mdev 65 - * module with parent_ops structure. 89 + * module with mdev_parent_ops structure. 66 90 **/ 67 - 68 - struct parent_ops { 91 + struct mdev_parent_ops { 69 92 struct module *owner; 70 93 const struct attribute_group **dev_attr_groups; 71 94 const struct attribute_group **mdev_attr_groups; ··· 78 103 size_t count, loff_t *ppos); 79 104 ssize_t (*write)(struct mdev_device *mdev, const char __user *buf, 80 105 size_t count, loff_t *ppos); 81 - ssize_t (*ioctl)(struct mdev_device *mdev, unsigned int cmd, 106 + long (*ioctl)(struct mdev_device *mdev, unsigned int cmd, 82 107 unsigned long arg); 83 108 int (*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma); 84 109 }; ··· 117 142 }; 118 143 119 144 #define to_mdev_driver(drv) container_of(drv, struct mdev_driver, driver) 120 - #define to_mdev_device(dev) container_of(dev, struct mdev_device, dev) 121 145 122 - static inline void *mdev_get_drvdata(struct mdev_device *mdev) 123 - { 124 - return mdev->driver_data; 125 - } 126 - 127 - static inline void mdev_set_drvdata(struct mdev_device *mdev, void *data) 128 - { 129 - mdev->driver_data = data; 130 - } 146 + extern void *mdev_get_drvdata(struct mdev_device *mdev); 147 + extern void mdev_set_drvdata(struct mdev_device *mdev, void *data); 148 + extern uuid_le mdev_uuid(struct mdev_device *mdev); 131 149 132 150 extern struct bus_type mdev_bus_type; 133 151 134 - #define dev_is_mdev(d) ((d)->bus == &mdev_bus_type) 135 - 136 152 extern int mdev_register_device(struct device *dev, 137 - const struct parent_ops *ops); 153 + const struct mdev_parent_ops *ops); 138 154 extern void mdev_unregister_device(struct device *dev); 139 155 140 156 extern int mdev_register_driver(struct mdev_driver *drv, struct module *owner); 141 157 extern void mdev_unregister_driver(struct mdev_driver *drv); 158 + 159 + extern struct device *mdev_parent_dev(struct mdev_device *mdev); 160 + extern struct device *mdev_dev(struct mdev_device *mdev); 161 + extern struct mdev_device *mdev_from_dev(struct device *dev); 142 162 143 163 #endif /* MDEV_H */
+7
samples/Kconfig
··· 105 105 help 106 106 Build samples of blackfin gptimers sample module. 107 107 108 + config SAMPLE_VFIO_MDEV_MTTY 109 + tristate "Build VFIO mtty example mediated device sample code -- loadable modules only" 110 + depends on VFIO_MDEV_DEVICE && m 111 + help 112 + Build a virtual tty sample driver for use as a VFIO 113 + mediated device 114 + 108 115 endif # SAMPLES
+2 -1
samples/Makefile
··· 2 2 3 3 obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ 4 4 hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ 5 - configfs/ connector/ v4l/ trace_printk/ blackfin/ 5 + configfs/ connector/ v4l/ trace_printk/ blackfin/ \ 6 + vfio-mdev/
+1 -13
samples/vfio-mdev/Makefile
··· 1 - # 2 - # Makefile for mtty.c file 3 - # 4 - KERNEL_DIR:=/lib/modules/$(shell uname -r)/build 5 - 6 - obj-m:=mtty.o 7 - 8 - modules clean modules_install: 9 - $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) $@ 10 - 11 - default: modules 12 - 13 - module: modules 1 + obj-$(CONFIG_SAMPLE_VFIO_MDEV_MTTY) += mtty.o
+18 -14
samples/vfio-mdev/mtty.c
··· 164 164 struct mdev_state *mds; 165 165 166 166 list_for_each_entry(mds, &mdev_devices_list, next) { 167 - if (uuid_le_cmp(mds->mdev->uuid, uuid) == 0) 167 + if (uuid_le_cmp(mdev_uuid(mds->mdev), uuid) == 0) 168 168 return mds; 169 169 } 170 170 ··· 341 341 pr_err("Serial port %d: Fifo level trigger\n", 342 342 index); 343 343 #endif 344 - mtty_trigger_interrupt(mdev_state->mdev->uuid); 344 + mtty_trigger_interrupt( 345 + mdev_uuid(mdev_state->mdev)); 345 346 } 346 347 } else { 347 348 #if defined(DEBUG_INTR) ··· 356 355 */ 357 356 if (mdev_state->s[index].uart_reg[UART_IER] & 358 357 UART_IER_RLSI) 359 - mtty_trigger_interrupt(mdev_state->mdev->uuid); 358 + mtty_trigger_interrupt( 359 + mdev_uuid(mdev_state->mdev)); 360 360 } 361 361 mutex_unlock(&mdev_state->rxtx_lock); 362 362 break; ··· 376 374 pr_err("Serial port %d: IER_THRI write\n", 377 375 index); 378 376 #endif 379 - mtty_trigger_interrupt(mdev_state->mdev->uuid); 377 + mtty_trigger_interrupt( 378 + mdev_uuid(mdev_state->mdev)); 380 379 } 381 380 382 381 mutex_unlock(&mdev_state->rxtx_lock); ··· 448 445 #if defined(DEBUG_INTR) 449 446 pr_err("Serial port %d: MCR_OUT2 write\n", index); 450 447 #endif 451 - mtty_trigger_interrupt(mdev_state->mdev->uuid); 448 + mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev)); 452 449 } 453 450 454 451 if ((mdev_state->s[index].uart_reg[UART_IER] & UART_IER_MSI) && ··· 456 453 #if defined(DEBUG_INTR) 457 454 pr_err("Serial port %d: MCR RTS/DTR write\n", index); 458 455 #endif 459 - mtty_trigger_interrupt(mdev_state->mdev->uuid); 456 + mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev)); 460 457 } 461 458 break; 462 459 ··· 507 504 #endif 508 505 if (mdev_state->s[index].uart_reg[UART_IER] & 509 506 UART_IER_THRI) 510 - mtty_trigger_interrupt(mdev_state->mdev->uuid); 507 + mtty_trigger_interrupt( 508 + mdev_uuid(mdev_state->mdev)); 511 509 } 512 510 mutex_unlock(&mdev_state->rxtx_lock); 513 511 ··· 738 734 739 735 for (i = 0; i < 2; i++) { 740 736 snprintf(name, MTTY_STRING_LEN, "%s-%d", 741 - dev_driver_string(mdev->parent->dev), i + 1); 737 + dev_driver_string(mdev_parent_dev(mdev)), i + 1); 742 738 if (!strcmp(kobj->name, name)) { 743 739 nr_ports = i + 1; 744 740 break; ··· 1302 1298 sample_mdev_dev_show(struct device *dev, struct device_attribute *attr, 1303 1299 char *buf) 1304 1300 { 1305 - struct mdev_device *mdev = to_mdev_device(dev); 1306 - 1307 - if (mdev) 1308 - return sprintf(buf, "This is MDEV %s\n", dev_name(&mdev->dev)); 1301 + if (mdev_from_dev(dev)) 1302 + return sprintf(buf, "This is MDEV %s\n", dev_name(dev)); 1309 1303 1310 1304 return sprintf(buf, "\n"); 1311 1305 } ··· 1404 1402 NULL, 1405 1403 }; 1406 1404 1407 - struct parent_ops mdev_fops = { 1405 + struct mdev_parent_ops mdev_fops = { 1408 1406 .owner = THIS_MODULE, 1409 1407 .dev_attr_groups = mtty_dev_groups, 1410 1408 .mdev_attr_groups = mdev_dev_groups, ··· 1449 1447 1450 1448 if (IS_ERR(mtty_dev.vd_class)) { 1451 1449 pr_err("Error: failed to register mtty_dev class\n"); 1450 + ret = PTR_ERR(mtty_dev.vd_class); 1452 1451 goto failed1; 1453 1452 } 1454 1453 ··· 1461 1458 if (ret) 1462 1459 goto failed2; 1463 1460 1464 - if (mdev_register_device(&mtty_dev.dev, &mdev_fops) != 0) 1461 + ret = mdev_register_device(&mtty_dev.dev, &mdev_fops); 1462 + if (ret) 1465 1463 goto failed3; 1466 1464 1467 1465 mutex_init(&mdev_list_lock);