aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-12 16:11:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-12 16:11:26 -0400
commit467590e055f5c714fb457803250415879d0da9e5 (patch)
tree7533a26dcd19023d5eeac54f62432097c85f4ef3
parent763f96944c954ce0e00a10a7bdfe29adbe4f92eb (diff)
parentc1abca96b252a9627f99f39215b84e5de92bf1e3 (diff)
Merge tag 'vfio-v4.18-rc1' of git://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson: - Bind type1 task tracking to group_leader to facilitate vCPU hotplug in QEMU (Alex Williamson) - Sample mdev display drivers, including region-based host and guest Linux drivers and bochs compatible dmabuf device (Gerd Hoffmann) - Fix vfio-platform reset module leak (Geert Uytterhoeven) - vfio-platform error message consistency (Geert Uytterhoeven) - Global checking for mdev uuid collisions rather than per parent device (Alex Williamson) - Use match_string() helper (Yisheng Xie) - vfio-platform PM domain fixes (Geert Uytterhoeven) - Fix sample mbochs driver build dependency (Arnd Bergmann) * tag 'vfio-v4.18-rc1' of git://github.com/awilliam/linux-vfio: samples: mbochs: add DMA_SHARED_BUFFER dependency vfio: platform: Fix using devices in PM Domains vfio: use match_string() helper vfio/mdev: Re-order sysfs attribute creation vfio/mdev: Check globally for duplicate devices vfio: platform: Make printed error messages more consistent vfio: platform: Fix reset module leak in error path sample: vfio bochs vbe display (host device for bochs-drm) sample: vfio mdev display - guest driver sample: vfio mdev display - host device vfio/type1: Fix task tracking for QEMU vCPU hotplug
-rw-r--r--Documentation/vfio-mediated-device.txt5
-rw-r--r--drivers/vfio/mdev/mdev_core.c102
-rw-r--r--drivers/vfio/mdev/mdev_private.h2
-rw-r--r--drivers/vfio/mdev/mdev_sysfs.c14
-rw-r--r--drivers/vfio/platform/vfio_platform_common.c30
-rw-r--r--drivers/vfio/vfio.c11
-rw-r--r--drivers/vfio/vfio_iommu_type1.c73
-rw-r--r--samples/Kconfig31
-rw-r--r--samples/vfio-mdev/Makefile3
-rw-r--r--samples/vfio-mdev/mbochs.c1406
-rw-r--r--samples/vfio-mdev/mdpy-defs.h22
-rw-r--r--samples/vfio-mdev/mdpy-fb.c232
-rw-r--r--samples/vfio-mdev/mdpy.c807
13 files changed, 2622 insertions, 116 deletions
diff --git a/Documentation/vfio-mediated-device.txt b/Documentation/vfio-mediated-device.txt
index 1b3950346532..c3f69bcaf96e 100644
--- a/Documentation/vfio-mediated-device.txt
+++ b/Documentation/vfio-mediated-device.txt
@@ -145,6 +145,11 @@ The functions in the mdev_parent_ops structure are as follows:
145* create: allocate basic resources in a driver for a mediated device 145* create: allocate basic resources in a driver for a mediated device
146* remove: free resources in a driver when a mediated device is destroyed 146* remove: free resources in a driver when a mediated device is destroyed
147 147
148(Note that mdev-core provides no implicit serialization of create/remove
149callbacks per mdev parent device, per mdev type, or any other categorization.
150Vendor drivers are expected to be fully asynchronous in this respect or
151provide their own internal resource protection.)
152
148The callbacks in the mdev_parent_ops structure are as follows: 153The callbacks in the mdev_parent_ops structure are as follows:
149 154
150* open: open callback of mediated device 155* open: open callback of mediated device
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 126991046eb7..0212f0ee8aea 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -66,34 +66,6 @@ uuid_le mdev_uuid(struct mdev_device *mdev)
66} 66}
67EXPORT_SYMBOL(mdev_uuid); 67EXPORT_SYMBOL(mdev_uuid);
68 68
69static int _find_mdev_device(struct device *dev, void *data)
70{
71 struct mdev_device *mdev;
72
73 if (!dev_is_mdev(dev))
74 return 0;
75
76 mdev = to_mdev_device(dev);
77
78 if (uuid_le_cmp(mdev->uuid, *(uuid_le *)data) == 0)
79 return 1;
80
81 return 0;
82}
83
84static bool mdev_device_exist(struct mdev_parent *parent, uuid_le uuid)
85{
86 struct device *dev;
87
88 dev = device_find_child(parent->dev, &uuid, _find_mdev_device);
89 if (dev) {
90 put_device(dev);
91 return true;
92 }
93
94 return false;
95}
96
97/* Should be called holding parent_list_lock */ 69/* Should be called holding parent_list_lock */
98static struct mdev_parent *__find_parent_device(struct device *dev) 70static struct mdev_parent *__find_parent_device(struct device *dev)
99{ 71{
@@ -221,7 +193,6 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
221 } 193 }
222 194
223 kref_init(&parent->ref); 195 kref_init(&parent->ref);
224 mutex_init(&parent->lock);
225 196
226 parent->dev = dev; 197 parent->dev = dev;
227 parent->ops = ops; 198 parent->ops = ops;
@@ -297,6 +268,10 @@ static void mdev_device_release(struct device *dev)
297{ 268{
298 struct mdev_device *mdev = to_mdev_device(dev); 269 struct mdev_device *mdev = to_mdev_device(dev);
299 270
271 mutex_lock(&mdev_list_lock);
272 list_del(&mdev->next);
273 mutex_unlock(&mdev_list_lock);
274
300 dev_dbg(&mdev->dev, "MDEV: destroying\n"); 275 dev_dbg(&mdev->dev, "MDEV: destroying\n");
301 kfree(mdev); 276 kfree(mdev);
302} 277}
@@ -304,7 +279,7 @@ static void mdev_device_release(struct device *dev)
304int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid) 279int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
305{ 280{
306 int ret; 281 int ret;
307 struct mdev_device *mdev; 282 struct mdev_device *mdev, *tmp;
308 struct mdev_parent *parent; 283 struct mdev_parent *parent;
309 struct mdev_type *type = to_mdev_type(kobj); 284 struct mdev_type *type = to_mdev_type(kobj);
310 285
@@ -312,21 +287,28 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
312 if (!parent) 287 if (!parent)
313 return -EINVAL; 288 return -EINVAL;
314 289
315 mutex_lock(&parent->lock); 290 mutex_lock(&mdev_list_lock);
316 291
317 /* Check for duplicate */ 292 /* Check for duplicate */
318 if (mdev_device_exist(parent, uuid)) { 293 list_for_each_entry(tmp, &mdev_list, next) {
319 ret = -EEXIST; 294 if (!uuid_le_cmp(tmp->uuid, uuid)) {
320 goto create_err; 295 mutex_unlock(&mdev_list_lock);
296 ret = -EEXIST;
297 goto mdev_fail;
298 }
321 } 299 }
322 300
323 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); 301 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
324 if (!mdev) { 302 if (!mdev) {
303 mutex_unlock(&mdev_list_lock);
325 ret = -ENOMEM; 304 ret = -ENOMEM;
326 goto create_err; 305 goto mdev_fail;
327 } 306 }
328 307
329 memcpy(&mdev->uuid, &uuid, sizeof(uuid_le)); 308 memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
309 list_add(&mdev->next, &mdev_list);
310 mutex_unlock(&mdev_list_lock);
311
330 mdev->parent = parent; 312 mdev->parent = parent;
331 kref_init(&mdev->ref); 313 kref_init(&mdev->ref);
332 314
@@ -338,35 +320,28 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
338 ret = device_register(&mdev->dev); 320 ret = device_register(&mdev->dev);
339 if (ret) { 321 if (ret) {
340 put_device(&mdev->dev); 322 put_device(&mdev->dev);
341 goto create_err; 323 goto mdev_fail;
342 } 324 }
343 325
344 ret = mdev_device_create_ops(kobj, mdev); 326 ret = mdev_device_create_ops(kobj, mdev);
345 if (ret) 327 if (ret)
346 goto create_failed; 328 goto create_fail;
347 329
348 ret = mdev_create_sysfs_files(&mdev->dev, type); 330 ret = mdev_create_sysfs_files(&mdev->dev, type);
349 if (ret) { 331 if (ret) {
350 mdev_device_remove_ops(mdev, true); 332 mdev_device_remove_ops(mdev, true);
351 goto create_failed; 333 goto create_fail;
352 } 334 }
353 335
354 mdev->type_kobj = kobj; 336 mdev->type_kobj = kobj;
337 mdev->active = true;
355 dev_dbg(&mdev->dev, "MDEV: created\n"); 338 dev_dbg(&mdev->dev, "MDEV: created\n");
356 339
357 mutex_unlock(&parent->lock); 340 return 0;
358
359 mutex_lock(&mdev_list_lock);
360 list_add(&mdev->next, &mdev_list);
361 mutex_unlock(&mdev_list_lock);
362
363 return ret;
364 341
365create_failed: 342create_fail:
366 device_unregister(&mdev->dev); 343 device_unregister(&mdev->dev);
367 344mdev_fail:
368create_err:
369 mutex_unlock(&parent->lock);
370 mdev_put_parent(parent); 345 mdev_put_parent(parent);
371 return ret; 346 return ret;
372} 347}
@@ -377,44 +352,39 @@ int mdev_device_remove(struct device *dev, bool force_remove)
377 struct mdev_parent *parent; 352 struct mdev_parent *parent;
378 struct mdev_type *type; 353 struct mdev_type *type;
379 int ret; 354 int ret;
380 bool found = false;
381 355
382 mdev = to_mdev_device(dev); 356 mdev = to_mdev_device(dev);
383 357
384 mutex_lock(&mdev_list_lock); 358 mutex_lock(&mdev_list_lock);
385 list_for_each_entry(tmp, &mdev_list, next) { 359 list_for_each_entry(tmp, &mdev_list, next) {
386 if (tmp == mdev) { 360 if (tmp == mdev)
387 found = true;
388 break; 361 break;
389 }
390 } 362 }
391 363
392 if (found) 364 if (tmp != mdev) {
393 list_del(&mdev->next); 365 mutex_unlock(&mdev_list_lock);
366 return -ENODEV;
367 }
394 368
395 mutex_unlock(&mdev_list_lock); 369 if (!mdev->active) {
370 mutex_unlock(&mdev_list_lock);
371 return -EAGAIN;
372 }
396 373
397 if (!found) 374 mdev->active = false;
398 return -ENODEV; 375 mutex_unlock(&mdev_list_lock);
399 376
400 type = to_mdev_type(mdev->type_kobj); 377 type = to_mdev_type(mdev->type_kobj);
401 parent = mdev->parent; 378 parent = mdev->parent;
402 mutex_lock(&parent->lock);
403 379
404 ret = mdev_device_remove_ops(mdev, force_remove); 380 ret = mdev_device_remove_ops(mdev, force_remove);
405 if (ret) { 381 if (ret) {
406 mutex_unlock(&parent->lock); 382 mdev->active = true;
407
408 mutex_lock(&mdev_list_lock);
409 list_add(&mdev->next, &mdev_list);
410 mutex_unlock(&mdev_list_lock);
411
412 return ret; 383 return ret;
413 } 384 }
414 385
415 mdev_remove_sysfs_files(dev, type); 386 mdev_remove_sysfs_files(dev, type);
416 device_unregister(dev); 387 device_unregister(dev);
417 mutex_unlock(&parent->lock);
418 mdev_put_parent(parent); 388 mdev_put_parent(parent);
419 389
420 return 0; 390 return 0;
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index a9cefd70a705..b5819b7d7ef7 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -20,7 +20,6 @@ struct mdev_parent {
20 struct device *dev; 20 struct device *dev;
21 const struct mdev_parent_ops *ops; 21 const struct mdev_parent_ops *ops;
22 struct kref ref; 22 struct kref ref;
23 struct mutex lock;
24 struct list_head next; 23 struct list_head next;
25 struct kset *mdev_types_kset; 24 struct kset *mdev_types_kset;
26 struct list_head type_list; 25 struct list_head type_list;
@@ -34,6 +33,7 @@ struct mdev_device {
34 struct kref ref; 33 struct kref ref;
35 struct list_head next; 34 struct list_head next;
36 struct kobject *type_kobj; 35 struct kobject *type_kobj;
36 bool active;
37}; 37};
38 38
39#define to_mdev_device(dev) container_of(dev, struct mdev_device, dev) 39#define to_mdev_device(dev) container_of(dev, struct mdev_device, dev)
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 802df210929b..249472f05509 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -257,24 +257,24 @@ int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type)
257{ 257{
258 int ret; 258 int ret;
259 259
260 ret = sysfs_create_files(&dev->kobj, mdev_device_attrs);
261 if (ret)
262 return ret;
263
264 ret = sysfs_create_link(type->devices_kobj, &dev->kobj, dev_name(dev)); 260 ret = sysfs_create_link(type->devices_kobj, &dev->kobj, dev_name(dev));
265 if (ret) 261 if (ret)
266 goto device_link_failed; 262 return ret;
267 263
268 ret = sysfs_create_link(&dev->kobj, &type->kobj, "mdev_type"); 264 ret = sysfs_create_link(&dev->kobj, &type->kobj, "mdev_type");
269 if (ret) 265 if (ret)
270 goto type_link_failed; 266 goto type_link_failed;
271 267
268 ret = sysfs_create_files(&dev->kobj, mdev_device_attrs);
269 if (ret)
270 goto create_files_failed;
271
272 return ret; 272 return ret;
273 273
274create_files_failed:
275 sysfs_remove_link(&dev->kobj, "mdev_type");
274type_link_failed: 276type_link_failed:
275 sysfs_remove_link(type->devices_kobj, dev_name(dev)); 277 sysfs_remove_link(type->devices_kobj, dev_name(dev));
276device_link_failed:
277 sysfs_remove_files(&dev->kobj, mdev_device_attrs);
278 return ret; 278 return ret;
279} 279}
280 280
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 4c27f4be3c3d..c0cd824be2b7 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -17,6 +17,7 @@
17#include <linux/iommu.h> 17#include <linux/iommu.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/pm_runtime.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <linux/types.h> 22#include <linux/types.h>
22#include <linux/uaccess.h> 23#include <linux/uaccess.h>
@@ -239,6 +240,7 @@ static void vfio_platform_release(void *device_data)
239 ret, extra_dbg ? extra_dbg : ""); 240 ret, extra_dbg ? extra_dbg : "");
240 WARN_ON(1); 241 WARN_ON(1);
241 } 242 }
243 pm_runtime_put(vdev->device);
242 vfio_platform_regions_cleanup(vdev); 244 vfio_platform_regions_cleanup(vdev);
243 vfio_platform_irq_cleanup(vdev); 245 vfio_platform_irq_cleanup(vdev);
244 } 246 }
@@ -269,6 +271,10 @@ static int vfio_platform_open(void *device_data)
269 if (ret) 271 if (ret)
270 goto err_irq; 272 goto err_irq;
271 273
274 ret = pm_runtime_get_sync(vdev->device);
275 if (ret < 0)
276 goto err_pm;
277
272 ret = vfio_platform_call_reset(vdev, &extra_dbg); 278 ret = vfio_platform_call_reset(vdev, &extra_dbg);
273 if (ret && vdev->reset_required) { 279 if (ret && vdev->reset_required) {
274 dev_warn(vdev->device, "reset driver is required and reset call failed in open (%d) %s\n", 280 dev_warn(vdev->device, "reset driver is required and reset call failed in open (%d) %s\n",
@@ -283,6 +289,8 @@ static int vfio_platform_open(void *device_data)
283 return 0; 289 return 0;
284 290
285err_rst: 291err_rst:
292 pm_runtime_put(vdev->device);
293err_pm:
286 vfio_platform_irq_cleanup(vdev); 294 vfio_platform_irq_cleanup(vdev);
287err_irq: 295err_irq:
288 vfio_platform_regions_cleanup(vdev); 296 vfio_platform_regions_cleanup(vdev);
@@ -630,8 +638,7 @@ static int vfio_platform_of_probe(struct vfio_platform_device *vdev,
630 ret = device_property_read_string(dev, "compatible", 638 ret = device_property_read_string(dev, "compatible",
631 &vdev->compat); 639 &vdev->compat);
632 if (ret) 640 if (ret)
633 pr_err("VFIO: cannot retrieve compat for %s\n", 641 pr_err("VFIO: Cannot retrieve compat for %s\n", vdev->name);
634 vdev->name);
635 642
636 return ret; 643 return ret;
637} 644}
@@ -673,7 +680,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
673 680
674 ret = vfio_platform_get_reset(vdev); 681 ret = vfio_platform_get_reset(vdev);
675 if (ret && vdev->reset_required) { 682 if (ret && vdev->reset_required) {
676 pr_err("vfio: no reset function found for device %s\n", 683 pr_err("VFIO: No reset function found for device %s\n",
677 vdev->name); 684 vdev->name);
678 return ret; 685 return ret;
679 } 686 }
@@ -681,18 +688,24 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
681 group = vfio_iommu_group_get(dev); 688 group = vfio_iommu_group_get(dev);
682 if (!group) { 689 if (!group) {
683 pr_err("VFIO: No IOMMU group for device %s\n", vdev->name); 690 pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
684 return -EINVAL; 691 ret = -EINVAL;
692 goto put_reset;
685 } 693 }
686 694
687 ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev); 695 ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
688 if (ret) { 696 if (ret)
689 vfio_iommu_group_put(group, dev); 697 goto put_iommu;
690 return ret;
691 }
692 698
693 mutex_init(&vdev->igate); 699 mutex_init(&vdev->igate);
694 700
701 pm_runtime_enable(vdev->device);
695 return 0; 702 return 0;
703
704put_iommu:
705 vfio_iommu_group_put(group, dev);
706put_reset:
707 vfio_platform_put_reset(vdev);
708 return ret;
696} 709}
697EXPORT_SYMBOL_GPL(vfio_platform_probe_common); 710EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
698 711
@@ -703,6 +716,7 @@ struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
703 vdev = vfio_del_group_dev(dev); 716 vdev = vfio_del_group_dev(dev);
704 717
705 if (vdev) { 718 if (vdev) {
719 pm_runtime_disable(vdev->device);
706 vfio_platform_put_reset(vdev); 720 vfio_platform_put_reset(vdev);
707 vfio_iommu_group_put(dev->iommu_group, dev); 721 vfio_iommu_group_put(dev->iommu_group, dev);
708 } 722 }
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 721f97f8dac1..64833879f75d 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -630,8 +630,6 @@ static const char * const vfio_driver_whitelist[] = { "pci-stub" };
630 630
631static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv) 631static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
632{ 632{
633 int i;
634
635 if (dev_is_pci(dev)) { 633 if (dev_is_pci(dev)) {
636 struct pci_dev *pdev = to_pci_dev(dev); 634 struct pci_dev *pdev = to_pci_dev(dev);
637 635
@@ -639,12 +637,9 @@ static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
639 return true; 637 return true;
640 } 638 }
641 639
642 for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) { 640 return match_string(vfio_driver_whitelist,
643 if (!strcmp(drv->name, vfio_driver_whitelist[i])) 641 ARRAY_SIZE(vfio_driver_whitelist),
644 return true; 642 drv->name) >= 0;
645 }
646
647 return false;
648} 643}
649 644
650/* 645/*
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 3c082451ab1a..2c75b33db4ac 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -83,6 +83,7 @@ struct vfio_dma {
83 size_t size; /* Map size (bytes) */ 83 size_t size; /* Map size (bytes) */
84 int prot; /* IOMMU_READ/WRITE */ 84 int prot; /* IOMMU_READ/WRITE */
85 bool iommu_mapped; 85 bool iommu_mapped;
86 bool lock_cap; /* capable(CAP_IPC_LOCK) */
86 struct task_struct *task; 87 struct task_struct *task;
87 struct rb_root pfn_list; /* Ex-user pinned pfn list */ 88 struct rb_root pfn_list; /* Ex-user pinned pfn list */
88}; 89};
@@ -253,29 +254,25 @@ static int vfio_iova_put_vfio_pfn(struct vfio_dma *dma, struct vfio_pfn *vpfn)
253 return ret; 254 return ret;
254} 255}
255 256
256static int vfio_lock_acct(struct task_struct *task, long npage, bool *lock_cap) 257static int vfio_lock_acct(struct vfio_dma *dma, long npage, bool async)
257{ 258{
258 struct mm_struct *mm; 259 struct mm_struct *mm;
259 bool is_current;
260 int ret; 260 int ret;
261 261
262 if (!npage) 262 if (!npage)
263 return 0; 263 return 0;
264 264
265 is_current = (task->mm == current->mm); 265 mm = async ? get_task_mm(dma->task) : dma->task->mm;
266
267 mm = is_current ? task->mm : get_task_mm(task);
268 if (!mm) 266 if (!mm)
269 return -ESRCH; /* process exited */ 267 return -ESRCH; /* process exited */
270 268
271 ret = down_write_killable(&mm->mmap_sem); 269 ret = down_write_killable(&mm->mmap_sem);
272 if (!ret) { 270 if (!ret) {
273 if (npage > 0) { 271 if (npage > 0) {
274 if (lock_cap ? !*lock_cap : 272 if (!dma->lock_cap) {
275 !has_capability(task, CAP_IPC_LOCK)) {
276 unsigned long limit; 273 unsigned long limit;
277 274
278 limit = task_rlimit(task, 275 limit = task_rlimit(dma->task,
279 RLIMIT_MEMLOCK) >> PAGE_SHIFT; 276 RLIMIT_MEMLOCK) >> PAGE_SHIFT;
280 277
281 if (mm->locked_vm + npage > limit) 278 if (mm->locked_vm + npage > limit)
@@ -289,7 +286,7 @@ static int vfio_lock_acct(struct task_struct *task, long npage, bool *lock_cap)
289 up_write(&mm->mmap_sem); 286 up_write(&mm->mmap_sem);
290 } 287 }
291 288
292 if (!is_current) 289 if (async)
293 mmput(mm); 290 mmput(mm);
294 291
295 return ret; 292 return ret;
@@ -400,7 +397,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
400 */ 397 */
401static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr, 398static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
402 long npage, unsigned long *pfn_base, 399 long npage, unsigned long *pfn_base,
403 bool lock_cap, unsigned long limit) 400 unsigned long limit)
404{ 401{
405 unsigned long pfn = 0; 402 unsigned long pfn = 0;
406 long ret, pinned = 0, lock_acct = 0; 403 long ret, pinned = 0, lock_acct = 0;
@@ -423,7 +420,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
423 * pages are already counted against the user. 420 * pages are already counted against the user.
424 */ 421 */
425 if (!rsvd && !vfio_find_vpfn(dma, iova)) { 422 if (!rsvd && !vfio_find_vpfn(dma, iova)) {
426 if (!lock_cap && current->mm->locked_vm + 1 > limit) { 423 if (!dma->lock_cap && current->mm->locked_vm + 1 > limit) {
427 put_pfn(*pfn_base, dma->prot); 424 put_pfn(*pfn_base, dma->prot);
428 pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__, 425 pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__,
429 limit << PAGE_SHIFT); 426 limit << PAGE_SHIFT);
@@ -449,7 +446,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
449 } 446 }
450 447
451 if (!rsvd && !vfio_find_vpfn(dma, iova)) { 448 if (!rsvd && !vfio_find_vpfn(dma, iova)) {
452 if (!lock_cap && 449 if (!dma->lock_cap &&
453 current->mm->locked_vm + lock_acct + 1 > limit) { 450 current->mm->locked_vm + lock_acct + 1 > limit) {
454 put_pfn(pfn, dma->prot); 451 put_pfn(pfn, dma->prot);
455 pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", 452 pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
@@ -462,7 +459,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
462 } 459 }
463 460
464out: 461out:
465 ret = vfio_lock_acct(current, lock_acct, &lock_cap); 462 ret = vfio_lock_acct(dma, lock_acct, false);
466 463
467unpin_out: 464unpin_out:
468 if (ret) { 465 if (ret) {
@@ -493,7 +490,7 @@ static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova,
493 } 490 }
494 491
495 if (do_accounting) 492 if (do_accounting)
496 vfio_lock_acct(dma->task, locked - unlocked, NULL); 493 vfio_lock_acct(dma, locked - unlocked, true);
497 494
498 return unlocked; 495 return unlocked;
499} 496}
@@ -510,7 +507,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
510 507
511 ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base); 508 ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base);
512 if (!ret && do_accounting && !is_invalid_reserved_pfn(*pfn_base)) { 509 if (!ret && do_accounting && !is_invalid_reserved_pfn(*pfn_base)) {
513 ret = vfio_lock_acct(dma->task, 1, NULL); 510 ret = vfio_lock_acct(dma, 1, true);
514 if (ret) { 511 if (ret) {
515 put_pfn(*pfn_base, dma->prot); 512 put_pfn(*pfn_base, dma->prot);
516 if (ret == -ENOMEM) 513 if (ret == -ENOMEM)
@@ -537,7 +534,7 @@ static int vfio_unpin_page_external(struct vfio_dma *dma, dma_addr_t iova,
537 unlocked = vfio_iova_put_vfio_pfn(dma, vpfn); 534 unlocked = vfio_iova_put_vfio_pfn(dma, vpfn);
538 535
539 if (do_accounting) 536 if (do_accounting)
540 vfio_lock_acct(dma->task, -unlocked, NULL); 537 vfio_lock_acct(dma, -unlocked, true);
541 538
542 return unlocked; 539 return unlocked;
543} 540}
@@ -829,7 +826,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
829 unlocked += vfio_sync_unpin(dma, domain, &unmapped_region_list); 826 unlocked += vfio_sync_unpin(dma, domain, &unmapped_region_list);
830 827
831 if (do_accounting) { 828 if (do_accounting) {
832 vfio_lock_acct(dma->task, -unlocked, NULL); 829 vfio_lock_acct(dma, -unlocked, true);
833 return 0; 830 return 0;
834 } 831 }
835 return unlocked; 832 return unlocked;
@@ -1044,14 +1041,12 @@ static int vfio_pin_map_dma(struct vfio_iommu *iommu, struct vfio_dma *dma,
1044 size_t size = map_size; 1041 size_t size = map_size;
1045 long npage; 1042 long npage;
1046 unsigned long pfn, limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 1043 unsigned long pfn, limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
1047 bool lock_cap = capable(CAP_IPC_LOCK);
1048 int ret = 0; 1044 int ret = 0;
1049 1045
1050 while (size) { 1046 while (size) {
1051 /* Pin a contiguous chunk of memory */ 1047 /* Pin a contiguous chunk of memory */
1052 npage = vfio_pin_pages_remote(dma, vaddr + dma->size, 1048 npage = vfio_pin_pages_remote(dma, vaddr + dma->size,
1053 size >> PAGE_SHIFT, &pfn, 1049 size >> PAGE_SHIFT, &pfn, limit);
1054 lock_cap, limit);
1055 if (npage <= 0) { 1050 if (npage <= 0) {
1056 WARN_ON(!npage); 1051 WARN_ON(!npage);
1057 ret = (int)npage; 1052 ret = (int)npage;
@@ -1126,8 +1121,36 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
1126 dma->iova = iova; 1121 dma->iova = iova;
1127 dma->vaddr = vaddr; 1122 dma->vaddr = vaddr;
1128 dma->prot = prot; 1123 dma->prot = prot;
1129 get_task_struct(current); 1124
1130 dma->task = current; 1125 /*
1126 * We need to be able to both add to a task's locked memory and test
1127 * against the locked memory limit and we need to be able to do both
1128 * outside of this call path as pinning can be asynchronous via the
1129 * external interfaces for mdev devices. RLIMIT_MEMLOCK requires a
1130 * task_struct and VM locked pages requires an mm_struct, however
1131 * holding an indefinite mm reference is not recommended, therefore we
1132 * only hold a reference to a task. We could hold a reference to
1133 * current, however QEMU uses this call path through vCPU threads,
1134 * which can be killed resulting in a NULL mm and failure in the unmap
1135 * path when called via a different thread. Avoid this problem by
1136 * using the group_leader as threads within the same group require
1137 * both CLONE_THREAD and CLONE_VM and will therefore use the same
1138 * mm_struct.
1139 *
1140 * Previously we also used the task for testing CAP_IPC_LOCK at the
1141 * time of pinning and accounting, however has_capability() makes use
1142 * of real_cred, a copy-on-write field, so we can't guarantee that it
1143 * matches group_leader, or in fact that it might not change by the
1144 * time it's evaluated. If a process were to call MAP_DMA with
1145 * CAP_IPC_LOCK but later drop it, it doesn't make sense that they
1146 * possibly see different results for an iommu_mapped vfio_dma vs
1147 * externally mapped. Therefore track CAP_IPC_LOCK in vfio_dma at the
1148 * time of calling MAP_DMA.
1149 */
1150 get_task_struct(current->group_leader);
1151 dma->task = current->group_leader;
1152 dma->lock_cap = capable(CAP_IPC_LOCK);
1153
1131 dma->pfn_list = RB_ROOT; 1154 dma->pfn_list = RB_ROOT;
1132 1155
1133 /* Insert zero-sized and grow as we map chunks of it */ 1156 /* Insert zero-sized and grow as we map chunks of it */
@@ -1162,7 +1185,6 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
1162 struct vfio_domain *d; 1185 struct vfio_domain *d;
1163 struct rb_node *n; 1186 struct rb_node *n;
1164 unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; 1187 unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
1165 bool lock_cap = capable(CAP_IPC_LOCK);
1166 int ret; 1188 int ret;
1167 1189
1168 /* Arbitrarily pick the first domain in the list for lookups */ 1190 /* Arbitrarily pick the first domain in the list for lookups */
@@ -1209,8 +1231,7 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
1209 1231
1210 npage = vfio_pin_pages_remote(dma, vaddr, 1232 npage = vfio_pin_pages_remote(dma, vaddr,
1211 n >> PAGE_SHIFT, 1233 n >> PAGE_SHIFT,
1212 &pfn, lock_cap, 1234 &pfn, limit);
1213 limit);
1214 if (npage <= 0) { 1235 if (npage <= 0) {
1215 WARN_ON(!npage); 1236 WARN_ON(!npage);
1216 ret = (int)npage; 1237 ret = (int)npage;
@@ -1487,7 +1508,7 @@ static void vfio_iommu_unmap_unpin_reaccount(struct vfio_iommu *iommu)
1487 if (!is_invalid_reserved_pfn(vpfn->pfn)) 1508 if (!is_invalid_reserved_pfn(vpfn->pfn))
1488 locked++; 1509 locked++;
1489 } 1510 }
1490 vfio_lock_acct(dma->task, locked - unlocked, NULL); 1511 vfio_lock_acct(dma, locked - unlocked, true);
1491 } 1512 }
1492} 1513}
1493 1514
diff --git a/samples/Kconfig b/samples/Kconfig
index 3db002b9e1d3..bd133efc1a56 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -115,6 +115,37 @@ config SAMPLE_VFIO_MDEV_MTTY
115 Build a virtual tty sample driver for use as a VFIO 115 Build a virtual tty sample driver for use as a VFIO
116 mediated device 116 mediated device
117 117
118config SAMPLE_VFIO_MDEV_MDPY
119 tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
120 depends on VFIO_MDEV_DEVICE && m
121 help
122 Build a virtual display sample driver for use as a VFIO
123 mediated device. It is a simple framebuffer and supports
124 the region display interface (VFIO_GFX_PLANE_TYPE_REGION).
125
126config SAMPLE_VFIO_MDEV_MDPY_FB
127 tristate "Build VFIO mdpy example guest fbdev driver -- loadable module only"
128 depends on FB && m
129 select FB_CFB_FILLRECT
130 select FB_CFB_COPYAREA
131 select FB_CFB_IMAGEBLIT
132 help
133 Guest fbdev driver for the virtual display sample driver.
134
135config SAMPLE_VFIO_MDEV_MBOCHS
136 tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
137 depends on VFIO_MDEV_DEVICE && m
138 select DMA_SHARED_BUFFER
139 help
140 Build a virtual display sample driver for use as a VFIO
141 mediated device. It supports the region display interface
142 (VFIO_GFX_PLANE_TYPE_DMABUF).
143 Emulate enough of qemu stdvga to make bochs-drm.ko happy.
144 That is basically the vram memory bar and the bochs dispi
145 interface vbe registers in the mmio register bar.
146 Specifically it does *not* include any legacy vga stuff.
147 Device looks a lot like "qemu -device secondary-vga".
148
118config SAMPLE_STATX 149config SAMPLE_STATX
119 bool "Build example extended-stat using code" 150 bool "Build example extended-stat using code"
120 depends on BROKEN 151 depends on BROKEN
diff --git a/samples/vfio-mdev/Makefile b/samples/vfio-mdev/Makefile
index cbbd868a50a8..7db889ca135c 100644
--- a/samples/vfio-mdev/Makefile
+++ b/samples/vfio-mdev/Makefile
@@ -1 +1,4 @@
1obj-$(CONFIG_SAMPLE_VFIO_MDEV_MTTY) += mtty.o 1obj-$(CONFIG_SAMPLE_VFIO_MDEV_MTTY) += mtty.o
2obj-$(CONFIG_SAMPLE_VFIO_MDEV_MDPY) += mdpy.o
3obj-$(CONFIG_SAMPLE_VFIO_MDEV_MDPY_FB) += mdpy-fb.o
4obj-$(CONFIG_SAMPLE_VFIO_MDEV_MBOCHS) += mbochs.o
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
new file mode 100644
index 000000000000..2960e26c6ea4
--- /dev/null
+++ b/samples/vfio-mdev/mbochs.c
@@ -0,0 +1,1406 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Mediated virtual PCI display host device driver
4 *
5 * Emulate enough of qemu stdvga to make bochs-drm.ko happy. That is
6 * basically the vram memory bar and the bochs dispi interface vbe
7 * registers in the mmio register bar. Specifically it does *not*
8 * include any legacy vga stuff. Device looks a lot like "qemu -device
9 * secondary-vga".
10 *
11 * (c) Gerd Hoffmann <kraxel@redhat.com>
12 *
13 * based on mtty driver which is:
14 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
15 * Author: Neo Jia <cjia@nvidia.com>
16 * Kirti Wankhede <kwankhede@nvidia.com>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License version 2 as
20 * published by the Free Software Foundation.
21 */
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/device.h>
25#include <linux/kernel.h>
26#include <linux/slab.h>
27#include <linux/vmalloc.h>
28#include <linux/cdev.h>
29#include <linux/vfio.h>
30#include <linux/iommu.h>
31#include <linux/sysfs.h>
32#include <linux/mdev.h>
33#include <linux/pci.h>
34#include <linux/dma-buf.h>
35#include <linux/highmem.h>
36#include <drm/drm_fourcc.h>
37#include <drm/drm_rect.h>
38#include <drm/drm_modeset_lock.h>
39#include <drm/drm_property.h>
40#include <drm/drm_plane.h>
41
42
43#define VBE_DISPI_INDEX_ID 0x0
44#define VBE_DISPI_INDEX_XRES 0x1
45#define VBE_DISPI_INDEX_YRES 0x2
46#define VBE_DISPI_INDEX_BPP 0x3
47#define VBE_DISPI_INDEX_ENABLE 0x4
48#define VBE_DISPI_INDEX_BANK 0x5
49#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
50#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
51#define VBE_DISPI_INDEX_X_OFFSET 0x8
52#define VBE_DISPI_INDEX_Y_OFFSET 0x9
53#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
54#define VBE_DISPI_INDEX_COUNT 0xb
55
56#define VBE_DISPI_ID0 0xB0C0
57#define VBE_DISPI_ID1 0xB0C1
58#define VBE_DISPI_ID2 0xB0C2
59#define VBE_DISPI_ID3 0xB0C3
60#define VBE_DISPI_ID4 0xB0C4
61#define VBE_DISPI_ID5 0xB0C5
62
63#define VBE_DISPI_DISABLED 0x00
64#define VBE_DISPI_ENABLED 0x01
65#define VBE_DISPI_GETCAPS 0x02
66#define VBE_DISPI_8BIT_DAC 0x20
67#define VBE_DISPI_LFB_ENABLED 0x40
68#define VBE_DISPI_NOCLEARMEM 0x80
69
70
71#define MBOCHS_NAME "mbochs"
72#define MBOCHS_CLASS_NAME "mbochs"
73
74#define MBOCHS_CONFIG_SPACE_SIZE 0xff
75#define MBOCHS_MMIO_BAR_OFFSET PAGE_SIZE
76#define MBOCHS_MMIO_BAR_SIZE PAGE_SIZE
77#define MBOCHS_MEMORY_BAR_OFFSET (MBOCHS_MMIO_BAR_OFFSET + \
78 MBOCHS_MMIO_BAR_SIZE)
79
80#define STORE_LE16(addr, val) (*(u16 *)addr = val)
81#define STORE_LE32(addr, val) (*(u32 *)addr = val)
82
83
84MODULE_LICENSE("GPL v2");
85
86static int max_mbytes = 256;
87module_param_named(count, max_mbytes, int, 0444);
88MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices");
89
90
91#define MBOCHS_TYPE_1 "small"
92#define MBOCHS_TYPE_2 "medium"
93#define MBOCHS_TYPE_3 "large"
94
95static const struct mbochs_type {
96 const char *name;
97 u32 mbytes;
98} mbochs_types[] = {
99 {
100 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
101 .mbytes = 4,
102 }, {
103 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
104 .mbytes = 16,
105 }, {
106 .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
107 .mbytes = 64,
108 },
109};
110
111
112static dev_t mbochs_devt;
113static struct class *mbochs_class;
114static struct cdev mbochs_cdev;
115static struct device mbochs_dev;
116static int mbochs_used_mbytes;
117
118struct mbochs_mode {
119 u32 drm_format;
120 u32 bytepp;
121 u32 width;
122 u32 height;
123 u32 stride;
124 u32 __pad;
125 u64 offset;
126 u64 size;
127};
128
129struct mbochs_dmabuf {
130 struct mbochs_mode mode;
131 u32 id;
132 struct page **pages;
133 pgoff_t pagecount;
134 struct dma_buf *buf;
135 struct mdev_state *mdev_state;
136 struct list_head next;
137 bool unlinked;
138};
139
140/* State of each mdev device */
141struct mdev_state {
142 u8 *vconfig;
143 u64 bar_mask[3];
144 u32 memory_bar_mask;
145 struct mutex ops_lock;
146 struct mdev_device *mdev;
147 struct vfio_device_info dev_info;
148
149 const struct mbochs_type *type;
150 u16 vbe[VBE_DISPI_INDEX_COUNT];
151 u64 memsize;
152 struct page **pages;
153 pgoff_t pagecount;
154
155 struct list_head dmabufs;
156 u32 active_id;
157 u32 next_id;
158};
159
160static const char *vbe_name_list[VBE_DISPI_INDEX_COUNT] = {
161 [VBE_DISPI_INDEX_ID] = "id",
162 [VBE_DISPI_INDEX_XRES] = "xres",
163 [VBE_DISPI_INDEX_YRES] = "yres",
164 [VBE_DISPI_INDEX_BPP] = "bpp",
165 [VBE_DISPI_INDEX_ENABLE] = "enable",
166 [VBE_DISPI_INDEX_BANK] = "bank",
167 [VBE_DISPI_INDEX_VIRT_WIDTH] = "virt-width",
168 [VBE_DISPI_INDEX_VIRT_HEIGHT] = "virt-height",
169 [VBE_DISPI_INDEX_X_OFFSET] = "x-offset",
170 [VBE_DISPI_INDEX_Y_OFFSET] = "y-offset",
171 [VBE_DISPI_INDEX_VIDEO_MEMORY_64K] = "video-mem",
172};
173
174static const char *vbe_name(u32 index)
175{
176 if (index < ARRAY_SIZE(vbe_name_list))
177 return vbe_name_list[index];
178 return "(invalid)";
179}
180
181static struct page *mbochs_get_page(struct mdev_state *mdev_state,
182 pgoff_t pgoff);
183
184static const struct mbochs_type *mbochs_find_type(struct kobject *kobj)
185{
186 int i;
187
188 for (i = 0; i < ARRAY_SIZE(mbochs_types); i++)
189 if (strcmp(mbochs_types[i].name, kobj->name) == 0)
190 return mbochs_types + i;
191 return NULL;
192}
193
194static void mbochs_create_config_space(struct mdev_state *mdev_state)
195{
196 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_VENDOR_ID],
197 0x1234);
198 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_DEVICE_ID],
199 0x1111);
200 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_VENDOR_ID],
201 PCI_SUBVENDOR_ID_REDHAT_QUMRANET);
202 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_ID],
203 PCI_SUBDEVICE_ID_QEMU);
204
205 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_COMMAND],
206 PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
207 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_CLASS_DEVICE],
208 PCI_CLASS_DISPLAY_OTHER);
209 mdev_state->vconfig[PCI_CLASS_REVISION] = 0x01;
210
211 STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_0],
212 PCI_BASE_ADDRESS_SPACE_MEMORY |
213 PCI_BASE_ADDRESS_MEM_TYPE_32 |
214 PCI_BASE_ADDRESS_MEM_PREFETCH);
215 mdev_state->bar_mask[0] = ~(mdev_state->memsize) + 1;
216
217 STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_2],
218 PCI_BASE_ADDRESS_SPACE_MEMORY |
219 PCI_BASE_ADDRESS_MEM_TYPE_32);
220 mdev_state->bar_mask[2] = ~(MBOCHS_MMIO_BAR_SIZE) + 1;
221}
222
223static int mbochs_check_framebuffer(struct mdev_state *mdev_state,
224 struct mbochs_mode *mode)
225{
226 struct device *dev = mdev_dev(mdev_state->mdev);
227 u16 *vbe = mdev_state->vbe;
228 u32 virt_width;
229
230 WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
231
232 if (!(vbe[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED))
233 goto nofb;
234
235 memset(mode, 0, sizeof(*mode));
236 switch (vbe[VBE_DISPI_INDEX_BPP]) {
237 case 32:
238 mode->drm_format = DRM_FORMAT_XRGB8888;
239 mode->bytepp = 4;
240 break;
241 default:
242 dev_info_ratelimited(dev, "%s: bpp %d not supported\n",
243 __func__, vbe[VBE_DISPI_INDEX_BPP]);
244 goto nofb;
245 }
246
247 mode->width = vbe[VBE_DISPI_INDEX_XRES];
248 mode->height = vbe[VBE_DISPI_INDEX_YRES];
249 virt_width = vbe[VBE_DISPI_INDEX_VIRT_WIDTH];
250 if (virt_width < mode->width)
251 virt_width = mode->width;
252 mode->stride = virt_width * mode->bytepp;
253 mode->size = (u64)mode->stride * mode->height;
254 mode->offset = ((u64)vbe[VBE_DISPI_INDEX_X_OFFSET] * mode->bytepp +
255 (u64)vbe[VBE_DISPI_INDEX_Y_OFFSET] * mode->stride);
256
257 if (mode->width < 64 || mode->height < 64) {
258 dev_info_ratelimited(dev, "%s: invalid resolution %dx%d\n",
259 __func__, mode->width, mode->height);
260 goto nofb;
261 }
262 if (mode->offset + mode->size > mdev_state->memsize) {
263 dev_info_ratelimited(dev, "%s: framebuffer memory overflow\n",
264 __func__);
265 goto nofb;
266 }
267
268 return 0;
269
270nofb:
271 memset(mode, 0, sizeof(*mode));
272 return -EINVAL;
273}
274
275static bool mbochs_modes_equal(struct mbochs_mode *mode1,
276 struct mbochs_mode *mode2)
277{
278 return memcmp(mode1, mode2, sizeof(struct mbochs_mode)) == 0;
279}
280
281static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
282 char *buf, u32 count)
283{
284 struct device *dev = mdev_dev(mdev_state->mdev);
285 int index = (offset - PCI_BASE_ADDRESS_0) / 0x04;
286 u32 cfg_addr;
287
288 switch (offset) {
289 case PCI_BASE_ADDRESS_0:
290 case PCI_BASE_ADDRESS_2:
291 cfg_addr = *(u32 *)buf;
292
293 if (cfg_addr == 0xffffffff) {
294 cfg_addr = (cfg_addr & mdev_state->bar_mask[index]);
295 } else {
296 cfg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
297 if (cfg_addr)
298 dev_info(dev, "BAR #%d @ 0x%x\n",
299 index, cfg_addr);
300 }
301
302 cfg_addr |= (mdev_state->vconfig[offset] &
303 ~PCI_BASE_ADDRESS_MEM_MASK);
304 STORE_LE32(&mdev_state->vconfig[offset], cfg_addr);
305 break;
306 }
307}
308
309static void handle_mmio_write(struct mdev_state *mdev_state, u16 offset,
310 char *buf, u32 count)
311{
312 struct device *dev = mdev_dev(mdev_state->mdev);
313 int index;
314 u16 reg16;
315
316 switch (offset) {
317 case 0x400 ... 0x41f: /* vga ioports remapped */
318 goto unhandled;
319 case 0x500 ... 0x515: /* bochs dispi interface */
320 if (count != 2)
321 goto unhandled;
322 index = (offset - 0x500) / 2;
323 reg16 = *(u16 *)buf;
324 if (index < ARRAY_SIZE(mdev_state->vbe))
325 mdev_state->vbe[index] = reg16;
326 dev_dbg(dev, "%s: vbe write %d = %d (%s)\n",
327 __func__, index, reg16, vbe_name(index));
328 break;
329 case 0x600 ... 0x607: /* qemu extended regs */
330 goto unhandled;
331 default:
332unhandled:
333 dev_dbg(dev, "%s: @0x%03x, count %d (unhandled)\n",
334 __func__, offset, count);
335 break;
336 }
337}
338
339static void handle_mmio_read(struct mdev_state *mdev_state, u16 offset,
340 char *buf, u32 count)
341{
342 struct device *dev = mdev_dev(mdev_state->mdev);
343 u16 reg16 = 0;
344 int index;
345
346 switch (offset) {
347 case 0x500 ... 0x515: /* bochs dispi interface */
348 if (count != 2)
349 goto unhandled;
350 index = (offset - 0x500) / 2;
351 if (index < ARRAY_SIZE(mdev_state->vbe))
352 reg16 = mdev_state->vbe[index];
353 dev_dbg(dev, "%s: vbe read %d = %d (%s)\n",
354 __func__, index, reg16, vbe_name(index));
355 *(u16 *)buf = reg16;
356 break;
357 default:
358unhandled:
359 dev_dbg(dev, "%s: @0x%03x, count %d (unhandled)\n",
360 __func__, offset, count);
361 memset(buf, 0, count);
362 break;
363 }
364}
365
366static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
367 loff_t pos, bool is_write)
368{
369 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
370 struct device *dev = mdev_dev(mdev);
371 struct page *pg;
372 loff_t poff;
373 char *map;
374 int ret = 0;
375
376 mutex_lock(&mdev_state->ops_lock);
377
378 if (pos < MBOCHS_CONFIG_SPACE_SIZE) {
379 if (is_write)
380 handle_pci_cfg_write(mdev_state, pos, buf, count);
381 else
382 memcpy(buf, (mdev_state->vconfig + pos), count);
383
384 } else if (pos >= MBOCHS_MMIO_BAR_OFFSET &&
385 pos + count <= MBOCHS_MEMORY_BAR_OFFSET) {
386 pos -= MBOCHS_MMIO_BAR_OFFSET;
387 if (is_write)
388 handle_mmio_write(mdev_state, pos, buf, count);
389 else
390 handle_mmio_read(mdev_state, pos, buf, count);
391
392 } else if (pos >= MBOCHS_MEMORY_BAR_OFFSET &&
393 pos + count <=
394 MBOCHS_MEMORY_BAR_OFFSET + mdev_state->memsize) {
395 pos -= MBOCHS_MMIO_BAR_OFFSET;
396 poff = pos & ~PAGE_MASK;
397 pg = mbochs_get_page(mdev_state, pos >> PAGE_SHIFT);
398 map = kmap(pg);
399 if (is_write)
400 memcpy(map + poff, buf, count);
401 else
402 memcpy(buf, map + poff, count);
403 kunmap(pg);
404 put_page(pg);
405
406 } else {
407 dev_dbg(dev, "%s: %s @0x%llx (unhandled)\n",
408 __func__, is_write ? "WR" : "RD", pos);
409 ret = -1;
410 goto accessfailed;
411 }
412
413 ret = count;
414
415
416accessfailed:
417 mutex_unlock(&mdev_state->ops_lock);
418
419 return ret;
420}
421
422static int mbochs_reset(struct mdev_device *mdev)
423{
424 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
425 u32 size64k = mdev_state->memsize / (64 * 1024);
426 int i;
427
428 for (i = 0; i < ARRAY_SIZE(mdev_state->vbe); i++)
429 mdev_state->vbe[i] = 0;
430 mdev_state->vbe[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
431 mdev_state->vbe[VBE_DISPI_INDEX_VIDEO_MEMORY_64K] = size64k;
432 return 0;
433}
434
435static int mbochs_create(struct kobject *kobj, struct mdev_device *mdev)
436{
437 const struct mbochs_type *type = mbochs_find_type(kobj);
438 struct device *dev = mdev_dev(mdev);
439 struct mdev_state *mdev_state;
440
441 if (!type)
442 type = &mbochs_types[0];
443 if (type->mbytes + mbochs_used_mbytes > max_mbytes)
444 return -ENOMEM;
445
446 mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
447 if (mdev_state == NULL)
448 return -ENOMEM;
449
450 mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
451 if (mdev_state->vconfig == NULL)
452 goto err_mem;
453
454 mdev_state->memsize = type->mbytes * 1024 * 1024;
455 mdev_state->pagecount = mdev_state->memsize >> PAGE_SHIFT;
456 mdev_state->pages = kcalloc(mdev_state->pagecount,
457 sizeof(struct page *),
458 GFP_KERNEL);
459 if (!mdev_state->pages)
460 goto err_mem;
461
462 dev_info(dev, "%s: %s, %d MB, %ld pages\n", __func__,
463 kobj->name, type->mbytes, mdev_state->pagecount);
464
465 mutex_init(&mdev_state->ops_lock);
466 mdev_state->mdev = mdev;
467 mdev_set_drvdata(mdev, mdev_state);
468 INIT_LIST_HEAD(&mdev_state->dmabufs);
469 mdev_state->next_id = 1;
470
471 mdev_state->type = type;
472 mbochs_create_config_space(mdev_state);
473 mbochs_reset(mdev);
474
475 mbochs_used_mbytes += type->mbytes;
476 return 0;
477
478err_mem:
479 kfree(mdev_state->vconfig);
480 kfree(mdev_state);
481 return -ENOMEM;
482}
483
484static int mbochs_remove(struct mdev_device *mdev)
485{
486 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
487
488 mbochs_used_mbytes -= mdev_state->type->mbytes;
489 mdev_set_drvdata(mdev, NULL);
490 kfree(mdev_state->pages);
491 kfree(mdev_state->vconfig);
492 kfree(mdev_state);
493 return 0;
494}
495
496static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
497 size_t count, loff_t *ppos)
498{
499 unsigned int done = 0;
500 int ret;
501
502 while (count) {
503 size_t filled;
504
505 if (count >= 4 && !(*ppos % 4)) {
506 u32 val;
507
508 ret = mdev_access(mdev, (char *)&val, sizeof(val),
509 *ppos, false);
510 if (ret <= 0)
511 goto read_err;
512
513 if (copy_to_user(buf, &val, sizeof(val)))
514 goto read_err;
515
516 filled = 4;
517 } else if (count >= 2 && !(*ppos % 2)) {
518 u16 val;
519
520 ret = mdev_access(mdev, (char *)&val, sizeof(val),
521 *ppos, false);
522 if (ret <= 0)
523 goto read_err;
524
525 if (copy_to_user(buf, &val, sizeof(val)))
526 goto read_err;
527
528 filled = 2;
529 } else {
530 u8 val;
531
532 ret = mdev_access(mdev, (char *)&val, sizeof(val),
533 *ppos, false);
534 if (ret <= 0)
535 goto read_err;
536
537 if (copy_to_user(buf, &val, sizeof(val)))
538 goto read_err;
539
540 filled = 1;
541 }
542
543 count -= filled;
544 done += filled;
545 *ppos += filled;
546 buf += filled;
547 }
548
549 return done;
550
551read_err:
552 return -EFAULT;
553}
554
555static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
556 size_t count, loff_t *ppos)
557{
558 unsigned int done = 0;
559 int ret;
560
561 while (count) {
562 size_t filled;
563
564 if (count >= 4 && !(*ppos % 4)) {
565 u32 val;
566
567 if (copy_from_user(&val, buf, sizeof(val)))
568 goto write_err;
569
570 ret = mdev_access(mdev, (char *)&val, sizeof(val),
571 *ppos, true);
572 if (ret <= 0)
573 goto write_err;
574
575 filled = 4;
576 } else if (count >= 2 && !(*ppos % 2)) {
577 u16 val;
578
579 if (copy_from_user(&val, buf, sizeof(val)))
580 goto write_err;
581
582 ret = mdev_access(mdev, (char *)&val, sizeof(val),
583 *ppos, true);
584 if (ret <= 0)
585 goto write_err;
586
587 filled = 2;
588 } else {
589 u8 val;
590
591 if (copy_from_user(&val, buf, sizeof(val)))
592 goto write_err;
593
594 ret = mdev_access(mdev, (char *)&val, sizeof(val),
595 *ppos, true);
596 if (ret <= 0)
597 goto write_err;
598
599 filled = 1;
600 }
601 count -= filled;
602 done += filled;
603 *ppos += filled;
604 buf += filled;
605 }
606
607 return done;
608write_err:
609 return -EFAULT;
610}
611
612static struct page *__mbochs_get_page(struct mdev_state *mdev_state,
613 pgoff_t pgoff)
614{
615 WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
616
617 if (!mdev_state->pages[pgoff]) {
618 mdev_state->pages[pgoff] =
619 alloc_pages(GFP_HIGHUSER | __GFP_ZERO, 0);
620 if (!mdev_state->pages[pgoff])
621 return NULL;
622 }
623
624 get_page(mdev_state->pages[pgoff]);
625 return mdev_state->pages[pgoff];
626}
627
628static struct page *mbochs_get_page(struct mdev_state *mdev_state,
629 pgoff_t pgoff)
630{
631 struct page *page;
632
633 if (WARN_ON(pgoff >= mdev_state->pagecount))
634 return NULL;
635
636 mutex_lock(&mdev_state->ops_lock);
637 page = __mbochs_get_page(mdev_state, pgoff);
638 mutex_unlock(&mdev_state->ops_lock);
639
640 return page;
641}
642
643static void mbochs_put_pages(struct mdev_state *mdev_state)
644{
645 struct device *dev = mdev_dev(mdev_state->mdev);
646 int i, count = 0;
647
648 WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
649
650 for (i = 0; i < mdev_state->pagecount; i++) {
651 if (!mdev_state->pages[i])
652 continue;
653 put_page(mdev_state->pages[i]);
654 mdev_state->pages[i] = NULL;
655 count++;
656 }
657 dev_dbg(dev, "%s: %d pages released\n", __func__, count);
658}
659
660static int mbochs_region_vm_fault(struct vm_fault *vmf)
661{
662 struct vm_area_struct *vma = vmf->vma;
663 struct mdev_state *mdev_state = vma->vm_private_data;
664 pgoff_t page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
665
666 if (page_offset >= mdev_state->pagecount)
667 return VM_FAULT_SIGBUS;
668
669 vmf->page = mbochs_get_page(mdev_state, page_offset);
670 if (!vmf->page)
671 return VM_FAULT_SIGBUS;
672
673 return 0;
674}
675
676static const struct vm_operations_struct mbochs_region_vm_ops = {
677 .fault = mbochs_region_vm_fault,
678};
679
680static int mbochs_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
681{
682 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
683
684 if (vma->vm_pgoff != MBOCHS_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
685 return -EINVAL;
686 if (vma->vm_end < vma->vm_start)
687 return -EINVAL;
688 if (vma->vm_end - vma->vm_start > mdev_state->memsize)
689 return -EINVAL;
690 if ((vma->vm_flags & VM_SHARED) == 0)
691 return -EINVAL;
692
693 vma->vm_ops = &mbochs_region_vm_ops;
694 vma->vm_private_data = mdev_state;
695 return 0;
696}
697
698static int mbochs_dmabuf_vm_fault(struct vm_fault *vmf)
699{
700 struct vm_area_struct *vma = vmf->vma;
701 struct mbochs_dmabuf *dmabuf = vma->vm_private_data;
702
703 if (WARN_ON(vmf->pgoff >= dmabuf->pagecount))
704 return VM_FAULT_SIGBUS;
705
706 vmf->page = dmabuf->pages[vmf->pgoff];
707 get_page(vmf->page);
708 return 0;
709}
710
711static const struct vm_operations_struct mbochs_dmabuf_vm_ops = {
712 .fault = mbochs_dmabuf_vm_fault,
713};
714
715static int mbochs_mmap_dmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
716{
717 struct mbochs_dmabuf *dmabuf = buf->priv;
718 struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
719
720 dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
721
722 if ((vma->vm_flags & VM_SHARED) == 0)
723 return -EINVAL;
724
725 vma->vm_ops = &mbochs_dmabuf_vm_ops;
726 vma->vm_private_data = dmabuf;
727 return 0;
728}
729
730static void mbochs_print_dmabuf(struct mbochs_dmabuf *dmabuf,
731 const char *prefix)
732{
733 struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
734 u32 fourcc = dmabuf->mode.drm_format;
735
736 dev_dbg(dev, "%s/%d: %c%c%c%c, %dx%d, stride %d, off 0x%llx, size 0x%llx, pages %ld\n",
737 prefix, dmabuf->id,
738 fourcc ? ((fourcc >> 0) & 0xff) : '-',
739 fourcc ? ((fourcc >> 8) & 0xff) : '-',
740 fourcc ? ((fourcc >> 16) & 0xff) : '-',
741 fourcc ? ((fourcc >> 24) & 0xff) : '-',
742 dmabuf->mode.width, dmabuf->mode.height, dmabuf->mode.stride,
743 dmabuf->mode.offset, dmabuf->mode.size, dmabuf->pagecount);
744}
745
746static struct sg_table *mbochs_map_dmabuf(struct dma_buf_attachment *at,
747 enum dma_data_direction direction)
748{
749 struct mbochs_dmabuf *dmabuf = at->dmabuf->priv;
750 struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
751 struct sg_table *sg;
752
753 dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
754
755 sg = kzalloc(sizeof(*sg), GFP_KERNEL);
756 if (!sg)
757 goto err1;
758 if (sg_alloc_table_from_pages(sg, dmabuf->pages, dmabuf->pagecount,
759 0, dmabuf->mode.size, GFP_KERNEL) < 0)
760 goto err2;
761 if (!dma_map_sg(at->dev, sg->sgl, sg->nents, direction))
762 goto err3;
763
764 return sg;
765
766err3:
767 sg_free_table(sg);
768err2:
769 kfree(sg);
770err1:
771 return ERR_PTR(-ENOMEM);
772}
773
774static void mbochs_unmap_dmabuf(struct dma_buf_attachment *at,
775 struct sg_table *sg,
776 enum dma_data_direction direction)
777{
778 struct mbochs_dmabuf *dmabuf = at->dmabuf->priv;
779 struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
780
781 dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
782
783 sg_free_table(sg);
784 kfree(sg);
785}
786
787static void mbochs_release_dmabuf(struct dma_buf *buf)
788{
789 struct mbochs_dmabuf *dmabuf = buf->priv;
790 struct mdev_state *mdev_state = dmabuf->mdev_state;
791 struct device *dev = mdev_dev(mdev_state->mdev);
792 pgoff_t pg;
793
794 dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
795
796 for (pg = 0; pg < dmabuf->pagecount; pg++)
797 put_page(dmabuf->pages[pg]);
798
799 mutex_lock(&mdev_state->ops_lock);
800 dmabuf->buf = NULL;
801 if (dmabuf->unlinked)
802 kfree(dmabuf);
803 mutex_unlock(&mdev_state->ops_lock);
804}
805
806static void *mbochs_kmap_atomic_dmabuf(struct dma_buf *buf,
807 unsigned long page_num)
808{
809 struct mbochs_dmabuf *dmabuf = buf->priv;
810 struct page *page = dmabuf->pages[page_num];
811
812 return kmap_atomic(page);
813}
814
815static void *mbochs_kmap_dmabuf(struct dma_buf *buf, unsigned long page_num)
816{
817 struct mbochs_dmabuf *dmabuf = buf->priv;
818 struct page *page = dmabuf->pages[page_num];
819
820 return kmap(page);
821}
822
823static struct dma_buf_ops mbochs_dmabuf_ops = {
824 .map_dma_buf = mbochs_map_dmabuf,
825 .unmap_dma_buf = mbochs_unmap_dmabuf,
826 .release = mbochs_release_dmabuf,
827 .map_atomic = mbochs_kmap_atomic_dmabuf,
828 .map = mbochs_kmap_dmabuf,
829 .mmap = mbochs_mmap_dmabuf,
830};
831
832static struct mbochs_dmabuf *mbochs_dmabuf_alloc(struct mdev_state *mdev_state,
833 struct mbochs_mode *mode)
834{
835 struct mbochs_dmabuf *dmabuf;
836 pgoff_t page_offset, pg;
837
838 WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
839
840 dmabuf = kzalloc(sizeof(struct mbochs_dmabuf), GFP_KERNEL);
841 if (!dmabuf)
842 return NULL;
843
844 dmabuf->mode = *mode;
845 dmabuf->id = mdev_state->next_id++;
846 dmabuf->pagecount = DIV_ROUND_UP(mode->size, PAGE_SIZE);
847 dmabuf->pages = kcalloc(dmabuf->pagecount, sizeof(struct page *),
848 GFP_KERNEL);
849 if (!dmabuf->pages)
850 goto err_free_dmabuf;
851
852 page_offset = dmabuf->mode.offset >> PAGE_SHIFT;
853 for (pg = 0; pg < dmabuf->pagecount; pg++) {
854 dmabuf->pages[pg] = __mbochs_get_page(mdev_state,
855 page_offset + pg);
856 if (!dmabuf->pages[pg])
857 goto err_free_pages;
858 }
859
860 dmabuf->mdev_state = mdev_state;
861 list_add(&dmabuf->next, &mdev_state->dmabufs);
862
863 mbochs_print_dmabuf(dmabuf, __func__);
864 return dmabuf;
865
866err_free_pages:
867 while (pg > 0)
868 put_page(dmabuf->pages[--pg]);
869 kfree(dmabuf->pages);
870err_free_dmabuf:
871 kfree(dmabuf);
872 return NULL;
873}
874
875static struct mbochs_dmabuf *
876mbochs_dmabuf_find_by_mode(struct mdev_state *mdev_state,
877 struct mbochs_mode *mode)
878{
879 struct mbochs_dmabuf *dmabuf;
880
881 WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
882
883 list_for_each_entry(dmabuf, &mdev_state->dmabufs, next)
884 if (mbochs_modes_equal(&dmabuf->mode, mode))
885 return dmabuf;
886
887 return NULL;
888}
889
890static struct mbochs_dmabuf *
891mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
892{
893 struct mbochs_dmabuf *dmabuf;
894
895 WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
896
897 list_for_each_entry(dmabuf, &mdev_state->dmabufs, next)
898 if (dmabuf->id == id)
899 return dmabuf;
900
901 return NULL;
902}
903
904static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
905{
906 struct mdev_state *mdev_state = dmabuf->mdev_state;
907 struct device *dev = mdev_dev(mdev_state->mdev);
908 DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
909 struct dma_buf *buf;
910
911 WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
912
913 if (!IS_ALIGNED(dmabuf->mode.offset, PAGE_SIZE)) {
914 dev_info_ratelimited(dev, "%s: framebuffer not page-aligned\n",
915 __func__);
916 return -EINVAL;
917 }
918
919 exp_info.ops = &mbochs_dmabuf_ops;
920 exp_info.size = dmabuf->mode.size;
921 exp_info.priv = dmabuf;
922
923 buf = dma_buf_export(&exp_info);
924 if (IS_ERR(buf)) {
925 dev_info_ratelimited(dev, "%s: dma_buf_export failed: %ld\n",
926 __func__, PTR_ERR(buf));
927 return PTR_ERR(buf);
928 }
929
930 dmabuf->buf = buf;
931 dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
932 return 0;
933}
934
935static int mbochs_get_region_info(struct mdev_device *mdev,
936 struct vfio_region_info *region_info,
937 u16 *cap_type_id, void **cap_type)
938{
939 struct mdev_state *mdev_state;
940
941 mdev_state = mdev_get_drvdata(mdev);
942 if (!mdev_state)
943 return -EINVAL;
944
945 if (region_info->index >= VFIO_PCI_NUM_REGIONS)
946 return -EINVAL;
947
948 switch (region_info->index) {
949 case VFIO_PCI_CONFIG_REGION_INDEX:
950 region_info->offset = 0;
951 region_info->size = MBOCHS_CONFIG_SPACE_SIZE;
952 region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
953 VFIO_REGION_INFO_FLAG_WRITE);
954 break;
955 case VFIO_PCI_BAR0_REGION_INDEX:
956 region_info->offset = MBOCHS_MEMORY_BAR_OFFSET;
957 region_info->size = mdev_state->memsize;
958 region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
959 VFIO_REGION_INFO_FLAG_WRITE |
960 VFIO_REGION_INFO_FLAG_MMAP);
961 break;
962 case VFIO_PCI_BAR2_REGION_INDEX:
963 region_info->offset = MBOCHS_MMIO_BAR_OFFSET;
964 region_info->size = MBOCHS_MMIO_BAR_SIZE;
965 region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
966 VFIO_REGION_INFO_FLAG_WRITE);
967 break;
968 default:
969 region_info->size = 0;
970 region_info->offset = 0;
971 region_info->flags = 0;
972 }
973
974 return 0;
975}
976
977static int mbochs_get_irq_info(struct mdev_device *mdev,
978 struct vfio_irq_info *irq_info)
979{
980 irq_info->count = 0;
981 return 0;
982}
983
984static int mbochs_get_device_info(struct mdev_device *mdev,
985 struct vfio_device_info *dev_info)
986{
987 dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
988 dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
989 dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
990 return 0;
991}
992
993static int mbochs_query_gfx_plane(struct mdev_device *mdev,
994 struct vfio_device_gfx_plane_info *plane)
995{
996 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
997 struct device *dev = mdev_dev(mdev);
998 struct mbochs_dmabuf *dmabuf;
999 struct mbochs_mode mode;
1000 int ret;
1001
1002 if (plane->flags & VFIO_GFX_PLANE_TYPE_PROBE) {
1003 if (plane->flags == (VFIO_GFX_PLANE_TYPE_PROBE |
1004 VFIO_GFX_PLANE_TYPE_DMABUF))
1005 return 0;
1006 return -EINVAL;
1007 }
1008
1009 if (plane->flags != VFIO_GFX_PLANE_TYPE_DMABUF)
1010 return -EINVAL;
1011
1012 plane->drm_format_mod = 0;
1013 plane->x_pos = 0;
1014 plane->y_pos = 0;
1015 plane->x_hot = 0;
1016 plane->y_hot = 0;
1017
1018 mutex_lock(&mdev_state->ops_lock);
1019
1020 ret = -EINVAL;
1021 if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY)
1022 ret = mbochs_check_framebuffer(mdev_state, &mode);
1023 if (ret < 0) {
1024 plane->drm_format = 0;
1025 plane->width = 0;
1026 plane->height = 0;
1027 plane->stride = 0;
1028 plane->size = 0;
1029 plane->dmabuf_id = 0;
1030 goto done;
1031 }
1032
1033 dmabuf = mbochs_dmabuf_find_by_mode(mdev_state, &mode);
1034 if (!dmabuf)
1035 mbochs_dmabuf_alloc(mdev_state, &mode);
1036 if (!dmabuf) {
1037 mutex_unlock(&mdev_state->ops_lock);
1038 return -ENOMEM;
1039 }
1040
1041 plane->drm_format = dmabuf->mode.drm_format;
1042 plane->width = dmabuf->mode.width;
1043 plane->height = dmabuf->mode.height;
1044 plane->stride = dmabuf->mode.stride;
1045 plane->size = dmabuf->mode.size;
1046 plane->dmabuf_id = dmabuf->id;
1047
1048done:
1049 if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY &&
1050 mdev_state->active_id != plane->dmabuf_id) {
1051 dev_dbg(dev, "%s: primary: %d => %d\n", __func__,
1052 mdev_state->active_id, plane->dmabuf_id);
1053 mdev_state->active_id = plane->dmabuf_id;
1054 }
1055 mutex_unlock(&mdev_state->ops_lock);
1056 return 0;
1057}
1058
1059static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
1060 u32 id)
1061{
1062 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
1063 struct mbochs_dmabuf *dmabuf;
1064
1065 mutex_lock(&mdev_state->ops_lock);
1066
1067 dmabuf = mbochs_dmabuf_find_by_id(mdev_state, id);
1068 if (!dmabuf) {
1069 mutex_unlock(&mdev_state->ops_lock);
1070 return -ENOENT;
1071 }
1072
1073 if (!dmabuf->buf)
1074 mbochs_dmabuf_export(dmabuf);
1075
1076 mutex_unlock(&mdev_state->ops_lock);
1077
1078 if (!dmabuf->buf)
1079 return -EINVAL;
1080
1081 return dma_buf_fd(dmabuf->buf, 0);
1082}
1083
1084static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
1085 unsigned long arg)
1086{
1087 int ret = 0;
1088 unsigned long minsz;
1089 struct mdev_state *mdev_state;
1090
1091 mdev_state = mdev_get_drvdata(mdev);
1092
1093 switch (cmd) {
1094 case VFIO_DEVICE_GET_INFO:
1095 {
1096 struct vfio_device_info info;
1097
1098 minsz = offsetofend(struct vfio_device_info, num_irqs);
1099
1100 if (copy_from_user(&info, (void __user *)arg, minsz))
1101 return -EFAULT;
1102
1103 if (info.argsz < minsz)
1104 return -EINVAL;
1105
1106 ret = mbochs_get_device_info(mdev, &info);
1107 if (ret)
1108 return ret;
1109
1110 memcpy(&mdev_state->dev_info, &info, sizeof(info));
1111
1112 if (copy_to_user((void __user *)arg, &info, minsz))
1113 return -EFAULT;
1114
1115 return 0;
1116 }
1117 case VFIO_DEVICE_GET_REGION_INFO:
1118 {
1119 struct vfio_region_info info;
1120 u16 cap_type_id = 0;
1121 void *cap_type = NULL;
1122
1123 minsz = offsetofend(struct vfio_region_info, offset);
1124
1125 if (copy_from_user(&info, (void __user *)arg, minsz))
1126 return -EFAULT;
1127
1128 if (info.argsz < minsz)
1129 return -EINVAL;
1130
1131 ret = mbochs_get_region_info(mdev, &info, &cap_type_id,
1132 &cap_type);
1133 if (ret)
1134 return ret;
1135
1136 if (copy_to_user((void __user *)arg, &info, minsz))
1137 return -EFAULT;
1138
1139 return 0;
1140 }
1141
1142 case VFIO_DEVICE_GET_IRQ_INFO:
1143 {
1144 struct vfio_irq_info info;
1145
1146 minsz = offsetofend(struct vfio_irq_info, count);
1147
1148 if (copy_from_user(&info, (void __user *)arg, minsz))
1149 return -EFAULT;
1150
1151 if ((info.argsz < minsz) ||
1152 (info.index >= mdev_state->dev_info.num_irqs))
1153 return -EINVAL;
1154
1155 ret = mbochs_get_irq_info(mdev, &info);
1156 if (ret)
1157 return ret;
1158
1159 if (copy_to_user((void __user *)arg, &info, minsz))
1160 return -EFAULT;
1161
1162 return 0;
1163 }
1164
1165 case VFIO_DEVICE_QUERY_GFX_PLANE:
1166 {
1167 struct vfio_device_gfx_plane_info plane;
1168
1169 minsz = offsetofend(struct vfio_device_gfx_plane_info,
1170 region_index);
1171
1172 if (copy_from_user(&plane, (void __user *)arg, minsz))
1173 return -EFAULT;
1174
1175 if (plane.argsz < minsz)
1176 return -EINVAL;
1177
1178 ret = mbochs_query_gfx_plane(mdev, &plane);
1179 if (ret)
1180 return ret;
1181
1182 if (copy_to_user((void __user *)arg, &plane, minsz))
1183 return -EFAULT;
1184
1185 return 0;
1186 }
1187
1188 case VFIO_DEVICE_GET_GFX_DMABUF:
1189 {
1190 u32 dmabuf_id;
1191
1192 if (get_user(dmabuf_id, (__u32 __user *)arg))
1193 return -EFAULT;
1194
1195 return mbochs_get_gfx_dmabuf(mdev, dmabuf_id);
1196 }
1197
1198 case VFIO_DEVICE_SET_IRQS:
1199 return -EINVAL;
1200
1201 case VFIO_DEVICE_RESET:
1202 return mbochs_reset(mdev);
1203 }
1204 return -ENOTTY;
1205}
1206
1207static int mbochs_open(struct mdev_device *mdev)
1208{
1209 if (!try_module_get(THIS_MODULE))
1210 return -ENODEV;
1211
1212 return 0;
1213}
1214
1215static void mbochs_close(struct mdev_device *mdev)
1216{
1217 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
1218 struct mbochs_dmabuf *dmabuf, *tmp;
1219
1220 mutex_lock(&mdev_state->ops_lock);
1221
1222 list_for_each_entry_safe(dmabuf, tmp, &mdev_state->dmabufs, next) {
1223 list_del(&dmabuf->next);
1224 if (dmabuf->buf) {
1225 /* free in mbochs_release_dmabuf() */
1226 dmabuf->unlinked = true;
1227 } else {
1228 kfree(dmabuf);
1229 }
1230 }
1231 mbochs_put_pages(mdev_state);
1232
1233 mutex_unlock(&mdev_state->ops_lock);
1234 module_put(THIS_MODULE);
1235}
1236
1237static ssize_t
1238memory_show(struct device *dev, struct device_attribute *attr,
1239 char *buf)
1240{
1241 struct mdev_device *mdev = mdev_from_dev(dev);
1242 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
1243
1244 return sprintf(buf, "%d MB\n", mdev_state->type->mbytes);
1245}
1246static DEVICE_ATTR_RO(memory);
1247
1248static struct attribute *mdev_dev_attrs[] = {
1249 &dev_attr_memory.attr,
1250 NULL,
1251};
1252
1253static const struct attribute_group mdev_dev_group = {
1254 .name = "vendor",
1255 .attrs = mdev_dev_attrs,
1256};
1257
1258const struct attribute_group *mdev_dev_groups[] = {
1259 &mdev_dev_group,
1260 NULL,
1261};
1262
1263static ssize_t
1264name_show(struct kobject *kobj, struct device *dev, char *buf)
1265{
1266 return sprintf(buf, "%s\n", kobj->name);
1267}
1268MDEV_TYPE_ATTR_RO(name);
1269
1270static ssize_t
1271description_show(struct kobject *kobj, struct device *dev, char *buf)
1272{
1273 const struct mbochs_type *type = mbochs_find_type(kobj);
1274
1275 return sprintf(buf, "virtual display, %d MB video memory\n",
1276 type ? type->mbytes : 0);
1277}
1278MDEV_TYPE_ATTR_RO(description);
1279
1280static ssize_t
1281available_instances_show(struct kobject *kobj, struct device *dev, char *buf)
1282{
1283 const struct mbochs_type *type = mbochs_find_type(kobj);
1284 int count = (max_mbytes - mbochs_used_mbytes) / type->mbytes;
1285
1286 return sprintf(buf, "%d\n", count);
1287}
1288MDEV_TYPE_ATTR_RO(available_instances);
1289
1290static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
1291 char *buf)
1292{
1293 return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
1294}
1295MDEV_TYPE_ATTR_RO(device_api);
1296
1297static struct attribute *mdev_types_attrs[] = {
1298 &mdev_type_attr_name.attr,
1299 &mdev_type_attr_description.attr,
1300 &mdev_type_attr_device_api.attr,
1301 &mdev_type_attr_available_instances.attr,
1302 NULL,
1303};
1304
1305static struct attribute_group mdev_type_group1 = {
1306 .name = MBOCHS_TYPE_1,
1307 .attrs = mdev_types_attrs,
1308};
1309
1310static struct attribute_group mdev_type_group2 = {
1311 .name = MBOCHS_TYPE_2,
1312 .attrs = mdev_types_attrs,
1313};
1314
1315static struct attribute_group mdev_type_group3 = {
1316 .name = MBOCHS_TYPE_3,
1317 .attrs = mdev_types_attrs,
1318};
1319
1320static struct attribute_group *mdev_type_groups[] = {
1321 &mdev_type_group1,
1322 &mdev_type_group2,
1323 &mdev_type_group3,
1324 NULL,
1325};
1326
1327static const struct mdev_parent_ops mdev_fops = {
1328 .owner = THIS_MODULE,
1329 .mdev_attr_groups = mdev_dev_groups,
1330 .supported_type_groups = mdev_type_groups,
1331 .create = mbochs_create,
1332 .remove = mbochs_remove,
1333 .open = mbochs_open,
1334 .release = mbochs_close,
1335 .read = mbochs_read,
1336 .write = mbochs_write,
1337 .ioctl = mbochs_ioctl,
1338 .mmap = mbochs_mmap,
1339};
1340
1341static const struct file_operations vd_fops = {
1342 .owner = THIS_MODULE,
1343};
1344
1345static void mbochs_device_release(struct device *dev)
1346{
1347 /* nothing */
1348}
1349
1350static int __init mbochs_dev_init(void)
1351{
1352 int ret = 0;
1353
1354 ret = alloc_chrdev_region(&mbochs_devt, 0, MINORMASK, MBOCHS_NAME);
1355 if (ret < 0) {
1356 pr_err("Error: failed to register mbochs_dev, err: %d\n", ret);
1357 return ret;
1358 }
1359 cdev_init(&mbochs_cdev, &vd_fops);
1360 cdev_add(&mbochs_cdev, mbochs_devt, MINORMASK);
1361 pr_info("%s: major %d\n", __func__, MAJOR(mbochs_devt));
1362
1363 mbochs_class = class_create(THIS_MODULE, MBOCHS_CLASS_NAME);
1364 if (IS_ERR(mbochs_class)) {
1365 pr_err("Error: failed to register mbochs_dev class\n");
1366 ret = PTR_ERR(mbochs_class);
1367 goto failed1;
1368 }
1369 mbochs_dev.class = mbochs_class;
1370 mbochs_dev.release = mbochs_device_release;
1371 dev_set_name(&mbochs_dev, "%s", MBOCHS_NAME);
1372
1373 ret = device_register(&mbochs_dev);
1374 if (ret)
1375 goto failed2;
1376
1377 ret = mdev_register_device(&mbochs_dev, &mdev_fops);
1378 if (ret)
1379 goto failed3;
1380
1381 return 0;
1382
1383failed3:
1384 device_unregister(&mbochs_dev);
1385failed2:
1386 class_destroy(mbochs_class);
1387failed1:
1388 cdev_del(&mbochs_cdev);
1389 unregister_chrdev_region(mbochs_devt, MINORMASK);
1390 return ret;
1391}
1392
1393static void __exit mbochs_dev_exit(void)
1394{
1395 mbochs_dev.bus = NULL;
1396 mdev_unregister_device(&mbochs_dev);
1397
1398 device_unregister(&mbochs_dev);
1399 cdev_del(&mbochs_cdev);
1400 unregister_chrdev_region(mbochs_devt, MINORMASK);
1401 class_destroy(mbochs_class);
1402 mbochs_class = NULL;
1403}
1404
1405module_init(mbochs_dev_init)
1406module_exit(mbochs_dev_exit)
diff --git a/samples/vfio-mdev/mdpy-defs.h b/samples/vfio-mdev/mdpy-defs.h
new file mode 100644
index 000000000000..96b3b1b49d34
--- /dev/null
+++ b/samples/vfio-mdev/mdpy-defs.h
@@ -0,0 +1,22 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/*
3 * Simple pci display device.
4 *
5 * Framebuffer memory is pci bar 0.
6 * Configuration (read-only) is in pci config space.
7 * Format field uses drm fourcc codes.
8 * ATM only DRM_FORMAT_XRGB8888 is supported.
9 */
10
11/* pci ids */
12#define MDPY_PCI_VENDOR_ID 0x1b36 /* redhat */
13#define MDPY_PCI_DEVICE_ID 0x000f
14#define MDPY_PCI_SUBVENDOR_ID PCI_SUBVENDOR_ID_REDHAT_QUMRANET
15#define MDPY_PCI_SUBDEVICE_ID PCI_SUBDEVICE_ID_QEMU
16
17/* pci cfg space offsets for fb config (dword) */
18#define MDPY_VENDORCAP_OFFSET 0x40
19#define MDPY_VENDORCAP_SIZE 0x10
20#define MDPY_FORMAT_OFFSET (MDPY_VENDORCAP_OFFSET + 0x04)
21#define MDPY_WIDTH_OFFSET (MDPY_VENDORCAP_OFFSET + 0x08)
22#define MDPY_HEIGHT_OFFSET (MDPY_VENDORCAP_OFFSET + 0x0c)
diff --git a/samples/vfio-mdev/mdpy-fb.c b/samples/vfio-mdev/mdpy-fb.c
new file mode 100644
index 000000000000..2719bb259653
--- /dev/null
+++ b/samples/vfio-mdev/mdpy-fb.c
@@ -0,0 +1,232 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Framebuffer driver for mdpy (mediated virtual pci display device).
4 *
5 * See mdpy-defs.h for device specs
6 *
7 * (c) Gerd Hoffmann <kraxel@redhat.com>
8 *
9 * Using some code snippets from simplefb and cirrusfb.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2, as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19 */
20#include <linux/errno.h>
21#include <linux/fb.h>
22#include <linux/io.h>
23#include <linux/pci.h>
24#include <linux/module.h>
25#include <drm/drm_fourcc.h>
26#include "mdpy-defs.h"
27
28static const struct fb_fix_screeninfo mdpy_fb_fix = {
29 .id = "mdpy-fb",
30 .type = FB_TYPE_PACKED_PIXELS,
31 .visual = FB_VISUAL_TRUECOLOR,
32 .accel = FB_ACCEL_NONE,
33};
34
35static const struct fb_var_screeninfo mdpy_fb_var = {
36 .height = -1,
37 .width = -1,
38 .activate = FB_ACTIVATE_NOW,
39 .vmode = FB_VMODE_NONINTERLACED,
40
41 .bits_per_pixel = 32,
42 .transp.offset = 24,
43 .red.offset = 16,
44 .green.offset = 8,
45 .blue.offset = 0,
46 .transp.length = 8,
47 .red.length = 8,
48 .green.length = 8,
49 .blue.length = 8,
50};
51
52#define PSEUDO_PALETTE_SIZE 16
53
54struct mdpy_fb_par {
55 u32 palette[PSEUDO_PALETTE_SIZE];
56};
57
58static int mdpy_fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
59 u_int transp, struct fb_info *info)
60{
61 u32 *pal = info->pseudo_palette;
62 u32 cr = red >> (16 - info->var.red.length);
63 u32 cg = green >> (16 - info->var.green.length);
64 u32 cb = blue >> (16 - info->var.blue.length);
65 u32 value, mask;
66
67 if (regno >= PSEUDO_PALETTE_SIZE)
68 return -EINVAL;
69
70 value = (cr << info->var.red.offset) |
71 (cg << info->var.green.offset) |
72 (cb << info->var.blue.offset);
73 if (info->var.transp.length > 0) {
74 mask = (1 << info->var.transp.length) - 1;
75 mask <<= info->var.transp.offset;
76 value |= mask;
77 }
78 pal[regno] = value;
79
80 return 0;
81}
82
83static void mdpy_fb_destroy(struct fb_info *info)
84{
85 if (info->screen_base)
86 iounmap(info->screen_base);
87}
88
89static struct fb_ops mdpy_fb_ops = {
90 .owner = THIS_MODULE,
91 .fb_destroy = mdpy_fb_destroy,
92 .fb_setcolreg = mdpy_fb_setcolreg,
93 .fb_fillrect = cfb_fillrect,
94 .fb_copyarea = cfb_copyarea,
95 .fb_imageblit = cfb_imageblit,
96};
97
98static int mdpy_fb_probe(struct pci_dev *pdev,
99 const struct pci_device_id *ent)
100{
101 struct fb_info *info;
102 struct mdpy_fb_par *par;
103 u32 format, width, height;
104 int ret;
105
106 ret = pci_enable_device(pdev);
107 if (ret < 0)
108 return ret;
109
110 ret = pci_request_regions(pdev, "mdpy-fb");
111 if (ret < 0)
112 return ret;
113
114 pci_read_config_dword(pdev, MDPY_FORMAT_OFFSET, &format);
115 pci_read_config_dword(pdev, MDPY_WIDTH_OFFSET, &width);
116 pci_read_config_dword(pdev, MDPY_HEIGHT_OFFSET, &height);
117 if (format != DRM_FORMAT_XRGB8888) {
118 pci_err(pdev, "format mismatch (0x%x != 0x%x)\n",
119 format, DRM_FORMAT_XRGB8888);
120 return -EINVAL;
121 }
122 if (width < 100 || width > 10000) {
123 pci_err(pdev, "width (%d) out of range\n", width);
124 return -EINVAL;
125 }
126 if (height < 100 || height > 10000) {
127 pci_err(pdev, "height (%d) out of range\n", height);
128 return -EINVAL;
129 }
130 pci_info(pdev, "mdpy found: %dx%d framebuffer\n",
131 width, height);
132
133 info = framebuffer_alloc(sizeof(struct mdpy_fb_par), &pdev->dev);
134 if (!info)
135 goto err_release_regions;
136 pci_set_drvdata(pdev, info);
137 par = info->par;
138
139 info->fix = mdpy_fb_fix;
140 info->fix.smem_start = pci_resource_start(pdev, 0);
141 info->fix.smem_len = pci_resource_len(pdev, 0);
142 info->fix.line_length = width * 4;
143
144 info->var = mdpy_fb_var;
145 info->var.xres = width;
146 info->var.yres = height;
147 info->var.xres_virtual = width;
148 info->var.yres_virtual = height;
149
150 info->screen_size = info->fix.smem_len;
151 info->screen_base = ioremap(info->fix.smem_start,
152 info->screen_size);
153 if (!info->screen_base) {
154 pci_err(pdev, "ioremap(pcibar) failed\n");
155 ret = -EIO;
156 goto err_release_fb;
157 }
158
159 info->apertures = alloc_apertures(1);
160 if (!info->apertures) {
161 ret = -ENOMEM;
162 goto err_unmap;
163 }
164 info->apertures->ranges[0].base = info->fix.smem_start;
165 info->apertures->ranges[0].size = info->fix.smem_len;
166
167 info->fbops = &mdpy_fb_ops;
168 info->flags = FBINFO_DEFAULT;
169 info->pseudo_palette = par->palette;
170
171 ret = register_framebuffer(info);
172 if (ret < 0) {
173 pci_err(pdev, "mdpy-fb device register failed: %d\n", ret);
174 goto err_unmap;
175 }
176
177 pci_info(pdev, "fb%d registered\n", info->node);
178 return 0;
179
180err_unmap:
181 iounmap(info->screen_base);
182
183err_release_fb:
184 framebuffer_release(info);
185
186err_release_regions:
187 pci_release_regions(pdev);
188
189 return ret;
190}
191
192static void mdpy_fb_remove(struct pci_dev *pdev)
193{
194 struct fb_info *info = pci_get_drvdata(pdev);
195
196 unregister_framebuffer(info);
197 framebuffer_release(info);
198}
199
200static struct pci_device_id mdpy_fb_pci_table[] = {
201 {
202 .vendor = MDPY_PCI_VENDOR_ID,
203 .device = MDPY_PCI_DEVICE_ID,
204 .subvendor = MDPY_PCI_SUBVENDOR_ID,
205 .subdevice = MDPY_PCI_SUBDEVICE_ID,
206 }, {
207 /* end of list */
208 }
209};
210
211static struct pci_driver mdpy_fb_pci_driver = {
212 .name = "mdpy-fb",
213 .id_table = mdpy_fb_pci_table,
214 .probe = mdpy_fb_probe,
215 .remove = mdpy_fb_remove,
216};
217
218static int __init mdpy_fb_init(void)
219{
220 int ret;
221
222 ret = pci_register_driver(&mdpy_fb_pci_driver);
223 if (ret)
224 return ret;
225
226 return 0;
227}
228
229module_init(mdpy_fb_init);
230
231MODULE_DEVICE_TABLE(pci, mdpy_fb_pci_table);
232MODULE_LICENSE("GPL v2");
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
new file mode 100644
index 000000000000..96e7969c473a
--- /dev/null
+++ b/samples/vfio-mdev/mdpy.c
@@ -0,0 +1,807 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Mediated virtual PCI display host device driver
4 *
5 * See mdpy-defs.h for device specs
6 *
7 * (c) Gerd Hoffmann <kraxel@redhat.com>
8 *
9 * based on mtty driver which is:
10 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
11 * Author: Neo Jia <cjia@nvidia.com>
12 * Kirti Wankhede <kwankhede@nvidia.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/device.h>
21#include <linux/kernel.h>
22#include <linux/slab.h>
23#include <linux/vmalloc.h>
24#include <linux/cdev.h>
25#include <linux/vfio.h>
26#include <linux/iommu.h>
27#include <linux/sysfs.h>
28#include <linux/mdev.h>
29#include <linux/pci.h>
30#include <drm/drm_fourcc.h>
31#include "mdpy-defs.h"
32
33#define MDPY_NAME "mdpy"
34#define MDPY_CLASS_NAME "mdpy"
35
36#define MDPY_CONFIG_SPACE_SIZE 0xff
37#define MDPY_MEMORY_BAR_OFFSET PAGE_SIZE
38#define MDPY_DISPLAY_REGION 16
39
40#define STORE_LE16(addr, val) (*(u16 *)addr = val)
41#define STORE_LE32(addr, val) (*(u32 *)addr = val)
42
43
44MODULE_LICENSE("GPL v2");
45
46static int max_devices = 4;
47module_param_named(count, max_devices, int, 0444);
48MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
49
50
51#define MDPY_TYPE_1 "vga"
52#define MDPY_TYPE_2 "xga"
53#define MDPY_TYPE_3 "hd"
54
55static const struct mdpy_type {
56 const char *name;
57 u32 format;
58 u32 bytepp;
59 u32 width;
60 u32 height;
61} mdpy_types[] = {
62 {
63 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_1,
64 .format = DRM_FORMAT_XRGB8888,
65 .bytepp = 4,
66 .width = 640,
67 .height = 480,
68 }, {
69 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_2,
70 .format = DRM_FORMAT_XRGB8888,
71 .bytepp = 4,
72 .width = 1024,
73 .height = 768,
74 }, {
75 .name = MDPY_CLASS_NAME "-" MDPY_TYPE_3,
76 .format = DRM_FORMAT_XRGB8888,
77 .bytepp = 4,
78 .width = 1920,
79 .height = 1080,
80 },
81};
82
83static dev_t mdpy_devt;
84static struct class *mdpy_class;
85static struct cdev mdpy_cdev;
86static struct device mdpy_dev;
87static u32 mdpy_count;
88
89/* State of each mdev device */
90struct mdev_state {
91 u8 *vconfig;
92 u32 bar_mask;
93 struct mutex ops_lock;
94 struct mdev_device *mdev;
95 struct vfio_device_info dev_info;
96
97 const struct mdpy_type *type;
98 u32 memsize;
99 void *memblk;
100};
101
102static const struct mdpy_type *mdpy_find_type(struct kobject *kobj)
103{
104 int i;
105
106 for (i = 0; i < ARRAY_SIZE(mdpy_types); i++)
107 if (strcmp(mdpy_types[i].name, kobj->name) == 0)
108 return mdpy_types + i;
109 return NULL;
110}
111
112static void mdpy_create_config_space(struct mdev_state *mdev_state)
113{
114 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_VENDOR_ID],
115 MDPY_PCI_VENDOR_ID);
116 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_DEVICE_ID],
117 MDPY_PCI_DEVICE_ID);
118 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_VENDOR_ID],
119 MDPY_PCI_SUBVENDOR_ID);
120 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_ID],
121 MDPY_PCI_SUBDEVICE_ID);
122
123 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_COMMAND],
124 PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
125 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_STATUS],
126 PCI_STATUS_CAP_LIST);
127 STORE_LE16((u16 *) &mdev_state->vconfig[PCI_CLASS_DEVICE],
128 PCI_CLASS_DISPLAY_OTHER);
129 mdev_state->vconfig[PCI_CLASS_REVISION] = 0x01;
130
131 STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_0],
132 PCI_BASE_ADDRESS_SPACE_MEMORY |
133 PCI_BASE_ADDRESS_MEM_TYPE_32 |
134 PCI_BASE_ADDRESS_MEM_PREFETCH);
135 mdev_state->bar_mask = ~(mdev_state->memsize) + 1;
136
137 /* vendor specific capability for the config registers */
138 mdev_state->vconfig[PCI_CAPABILITY_LIST] = MDPY_VENDORCAP_OFFSET;
139 mdev_state->vconfig[MDPY_VENDORCAP_OFFSET + 0] = 0x09; /* vendor cap */
140 mdev_state->vconfig[MDPY_VENDORCAP_OFFSET + 1] = 0x00; /* next ptr */
141 mdev_state->vconfig[MDPY_VENDORCAP_OFFSET + 2] = MDPY_VENDORCAP_SIZE;
142 STORE_LE32((u32 *) &mdev_state->vconfig[MDPY_FORMAT_OFFSET],
143 mdev_state->type->format);
144 STORE_LE32((u32 *) &mdev_state->vconfig[MDPY_WIDTH_OFFSET],
145 mdev_state->type->width);
146 STORE_LE32((u32 *) &mdev_state->vconfig[MDPY_HEIGHT_OFFSET],
147 mdev_state->type->height);
148}
149
150static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
151 char *buf, u32 count)
152{
153 struct device *dev = mdev_dev(mdev_state->mdev);
154 u32 cfg_addr;
155
156 switch (offset) {
157 case PCI_BASE_ADDRESS_0:
158 cfg_addr = *(u32 *)buf;
159
160 if (cfg_addr == 0xffffffff) {
161 cfg_addr = (cfg_addr & mdev_state->bar_mask);
162 } else {
163 cfg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
164 if (cfg_addr)
165 dev_info(dev, "BAR0 @ 0x%x\n", cfg_addr);
166 }
167
168 cfg_addr |= (mdev_state->vconfig[offset] &
169 ~PCI_BASE_ADDRESS_MEM_MASK);
170 STORE_LE32(&mdev_state->vconfig[offset], cfg_addr);
171 break;
172 }
173}
174
175static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
176 loff_t pos, bool is_write)
177{
178 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
179 struct device *dev = mdev_dev(mdev);
180 int ret = 0;
181
182 mutex_lock(&mdev_state->ops_lock);
183
184 if (pos < MDPY_CONFIG_SPACE_SIZE) {
185 if (is_write)
186 handle_pci_cfg_write(mdev_state, pos, buf, count);
187 else
188 memcpy(buf, (mdev_state->vconfig + pos), count);
189
190 } else if ((pos >= MDPY_MEMORY_BAR_OFFSET) &&
191 (pos + count <=
192 MDPY_MEMORY_BAR_OFFSET + mdev_state->memsize)) {
193 pos -= MDPY_MEMORY_BAR_OFFSET;
194 if (is_write)
195 memcpy(mdev_state->memblk, buf, count);
196 else
197 memcpy(buf, mdev_state->memblk, count);
198
199 } else {
200 dev_info(dev, "%s: %s @0x%llx (unhandled)\n",
201 __func__, is_write ? "WR" : "RD", pos);
202 ret = -1;
203 goto accessfailed;
204 }
205
206 ret = count;
207
208
209accessfailed:
210 mutex_unlock(&mdev_state->ops_lock);
211
212 return ret;
213}
214
215static int mdpy_reset(struct mdev_device *mdev)
216{
217 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
218 u32 stride, i;
219
220 /* initialize with gray gradient */
221 stride = mdev_state->type->width * mdev_state->type->bytepp;
222 for (i = 0; i < mdev_state->type->height; i++)
223 memset(mdev_state->memblk + i * stride,
224 i * 255 / mdev_state->type->height,
225 stride);
226 return 0;
227}
228
229static int mdpy_create(struct kobject *kobj, struct mdev_device *mdev)
230{
231 const struct mdpy_type *type = mdpy_find_type(kobj);
232 struct device *dev = mdev_dev(mdev);
233 struct mdev_state *mdev_state;
234 u32 fbsize;
235
236 if (mdpy_count >= max_devices)
237 return -ENOMEM;
238
239 mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
240 if (mdev_state == NULL)
241 return -ENOMEM;
242
243 mdev_state->vconfig = kzalloc(MDPY_CONFIG_SPACE_SIZE, GFP_KERNEL);
244 if (mdev_state->vconfig == NULL) {
245 kfree(mdev_state);
246 return -ENOMEM;
247 }
248
249 if (!type)
250 type = &mdpy_types[0];
251 fbsize = roundup_pow_of_two(type->width * type->height * type->bytepp);
252
253 mdev_state->memblk = vmalloc_user(fbsize);
254 if (!mdev_state->memblk) {
255 kfree(mdev_state->vconfig);
256 kfree(mdev_state);
257 return -ENOMEM;
258 }
259 dev_info(dev, "%s: %s (%dx%d)\n",
260 __func__, kobj->name, type->width, type->height);
261
262 mutex_init(&mdev_state->ops_lock);
263 mdev_state->mdev = mdev;
264 mdev_set_drvdata(mdev, mdev_state);
265
266 mdev_state->type = type;
267 mdev_state->memsize = fbsize;
268 mdpy_create_config_space(mdev_state);
269 mdpy_reset(mdev);
270
271 mdpy_count++;
272 return 0;
273}
274
275static int mdpy_remove(struct mdev_device *mdev)
276{
277 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
278 struct device *dev = mdev_dev(mdev);
279
280 dev_info(dev, "%s\n", __func__);
281
282 mdev_set_drvdata(mdev, NULL);
283 vfree(mdev_state->memblk);
284 kfree(mdev_state->vconfig);
285 kfree(mdev_state);
286
287 mdpy_count--;
288 return 0;
289}
290
291static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
292 size_t count, loff_t *ppos)
293{
294 unsigned int done = 0;
295 int ret;
296
297 while (count) {
298 size_t filled;
299
300 if (count >= 4 && !(*ppos % 4)) {
301 u32 val;
302
303 ret = mdev_access(mdev, (char *)&val, sizeof(val),
304 *ppos, false);
305 if (ret <= 0)
306 goto read_err;
307
308 if (copy_to_user(buf, &val, sizeof(val)))
309 goto read_err;
310
311 filled = 4;
312 } else if (count >= 2 && !(*ppos % 2)) {
313 u16 val;
314
315 ret = mdev_access(mdev, (char *)&val, sizeof(val),
316 *ppos, false);
317 if (ret <= 0)
318 goto read_err;
319
320 if (copy_to_user(buf, &val, sizeof(val)))
321 goto read_err;
322
323 filled = 2;
324 } else {
325 u8 val;
326
327 ret = mdev_access(mdev, (char *)&val, sizeof(val),
328 *ppos, false);
329 if (ret <= 0)
330 goto read_err;
331
332 if (copy_to_user(buf, &val, sizeof(val)))
333 goto read_err;
334
335 filled = 1;
336 }
337
338 count -= filled;
339 done += filled;
340 *ppos += filled;
341 buf += filled;
342 }
343
344 return done;
345
346read_err:
347 return -EFAULT;
348}
349
350static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
351 size_t count, loff_t *ppos)
352{
353 unsigned int done = 0;
354 int ret;
355
356 while (count) {
357 size_t filled;
358
359 if (count >= 4 && !(*ppos % 4)) {
360 u32 val;
361
362 if (copy_from_user(&val, buf, sizeof(val)))
363 goto write_err;
364
365 ret = mdev_access(mdev, (char *)&val, sizeof(val),
366 *ppos, true);
367 if (ret <= 0)
368 goto write_err;
369
370 filled = 4;
371 } else if (count >= 2 && !(*ppos % 2)) {
372 u16 val;
373
374 if (copy_from_user(&val, buf, sizeof(val)))
375 goto write_err;
376
377 ret = mdev_access(mdev, (char *)&val, sizeof(val),
378 *ppos, true);
379 if (ret <= 0)
380 goto write_err;
381
382 filled = 2;
383 } else {
384 u8 val;
385
386 if (copy_from_user(&val, buf, sizeof(val)))
387 goto write_err;
388
389 ret = mdev_access(mdev, (char *)&val, sizeof(val),
390 *ppos, true);
391 if (ret <= 0)
392 goto write_err;
393
394 filled = 1;
395 }
396 count -= filled;
397 done += filled;
398 *ppos += filled;
399 buf += filled;
400 }
401
402 return done;
403write_err:
404 return -EFAULT;
405}
406
407static int mdpy_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
408{
409 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
410
411 if (vma->vm_pgoff != MDPY_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
412 return -EINVAL;
413 if (vma->vm_end < vma->vm_start)
414 return -EINVAL;
415 if (vma->vm_end - vma->vm_start > mdev_state->memsize)
416 return -EINVAL;
417 if ((vma->vm_flags & VM_SHARED) == 0)
418 return -EINVAL;
419
420 return remap_vmalloc_range_partial(vma, vma->vm_start,
421 mdev_state->memblk,
422 vma->vm_end - vma->vm_start);
423}
424
425static int mdpy_get_region_info(struct mdev_device *mdev,
426 struct vfio_region_info *region_info,
427 u16 *cap_type_id, void **cap_type)
428{
429 struct mdev_state *mdev_state;
430
431 mdev_state = mdev_get_drvdata(mdev);
432 if (!mdev_state)
433 return -EINVAL;
434
435 if (region_info->index >= VFIO_PCI_NUM_REGIONS &&
436 region_info->index != MDPY_DISPLAY_REGION)
437 return -EINVAL;
438
439 switch (region_info->index) {
440 case VFIO_PCI_CONFIG_REGION_INDEX:
441 region_info->offset = 0;
442 region_info->size = MDPY_CONFIG_SPACE_SIZE;
443 region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
444 VFIO_REGION_INFO_FLAG_WRITE);
445 break;
446 case VFIO_PCI_BAR0_REGION_INDEX:
447 case MDPY_DISPLAY_REGION:
448 region_info->offset = MDPY_MEMORY_BAR_OFFSET;
449 region_info->size = mdev_state->memsize;
450 region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
451 VFIO_REGION_INFO_FLAG_WRITE |
452 VFIO_REGION_INFO_FLAG_MMAP);
453 break;
454 default:
455 region_info->size = 0;
456 region_info->offset = 0;
457 region_info->flags = 0;
458 }
459
460 return 0;
461}
462
463static int mdpy_get_irq_info(struct mdev_device *mdev,
464 struct vfio_irq_info *irq_info)
465{
466 irq_info->count = 0;
467 return 0;
468}
469
470static int mdpy_get_device_info(struct mdev_device *mdev,
471 struct vfio_device_info *dev_info)
472{
473 dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
474 dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
475 dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
476 return 0;
477}
478
479static int mdpy_query_gfx_plane(struct mdev_device *mdev,
480 struct vfio_device_gfx_plane_info *plane)
481{
482 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
483
484 if (plane->flags & VFIO_GFX_PLANE_TYPE_PROBE) {
485 if (plane->flags == (VFIO_GFX_PLANE_TYPE_PROBE |
486 VFIO_GFX_PLANE_TYPE_REGION))
487 return 0;
488 return -EINVAL;
489 }
490
491 if (plane->flags != VFIO_GFX_PLANE_TYPE_REGION)
492 return -EINVAL;
493
494 plane->drm_format = mdev_state->type->format;
495 plane->width = mdev_state->type->width;
496 plane->height = mdev_state->type->height;
497 plane->stride = (mdev_state->type->width *
498 mdev_state->type->bytepp);
499 plane->size = mdev_state->memsize;
500 plane->region_index = MDPY_DISPLAY_REGION;
501
502 /* unused */
503 plane->drm_format_mod = 0;
504 plane->x_pos = 0;
505 plane->y_pos = 0;
506 plane->x_hot = 0;
507 plane->y_hot = 0;
508
509 return 0;
510}
511
512static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
513 unsigned long arg)
514{
515 int ret = 0;
516 unsigned long minsz;
517 struct mdev_state *mdev_state;
518
519 mdev_state = mdev_get_drvdata(mdev);
520
521 switch (cmd) {
522 case VFIO_DEVICE_GET_INFO:
523 {
524 struct vfio_device_info info;
525
526 minsz = offsetofend(struct vfio_device_info, num_irqs);
527
528 if (copy_from_user(&info, (void __user *)arg, minsz))
529 return -EFAULT;
530
531 if (info.argsz < minsz)
532 return -EINVAL;
533
534 ret = mdpy_get_device_info(mdev, &info);
535 if (ret)
536 return ret;
537
538 memcpy(&mdev_state->dev_info, &info, sizeof(info));
539
540 if (copy_to_user((void __user *)arg, &info, minsz))
541 return -EFAULT;
542
543 return 0;
544 }
545 case VFIO_DEVICE_GET_REGION_INFO:
546 {
547 struct vfio_region_info info;
548 u16 cap_type_id = 0;
549 void *cap_type = NULL;
550
551 minsz = offsetofend(struct vfio_region_info, offset);
552
553 if (copy_from_user(&info, (void __user *)arg, minsz))
554 return -EFAULT;
555
556 if (info.argsz < minsz)
557 return -EINVAL;
558
559 ret = mdpy_get_region_info(mdev, &info, &cap_type_id,
560 &cap_type);
561 if (ret)
562 return ret;
563
564 if (copy_to_user((void __user *)arg, &info, minsz))
565 return -EFAULT;
566
567 return 0;
568 }
569
570 case VFIO_DEVICE_GET_IRQ_INFO:
571 {
572 struct vfio_irq_info info;
573
574 minsz = offsetofend(struct vfio_irq_info, count);
575
576 if (copy_from_user(&info, (void __user *)arg, minsz))
577 return -EFAULT;
578
579 if ((info.argsz < minsz) ||
580 (info.index >= mdev_state->dev_info.num_irqs))
581 return -EINVAL;
582
583 ret = mdpy_get_irq_info(mdev, &info);
584 if (ret)
585 return ret;
586
587 if (copy_to_user((void __user *)arg, &info, minsz))
588 return -EFAULT;
589
590 return 0;
591 }
592
593 case VFIO_DEVICE_QUERY_GFX_PLANE:
594 {
595 struct vfio_device_gfx_plane_info plane;
596
597 minsz = offsetofend(struct vfio_device_gfx_plane_info,
598 region_index);
599
600 if (copy_from_user(&plane, (void __user *)arg, minsz))
601 return -EFAULT;
602
603 if (plane.argsz < minsz)
604 return -EINVAL;
605
606 ret = mdpy_query_gfx_plane(mdev, &plane);
607 if (ret)
608 return ret;
609
610 if (copy_to_user((void __user *)arg, &plane, minsz))
611 return -EFAULT;
612
613 return 0;
614 }
615
616 case VFIO_DEVICE_SET_IRQS:
617 return -EINVAL;
618
619 case VFIO_DEVICE_RESET:
620 return mdpy_reset(mdev);
621 }
622 return -ENOTTY;
623}
624
625static int mdpy_open(struct mdev_device *mdev)
626{
627 if (!try_module_get(THIS_MODULE))
628 return -ENODEV;
629
630 return 0;
631}
632
633static void mdpy_close(struct mdev_device *mdev)
634{
635 module_put(THIS_MODULE);
636}
637
638static ssize_t
639resolution_show(struct device *dev, struct device_attribute *attr,
640 char *buf)
641{
642 struct mdev_device *mdev = mdev_from_dev(dev);
643 struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
644
645 return sprintf(buf, "%dx%d\n",
646 mdev_state->type->width,
647 mdev_state->type->height);
648}
649static DEVICE_ATTR_RO(resolution);
650
651static struct attribute *mdev_dev_attrs[] = {
652 &dev_attr_resolution.attr,
653 NULL,
654};
655
656static const struct attribute_group mdev_dev_group = {
657 .name = "vendor",
658 .attrs = mdev_dev_attrs,
659};
660
661const struct attribute_group *mdev_dev_groups[] = {
662 &mdev_dev_group,
663 NULL,
664};
665
666static ssize_t
667name_show(struct kobject *kobj, struct device *dev, char *buf)
668{
669 return sprintf(buf, "%s\n", kobj->name);
670}
671MDEV_TYPE_ATTR_RO(name);
672
673static ssize_t
674description_show(struct kobject *kobj, struct device *dev, char *buf)
675{
676 const struct mdpy_type *type = mdpy_find_type(kobj);
677
678 return sprintf(buf, "virtual display, %dx%d framebuffer\n",
679 type ? type->width : 0,
680 type ? type->height : 0);
681}
682MDEV_TYPE_ATTR_RO(description);
683
684static ssize_t
685available_instances_show(struct kobject *kobj, struct device *dev, char *buf)
686{
687 return sprintf(buf, "%d\n", max_devices - mdpy_count);
688}
689MDEV_TYPE_ATTR_RO(available_instances);
690
691static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
692 char *buf)
693{
694 return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
695}
696MDEV_TYPE_ATTR_RO(device_api);
697
698static struct attribute *mdev_types_attrs[] = {
699 &mdev_type_attr_name.attr,
700 &mdev_type_attr_description.attr,
701 &mdev_type_attr_device_api.attr,
702 &mdev_type_attr_available_instances.attr,
703 NULL,
704};
705
706static struct attribute_group mdev_type_group1 = {
707 .name = MDPY_TYPE_1,
708 .attrs = mdev_types_attrs,
709};
710
711static struct attribute_group mdev_type_group2 = {
712 .name = MDPY_TYPE_2,
713 .attrs = mdev_types_attrs,
714};
715
716static struct attribute_group mdev_type_group3 = {
717 .name = MDPY_TYPE_3,
718 .attrs = mdev_types_attrs,
719};
720
721static struct attribute_group *mdev_type_groups[] = {
722 &mdev_type_group1,
723 &mdev_type_group2,
724 &mdev_type_group3,
725 NULL,
726};
727
728static const struct mdev_parent_ops mdev_fops = {
729 .owner = THIS_MODULE,
730 .mdev_attr_groups = mdev_dev_groups,
731 .supported_type_groups = mdev_type_groups,
732 .create = mdpy_create,
733 .remove = mdpy_remove,
734 .open = mdpy_open,
735 .release = mdpy_close,
736 .read = mdpy_read,
737 .write = mdpy_write,
738 .ioctl = mdpy_ioctl,
739 .mmap = mdpy_mmap,
740};
741
742static const struct file_operations vd_fops = {
743 .owner = THIS_MODULE,
744};
745
746static void mdpy_device_release(struct device *dev)
747{
748 /* nothing */
749}
750
751static int __init mdpy_dev_init(void)
752{
753 int ret = 0;
754
755 ret = alloc_chrdev_region(&mdpy_devt, 0, MINORMASK, MDPY_NAME);
756 if (ret < 0) {
757 pr_err("Error: failed to register mdpy_dev, err: %d\n", ret);
758 return ret;
759 }
760 cdev_init(&mdpy_cdev, &vd_fops);
761 cdev_add(&mdpy_cdev, mdpy_devt, MINORMASK);
762 pr_info("%s: major %d\n", __func__, MAJOR(mdpy_devt));
763
764 mdpy_class = class_create(THIS_MODULE, MDPY_CLASS_NAME);
765 if (IS_ERR(mdpy_class)) {
766 pr_err("Error: failed to register mdpy_dev class\n");
767 ret = PTR_ERR(mdpy_class);
768 goto failed1;
769 }
770 mdpy_dev.class = mdpy_class;
771 mdpy_dev.release = mdpy_device_release;
772 dev_set_name(&mdpy_dev, "%s", MDPY_NAME);
773
774 ret = device_register(&mdpy_dev);
775 if (ret)
776 goto failed2;
777
778 ret = mdev_register_device(&mdpy_dev, &mdev_fops);
779 if (ret)
780 goto failed3;
781
782 return 0;
783
784failed3:
785 device_unregister(&mdpy_dev);
786failed2:
787 class_destroy(mdpy_class);
788failed1:
789 cdev_del(&mdpy_cdev);
790 unregister_chrdev_region(mdpy_devt, MINORMASK);
791 return ret;
792}
793
794static void __exit mdpy_dev_exit(void)
795{
796 mdpy_dev.bus = NULL;
797 mdev_unregister_device(&mdpy_dev);
798
799 device_unregister(&mdpy_dev);
800 cdev_del(&mdpy_cdev);
801 unregister_chrdev_region(mdpy_devt, MINORMASK);
802 class_destroy(mdpy_class);
803 mdpy_class = NULL;
804}
805
806module_init(mdpy_dev_init)
807module_exit(mdpy_dev_exit)