Pull VFIO updates from Alex Williamson: - Cleanup vfio iommu_group creation (Christoph Hellwig) - Add individual device reset for vfio/fsl-mc (Diana Craciun) - IGD OpRegion 2.0+ support (Colin Xu) - Use modern cdev lifecycle for vfio_group (Jason Gunthorpe) - Use new mdev API in vfio_ccw (Jason Gunthorpe) * tag 'vfio-v5.16-rc1' of git://github.com/awilliam/linux-vfio: (27 commits) vfio/ccw: Convert to use vfio_register_emulated_iommu_dev() vfio/ccw: Pass vfio_ccw_private not mdev_device to various functions vfio/ccw: Use functions for alloc/free of the vfio_ccw_private vfio/ccw: Remove unneeded GFP_DMA vfio: Use cdev_device_add() instead of device_create() vfio: Use a refcount_t instead of a kref in the vfio_group vfio: Don't leak a group reference if the group already exists vfio: Do not open code the group list search in vfio_create_group() vfio: Delete vfio_get/put_group from vfio_iommu_group_notifier() vfio/pci: Add OpRegion 2.0+ Extended VBT support. vfio/iommu_type1: remove IS_IOMMU_CAP_DOMAIN_IN_CONTAINER vfio/iommu_type1: remove the "external" domain vfio/iommu_type1: initialize pgsize_bitmap in ->open vfio/spapr_tce: reject mediated devices vfio: clean up the check for mediated device in vfio_iommu_type1 vfio: remove the unused mdev iommu hook vfio: move the vfio_iommu_driver_ops interface out of <linux/vfio.h> vfio: remove unused method from vfio_iommu_driver_ops vfio: simplify iommu group allocation for mediated devices vfio: remove the iommudata hack for noiommu groups ...
Unified · Split
| @@ -15,7 +15,8 @@ mc-bus-driver-objs := fsl-mc-bus.o \ · 14 unmodified lines | |||
| 15 | dprc-driver.o \ | 15 | dprc-driver.o \ |
| 16 | fsl-mc-allocator.o \ | 16 | fsl-mc-allocator.o \ |
| 17 | fsl-mc-msi.o \ | 17 | fsl-mc-msi.o \ |
| 18 | dpmcp.o | 18 | dpmcp.o \ |
| 19 | obj-api.o | ||
| 19 | 20 | ||
| 20 | # MC userspace support | 21 | # MC userspace support |
| 21 | obj-$(CONFIG_FSL_MC_UAPI_SUPPORT) += fsl-mc-uapi.o | 22 | obj-$(CONFIG_FSL_MC_UAPI_SUPPORT) += fsl-mc-uapi.o |
| @@ -48,7 +48,6 @@ struct dpmng_rsp_get_version { · 47 unmodified lines | |||
| 48 | 48 | ||
| 49 | /* DPMCP command IDs */ | 49 | /* DPMCP command IDs */ |
| 50 | #define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) | 50 | #define DPMCP_CMDID_CLOSE DPMCP_CMD(0x800) |
| 51 | #define DPMCP_CMDID_OPEN DPMCP_CMD(0x80b) | ||
| 52 | #define DPMCP_CMDID_RESET DPMCP_CMD(0x005) | 51 | #define DPMCP_CMDID_RESET DPMCP_CMD(0x005) |
| 53 | 52 | ||
| 54 | struct dpmcp_cmd_open { | 53 | struct dpmcp_cmd_open { |
| @@ -91,7 +90,6 @@ int dpmcp_reset(struct fsl_mc_io *mc_io, · 36 unmodified lines | |||
| 91 | 90 | ||
| 92 | /* DPRC command IDs */ | 91 | /* DPRC command IDs */ |
| 93 | #define DPRC_CMDID_CLOSE DPRC_CMD(0x800) | 92 | #define DPRC_CMDID_CLOSE DPRC_CMD(0x800) |
| 94 | #define DPRC_CMDID_OPEN DPRC_CMD(0x805) | ||
| 95 | #define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) | 93 | #define DPRC_CMDID_GET_API_VERSION DPRC_CMD(0xa05) |
| 96 | 94 | ||
| 97 | #define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) | 95 | #define DPRC_CMDID_GET_ATTR DPRC_CMD(0x004) |
| @@ -453,7 +451,6 @@ int dprc_get_connection(struct fsl_mc_io *mc_io, · 355 unmodified lines | |||
| 453 | 451 | ||
| 454 | /* Command IDs */ | 452 | /* Command IDs */ |
| 455 | #define DPBP_CMDID_CLOSE DPBP_CMD(0x800) | 453 | #define DPBP_CMDID_CLOSE DPBP_CMD(0x800) |
| 456 | #define DPBP_CMDID_OPEN DPBP_CMD(0x804) | ||
| 457 | 454 | ||
| 458 | #define DPBP_CMDID_ENABLE DPBP_CMD(0x002) | 455 | #define DPBP_CMDID_ENABLE DPBP_CMD(0x002) |
| 459 | #define DPBP_CMDID_DISABLE DPBP_CMD(0x003) | 456 | #define DPBP_CMDID_DISABLE DPBP_CMD(0x003) |
| @@ -492,7 +489,6 @@ struct dpbp_rsp_get_attributes { · 32 unmodified lines | |||
| 492 | 489 | ||
| 493 | /* Command IDs */ | 490 | /* Command IDs */ |
| 494 | #define DPCON_CMDID_CLOSE DPCON_CMD(0x800) | 491 | #define DPCON_CMDID_CLOSE DPCON_CMD(0x800) |
| 495 | #define DPCON_CMDID_OPEN DPCON_CMD(0x808) | ||
| 496 | 492 | ||
| 497 | #define DPCON_CMDID_ENABLE DPCON_CMD(0x002) | 493 | #define DPCON_CMDID_ENABLE DPCON_CMD(0x002) |
| 498 | #define DPCON_CMDID_DISABLE DPCON_CMD(0x003) | 494 | #define DPCON_CMDID_DISABLE DPCON_CMD(0x003) |
| @@ -524,6 +520,41 @@ struct dpcon_cmd_set_notification { · 25 unmodified lines | |||
| 524 | __le64 user_ctx; | 520 | __le64 user_ctx; |
| 525 | }; | 521 | }; |
| 526 | 522 | ||
| 523 | /* | ||
| 524 | * Generic FSL MC API | ||
| 525 | */ | ||
| 526 | |||
| 527 | /* generic command versioning */ | ||
| 528 | #define OBJ_CMD_BASE_VERSION 1 | ||
| 529 | #define OBJ_CMD_ID_OFFSET 4 | ||
| 530 | |||
| 531 | #define OBJ_CMD(id) (((id) << OBJ_CMD_ID_OFFSET) | OBJ_CMD_BASE_VERSION) | ||
| 532 | |||
| 533 | /* open command codes */ | ||
| 534 | #define DPRTC_CMDID_OPEN OBJ_CMD(0x810) | ||
| 535 | #define DPNI_CMDID_OPEN OBJ_CMD(0x801) | ||
| 536 | #define DPSW_CMDID_OPEN OBJ_CMD(0x802) | ||
| 537 | #define DPIO_CMDID_OPEN OBJ_CMD(0x803) | ||
| 538 | #define DPBP_CMDID_OPEN OBJ_CMD(0x804) | ||
| 539 | #define DPRC_CMDID_OPEN OBJ_CMD(0x805) | ||
| 540 | #define DPDMUX_CMDID_OPEN OBJ_CMD(0x806) | ||
| 541 | #define DPCI_CMDID_OPEN OBJ_CMD(0x807) | ||
| 542 | #define DPCON_CMDID_OPEN OBJ_CMD(0x808) | ||
| 543 | #define DPSECI_CMDID_OPEN OBJ_CMD(0x809) | ||
| 544 | #define DPAIOP_CMDID_OPEN OBJ_CMD(0x80a) | ||
| 545 | #define DPMCP_CMDID_OPEN OBJ_CMD(0x80b) | ||
| 546 | #define DPMAC_CMDID_OPEN OBJ_CMD(0x80c) | ||
| 547 | #define DPDCEI_CMDID_OPEN OBJ_CMD(0x80d) | ||
| 548 | #define DPDMAI_CMDID_OPEN OBJ_CMD(0x80e) | ||
| 549 | #define DPDBG_CMDID_OPEN OBJ_CMD(0x80f) | ||
| 550 | |||
| 551 | /* Generic object command IDs */ | ||
| 552 | #define OBJ_CMDID_CLOSE OBJ_CMD(0x800) | ||
| 553 | #define OBJ_CMDID_RESET OBJ_CMD(0x005) | ||
| 554 | |||
| 555 | struct fsl_mc_obj_cmd_open { | ||
| 556 | __le32 obj_id; | ||
| 557 | }; | ||
| 527 | 558 | ||
| 528 | /** | 559 | /** |
| 529 | * struct fsl_mc_resource_pool - Pool of MC resources of a given | 560 | * struct fsl_mc_resource_pool - Pool of MC resources of a given |
| @@ -0,0 +1,103 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) | ||
| 2 | /* | ||
| 3 | * Copyright 2021 NXP | ||
| 4 | * | ||
| 5 | */ | ||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/fsl/mc.h> | ||
| 8 | |||
| 9 | #include "fsl-mc-private.h" | ||
| 10 | |||
| 11 | static int fsl_mc_get_open_cmd_id(const char *type) | ||
| 12 | { | ||
| 13 | static const struct { | ||
| 14 | int cmd_id; | ||
| 15 | const char *type; | ||
| 16 | } dev_ids[] = { | ||
| 17 | { DPRTC_CMDID_OPEN, "dprtc" }, | ||
| 18 | { DPRC_CMDID_OPEN, "dprc" }, | ||
| 19 | { DPNI_CMDID_OPEN, "dpni" }, | ||
| 20 | { DPIO_CMDID_OPEN, "dpio" }, | ||
| 21 | { DPSW_CMDID_OPEN, "dpsw" }, | ||
| 22 | { DPBP_CMDID_OPEN, "dpbp" }, | ||
| 23 | { DPCON_CMDID_OPEN, "dpcon" }, | ||
| 24 | { DPMCP_CMDID_OPEN, "dpmcp" }, | ||
| 25 | { DPMAC_CMDID_OPEN, "dpmac" }, | ||
| 26 | { DPSECI_CMDID_OPEN, "dpseci" }, | ||
| 27 | { DPDMUX_CMDID_OPEN, "dpdmux" }, | ||
| 28 | { DPDCEI_CMDID_OPEN, "dpdcei" }, | ||
| 29 | { DPAIOP_CMDID_OPEN, "dpaiop" }, | ||
| 30 | { DPCI_CMDID_OPEN, "dpci" }, | ||
| 31 | { DPDMAI_CMDID_OPEN, "dpdmai" }, | ||
| 32 | { DPDBG_CMDID_OPEN, "dpdbg" }, | ||
| 33 | { 0, NULL } | ||
| 34 | }; | ||
| 35 | int i; | ||
| 36 | |||
| 37 | for (i = 0; dev_ids[i].type; i++) | ||
| 38 | if (!strcmp(dev_ids[i].type, type)) | ||
| 39 | return dev_ids[i].cmd_id; | ||
| 40 | |||
| 41 | return -1; | ||
| 42 | } | ||
| 43 | |||
| 44 | int fsl_mc_obj_open(struct fsl_mc_io *mc_io, | ||
| 45 | u32 cmd_flags, | ||
| 46 | int obj_id, | ||
| 47 | char *obj_type, | ||
| 48 | u16 *token) | ||
| 49 | { | ||
| 50 | struct fsl_mc_command cmd = { 0 }; | ||
| 51 | struct fsl_mc_obj_cmd_open *cmd_params; | ||
| 52 | int err = 0; | ||
| 53 | int cmd_id = fsl_mc_get_open_cmd_id(obj_type); | ||
| 54 | |||
| 55 | if (cmd_id == -1) | ||
| 56 | return -ENODEV; | ||
| 57 | |||
| 58 | /* prepare command */ | ||
| 59 | cmd.header = mc_encode_cmd_header(cmd_id, cmd_flags, 0); | ||
| 60 | cmd_params = (struct fsl_mc_obj_cmd_open *)cmd.params; | ||
| 61 | cmd_params->obj_id = cpu_to_le32(obj_id); | ||
| 62 | |||
| 63 | /* send command to mc*/ | ||
| 64 | err = mc_send_command(mc_io, &cmd); | ||
| 65 | if (err) | ||
| 66 | return err; | ||
| 67 | |||
| 68 | /* retrieve response parameters */ | ||
| 69 | *token = mc_cmd_hdr_read_token(&cmd); | ||
| 70 | |||
| 71 | return err; | ||
| 72 | } | ||
| 73 | EXPORT_SYMBOL_GPL(fsl_mc_obj_open); | ||
| 74 | |||
| 75 | int fsl_mc_obj_close(struct fsl_mc_io *mc_io, | ||
| 76 | u32 cmd_flags, | ||
| 77 | u16 token) | ||
| 78 | { | ||
| 79 | struct fsl_mc_command cmd = { 0 }; | ||
| 80 | |||
| 81 | /* prepare command */ | ||
| 82 | cmd.header = mc_encode_cmd_header(OBJ_CMDID_CLOSE, cmd_flags, | ||
| 83 | token); | ||
| 84 | |||
| 85 | /* send command to mc*/ | ||
| 86 | return mc_send_command(mc_io, &cmd); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(fsl_mc_obj_close); | ||
| 89 | |||
| 90 | int fsl_mc_obj_reset(struct fsl_mc_io *mc_io, | ||
| 91 | u32 cmd_flags, | ||
| 92 | u16 token) | ||
| 93 | { | ||
| 94 | struct fsl_mc_command cmd = { 0 }; | ||
| 95 | |||
| 96 | /* prepare command */ | ||
| 97 | cmd.header = mc_encode_cmd_header(OBJ_CMDID_RESET, cmd_flags, | ||
| 98 | token); | ||
| 99 | |||
| 100 | /* send command to mc*/ | ||
| 101 | return mc_send_command(mc_io, &cmd); | ||
| 102 | } | ||
| 103 | EXPORT_SYMBOL_GPL(fsl_mc_obj_reset); | ||
| @@ -137,77 +137,107 @@ static void vfio_ccw_sch_irq(struct subchannel *sch) · 136 unmodified lines | |||
| 137 | vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); | 137 | vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static void vfio_ccw_free_regions(struct vfio_ccw_private *private) | 140 | static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) |
| 141 | { | 141 | { |
| 142 | if (private->crw_region) | ||
| 143 | kmem_cache_free(vfio_ccw_crw_region, private->crw_region); | ||
| 144 | if (private->schib_region) | ||
| 145 | kmem_cache_free(vfio_ccw_schib_region, private->schib_region); | ||
| 146 | if (private->cmd_region) | ||
| 147 | kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); | ||
| 148 | if (private->io_region) | ||
| 149 | kmem_cache_free(vfio_ccw_io_region, private->io_region); | ||
| 150 | } | ||
| 151 | |||
| 152 | static int vfio_ccw_sch_probe(struct subchannel *sch) | ||
| 153 | { | ||
| 154 | struct pmcw *pmcw = &sch->schib.pmcw; | ||
| 155 | struct vfio_ccw_private *private; | 142 | struct vfio_ccw_private *private; |
| 156 | int ret = -ENOMEM; | ||
| 157 | 143 | ||
| 158 | if (pmcw->qf) { | 144 | private = kzalloc(sizeof(*private), GFP_KERNEL); |
| 159 | dev_warn(&sch->dev, "vfio: ccw: does not support QDIO: %s\n", | ||
| 160 | dev_name(&sch->dev)); | ||
| 161 | return -ENODEV; | ||
| 162 | } | ||
| 163 | |||
| 164 | private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA); | ||
| 165 | if (!private) | 145 | if (!private) |
| 166 | return -ENOMEM; | 146 | return ERR_PTR(-ENOMEM); |
| 147 | |||
| 148 | private->sch = sch; | ||
| 149 | mutex_init(&private->io_mutex); | ||
| 150 | private->state = VFIO_CCW_STATE_NOT_OPER; | ||
| 151 | INIT_LIST_HEAD(&private->crw); | ||
| 152 | INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); | ||
| 153 | INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); | ||
| 154 | atomic_set(&private->avail, 1); | ||
| 167 | 155 | ||
| 168 | private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1), | 156 | private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1), |
| 169 | GFP_KERNEL); | 157 | GFP_KERNEL); |
| 170 | if (!private->cp.guest_cp) | 158 | if (!private->cp.guest_cp) |
| 171 | goto out_free; | 159 | goto out_free_private; |
| 172 | 160 | ||
| 173 | private->io_region = kmem_cache_zalloc(vfio_ccw_io_region, | 161 | private->io_region = kmem_cache_zalloc(vfio_ccw_io_region, |
| 174 | GFP_KERNEL | GFP_DMA); | 162 | GFP_KERNEL | GFP_DMA); |
| 175 | if (!private->io_region) | 163 | if (!private->io_region) |
| 176 | goto out_free; | 164 | goto out_free_cp; |
| 177 | 165 | ||
| 178 | private->cmd_region = kmem_cache_zalloc(vfio_ccw_cmd_region, | 166 | private->cmd_region = kmem_cache_zalloc(vfio_ccw_cmd_region, |
| 179 | GFP_KERNEL | GFP_DMA); | 167 | GFP_KERNEL | GFP_DMA); |
| 180 | if (!private->cmd_region) | 168 | if (!private->cmd_region) |
| 181 | goto out_free; | 169 | goto out_free_io; |
| 182 | 170 | ||
| 183 | private->schib_region = kmem_cache_zalloc(vfio_ccw_schib_region, | 171 | private->schib_region = kmem_cache_zalloc(vfio_ccw_schib_region, |
| 184 | GFP_KERNEL | GFP_DMA); | 172 | GFP_KERNEL | GFP_DMA); |
| 185 | 173 | ||
| 186 | if (!private->schib_region) | 174 | if (!private->schib_region) |
| 187 | goto out_free; | 175 | goto out_free_cmd; |
| 188 | 176 | ||
| 189 | private->crw_region = kmem_cache_zalloc(vfio_ccw_crw_region, | 177 | private->crw_region = kmem_cache_zalloc(vfio_ccw_crw_region, |
| 190 | GFP_KERNEL | GFP_DMA); | 178 | GFP_KERNEL | GFP_DMA); |
| 191 | 179 | ||
| 192 | if (!private->crw_region) | 180 | if (!private->crw_region) |
| 193 | goto out_free; | 181 | goto out_free_schib; |
| 182 | return private; | ||
| 183 | |||
| 184 | out_free_schib: | ||
| 185 | kmem_cache_free(vfio_ccw_schib_region, private->schib_region); | ||
| 186 | out_free_cmd: | ||
| 187 | kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); | ||
| 188 | out_free_io: | ||
| 189 | kmem_cache_free(vfio_ccw_io_region, private->io_region); | ||
| 190 | out_free_cp: | ||
| 191 | kfree(private->cp.guest_cp); | ||
| 192 | out_free_private: | ||
| 193 | mutex_destroy(&private->io_mutex); | ||
| 194 | kfree(private); | ||
| 195 | return ERR_PTR(-ENOMEM); | ||
| 196 | } | ||
| 197 | |||
| 198 | static void vfio_ccw_free_private(struct vfio_ccw_private *private) | ||
| 199 | { | ||
| 200 | struct vfio_ccw_crw *crw, *temp; | ||
| 201 | |||
| 202 | list_for_each_entry_safe(crw, temp, &private->crw, next) { | ||
| 203 | list_del(&crw->next); | ||
| 204 | kfree(crw); | ||
| 205 | } | ||
| 206 | |||
| 207 | kmem_cache_free(vfio_ccw_crw_region, private->crw_region); | ||
| 208 | kmem_cache_free(vfio_ccw_schib_region, private->schib_region); | ||
| 209 | kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); | ||
| 210 | kmem_cache_free(vfio_ccw_io_region, private->io_region); | ||
| 211 | kfree(private->cp.guest_cp); | ||
| 212 | mutex_destroy(&private->io_mutex); | ||
| 213 | kfree(private); | ||
| 214 | } | ||
| 215 | |||
| 216 | static int vfio_ccw_sch_probe(struct subchannel *sch) | ||
| 217 | { | ||
| 218 | struct pmcw *pmcw = &sch->schib.pmcw; | ||
| 219 | struct vfio_ccw_private *private; | ||
| 220 | int ret = -ENOMEM; | ||
| 221 | |||
| 222 | if (pmcw->qf) { | ||
| 223 | dev_warn(&sch->dev, "vfio: ccw: does not support QDIO: %s\n", | ||
| 224 | dev_name(&sch->dev)); | ||
| 225 | return -ENODEV; | ||
| 226 | } | ||
| 227 | |||
| 228 | private = vfio_ccw_alloc_private(sch); | ||
| 229 | if (IS_ERR(private)) | ||
| 230 | return PTR_ERR(private); | ||
| 194 | 231 | ||
| 195 | private->sch = sch; | ||
| 196 | dev_set_drvdata(&sch->dev, private); | 232 | dev_set_drvdata(&sch->dev, private); |
| 197 | mutex_init(&private->io_mutex); | ||
| 198 | 233 | ||
| 199 | spin_lock_irq(sch->lock); | 234 | spin_lock_irq(sch->lock); |
| 200 | private->state = VFIO_CCW_STATE_NOT_OPER; | ||
| 201 | sch->isc = VFIO_CCW_ISC; | 235 | sch->isc = VFIO_CCW_ISC; |
| 202 | ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); | 236 | ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); |
| 203 | spin_unlock_irq(sch->lock); | 237 | spin_unlock_irq(sch->lock); |
| 204 | if (ret) | 238 | if (ret) |
| 205 | goto out_free; | 239 | goto out_free; |
| 206 | 240 | ||
| 207 | INIT_LIST_HEAD(&private->crw); | ||
| 208 | INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); | ||
| 209 | INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); | ||
| 210 | atomic_set(&private->avail, 1); | ||
| 211 | private->state = VFIO_CCW_STATE_STANDBY; | 241 | private->state = VFIO_CCW_STATE_STANDBY; |
| 212 | 242 | ||
| 213 | ret = vfio_ccw_mdev_reg(sch); | 243 | ret = vfio_ccw_mdev_reg(sch); |
| @@ -228,31 +258,20 @@ out_disable: · 14 unmodified lines | |||
| 228 | cio_disable_subchannel(sch); | 258 | cio_disable_subchannel(sch); |
| 229 | out_free: | 259 | out_free: |
| 230 | dev_set_drvdata(&sch->dev, NULL); | 260 | dev_set_drvdata(&sch->dev, NULL); |
| 231 | vfio_ccw_free_regions(private); | 261 | vfio_ccw_free_private(private); |
| 232 | kfree(private->cp.guest_cp); | ||
| 233 | kfree(private); | ||
| 234 | return ret; | 262 | return ret; |
| 235 | } | 263 | } |
| 236 | 264 | ||
| 237 | static void vfio_ccw_sch_remove(struct subchannel *sch) | 265 | static void vfio_ccw_sch_remove(struct subchannel *sch) |
| 238 | { | 266 | { |
| 239 | struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); | 267 | struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); |
| 240 | struct vfio_ccw_crw *crw, *temp; | ||
| 241 | 268 | ||
| 242 | vfio_ccw_sch_quiesce(sch); | 269 | vfio_ccw_sch_quiesce(sch); |
| 243 | |||
| 244 | list_for_each_entry_safe(crw, temp, &private->crw, next) { | ||
| 245 | list_del(&crw->next); | ||
| 246 | kfree(crw); | ||
| 247 | } | ||
| 248 | |||
| 249 | vfio_ccw_mdev_unreg(sch); | 270 | vfio_ccw_mdev_unreg(sch); |
| 250 | 271 | ||
| 251 | dev_set_drvdata(&sch->dev, NULL); | 272 | dev_set_drvdata(&sch->dev, NULL); |
| 252 | 273 | ||
| 253 | vfio_ccw_free_regions(private); | 274 | vfio_ccw_free_private(private); |
| 254 | kfree(private->cp.guest_cp); | ||
| 255 | kfree(private); | ||
| 256 | 275 | ||
| 257 | VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n", | 276 | VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n", |
| 258 | sch->schid.cssid, sch->schid.ssid, | 277 | sch->schid.cssid, sch->schid.ssid, |
| @@ -449,7 +468,7 @@ static int __init vfio_ccw_sch_init(void) · 190 unmodified lines | |||
| 449 | vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw"); | 468 | vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw"); |
| 450 | if (!vfio_ccw_work_q) { | 469 | if (!vfio_ccw_work_q) { |
| 451 | ret = -ENOMEM; | 470 | ret = -ENOMEM; |
| 452 | goto out_err; | 471 | goto out_regions; |
| 453 | } | 472 | } |
| 454 | 473 | ||
| 455 | vfio_ccw_io_region = kmem_cache_create_usercopy("vfio_ccw_io_region", | 474 | vfio_ccw_io_region = kmem_cache_create_usercopy("vfio_ccw_io_region", |
| @@ -458,7 +477,7 @@ static int __init vfio_ccw_sch_init(void) · 2 unmodified lines | |||
| 458 | sizeof(struct ccw_io_region), NULL); | 477 | sizeof(struct ccw_io_region), NULL); |
| 459 | if (!vfio_ccw_io_region) { | 478 | if (!vfio_ccw_io_region) { |
| 460 | ret = -ENOMEM; | 479 | ret = -ENOMEM; |
| 461 | goto out_err; | 480 | goto out_regions; |
| 462 | } | 481 | } |
| 463 | 482 | ||
| 464 | vfio_ccw_cmd_region = kmem_cache_create_usercopy("vfio_ccw_cmd_region", | 483 | vfio_ccw_cmd_region = kmem_cache_create_usercopy("vfio_ccw_cmd_region", |
| @@ -467,7 +486,7 @@ static int __init vfio_ccw_sch_init(void) · 2 unmodified lines | |||
| 467 | sizeof(struct ccw_cmd_region), NULL); | 486 | sizeof(struct ccw_cmd_region), NULL); |
| 468 | if (!vfio_ccw_cmd_region) { | 487 | if (!vfio_ccw_cmd_region) { |
| 469 | ret = -ENOMEM; | 488 | ret = -ENOMEM; |
| 470 | goto out_err; | 489 | goto out_regions; |
| 471 | } | 490 | } |
| 472 | 491 | ||
| 473 | vfio_ccw_schib_region = kmem_cache_create_usercopy("vfio_ccw_schib_region", | 492 | vfio_ccw_schib_region = kmem_cache_create_usercopy("vfio_ccw_schib_region", |
| @@ -477,7 +496,7 @@ static int __init vfio_ccw_sch_init(void) · 3 unmodified lines | |||
| 477 | 496 | ||
| 478 | if (!vfio_ccw_schib_region) { | 497 | if (!vfio_ccw_schib_region) { |
| 479 | ret = -ENOMEM; | 498 | ret = -ENOMEM; |
| 480 | goto out_err; | 499 | goto out_regions; |
| 481 | } | 500 | } |
| 482 | 501 | ||
| 483 | vfio_ccw_crw_region = kmem_cache_create_usercopy("vfio_ccw_crw_region", | 502 | vfio_ccw_crw_region = kmem_cache_create_usercopy("vfio_ccw_crw_region", |
| @@ -487,19 +506,25 @@ static int __init vfio_ccw_sch_init(void) · 3 unmodified lines | |||
| 487 | 506 | ||
| 488 | if (!vfio_ccw_crw_region) { | 507 | if (!vfio_ccw_crw_region) { |
| 489 | ret = -ENOMEM; | 508 | ret = -ENOMEM; |
| 490 | goto out_err; | 509 | goto out_regions; |
| 491 | } | 510 | } |
| 492 | 511 | ||
| 512 | ret = mdev_register_driver(&vfio_ccw_mdev_driver); | ||
| 513 | if (ret) | ||
| 514 | goto out_regions; | ||
| 515 | |||
| 493 | isc_register(VFIO_CCW_ISC); | 516 | isc_register(VFIO_CCW_ISC); |
| 494 | ret = css_driver_register(&vfio_ccw_sch_driver); | 517 | ret = css_driver_register(&vfio_ccw_sch_driver); |
| 495 | if (ret) { | 518 | if (ret) { |
| 496 | isc_unregister(VFIO_CCW_ISC); | 519 | isc_unregister(VFIO_CCW_ISC); |
| 497 | goto out_err; | 520 | goto out_driver; |
| 498 | } | 521 | } |
| 499 | 522 | ||
| 500 | return ret; | 523 | return ret; |
| 501 | 524 | ||
| 502 | out_err: | 525 | out_driver: |
| 526 | mdev_unregister_driver(&vfio_ccw_mdev_driver); | ||
| 527 | out_regions: | ||
| 503 | vfio_ccw_destroy_regions(); | 528 | vfio_ccw_destroy_regions(); |
| 504 | destroy_workqueue(vfio_ccw_work_q); | 529 | destroy_workqueue(vfio_ccw_work_q); |
| 505 | vfio_ccw_debug_exit(); | 530 | vfio_ccw_debug_exit(); |
| @@ -509,6 +534,7 @@ out_err: · 3 unmodified lines | |||
| 509 | static void __exit vfio_ccw_sch_exit(void) | 534 | static void __exit vfio_ccw_sch_exit(void) |
| 510 | { | 535 | { |
| 511 | css_driver_unregister(&vfio_ccw_sch_driver); | 536 | css_driver_unregister(&vfio_ccw_sch_driver); |
| 537 | mdev_unregister_driver(&vfio_ccw_mdev_driver); | ||
| 512 | isc_unregister(VFIO_CCW_ISC); | 538 | isc_unregister(VFIO_CCW_ISC); |
| 513 | vfio_ccw_destroy_regions(); | 539 | vfio_ccw_destroy_regions(); |
| 514 | destroy_workqueue(vfio_ccw_work_q); | 540 | destroy_workqueue(vfio_ccw_work_q); |
| @@ -17,13 +17,13 @@ · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | #include "vfio_ccw_private.h" | 18 | #include "vfio_ccw_private.h" |
| 19 | 19 | ||
| 20 | static int vfio_ccw_mdev_reset(struct mdev_device *mdev) | 20 | static const struct vfio_device_ops vfio_ccw_dev_ops; |
| 21 | |||
| 22 | static int vfio_ccw_mdev_reset(struct vfio_ccw_private *private) | ||
| 21 | { | 23 | { |
| 22 | struct vfio_ccw_private *private; | ||
| 23 | struct subchannel *sch; | 24 | struct subchannel *sch; |
| 24 | int ret; | 25 | int ret; |
| 25 | 26 | ||
| 26 | private = dev_get_drvdata(mdev_parent_dev(mdev)); | ||
| 27 | sch = private->sch; | 27 | sch = private->sch; |
| 28 | /* | 28 | /* |
| 29 | * TODO: | 29 | * TODO: |
| @@ -61,7 +61,7 @@ static int vfio_ccw_mdev_notifier(struct notifier_block *nb, · 31 unmodified lines | |||
| 61 | if (!cp_iova_pinned(&private->cp, unmap->iova)) | 61 | if (!cp_iova_pinned(&private->cp, unmap->iova)) |
| 62 | return NOTIFY_OK; | 62 | return NOTIFY_OK; |
| 63 | 63 | ||
| 64 | if (vfio_ccw_mdev_reset(private->mdev)) | 64 | if (vfio_ccw_mdev_reset(private)) |
| 65 | return NOTIFY_BAD; | 65 | return NOTIFY_BAD; |
| 66 | 66 | ||
| 67 | cp_free(&private->cp); | 67 | cp_free(&private->cp); |
| @@ -113,10 +113,10 @@ static struct attribute_group *mdev_type_groups[] = { · 45 unmodified lines | |||
| 113 | NULL, | 113 | NULL, |
| 114 | }; | 114 | }; |
| 115 | 115 | ||
| 116 | static int vfio_ccw_mdev_create(struct mdev_device *mdev) | 116 | static int vfio_ccw_mdev_probe(struct mdev_device *mdev) |
| 117 | { | 117 | { |
| 118 | struct vfio_ccw_private *private = | 118 | struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent); |
| 119 | dev_get_drvdata(mdev_parent_dev(mdev)); | 119 | int ret; |
| 120 | 120 | ||
| 121 | if (private->state == VFIO_CCW_STATE_NOT_OPER) | 121 | if (private->state == VFIO_CCW_STATE_NOT_OPER) |
| 122 | return -ENODEV; | 122 | return -ENODEV; |
| @@ -124,6 +124,10 @@ static int vfio_ccw_mdev_create(struct mdev_device *mdev) · 1 unmodified line | |||
| 124 | if (atomic_dec_if_positive(&private->avail) < 0) | 124 | if (atomic_dec_if_positive(&private->avail) < 0) |
| 125 | return -EPERM; | 125 | return -EPERM; |
| 126 | 126 | ||
| 127 | memset(&private->vdev, 0, sizeof(private->vdev)); | ||
| 128 | vfio_init_group_dev(&private->vdev, &mdev->dev, | ||
| 129 | &vfio_ccw_dev_ops); | ||
| 130 | |||
| 127 | private->mdev = mdev; | 131 | private->mdev = mdev; |
| 128 | private->state = VFIO_CCW_STATE_IDLE; | 132 | private->state = VFIO_CCW_STATE_IDLE; |
| 129 | 133 | ||
| @@ -132,19 +136,31 @@ static int vfio_ccw_mdev_create(struct mdev_device *mdev) · 2 unmodified lines | |||
| 132 | private->sch->schid.ssid, | 136 | private->sch->schid.ssid, |
| 133 | private->sch->schid.sch_no); | 137 | private->sch->schid.sch_no); |
| 134 | 138 | ||
| 139 | ret = vfio_register_emulated_iommu_dev(&private->vdev); | ||
| 140 | if (ret) | ||
| 141 | goto err_atomic; | ||
| 142 | dev_set_drvdata(&mdev->dev, private); | ||
| 135 | return 0; | 143 | return 0; |
| 144 | |||
| 145 | err_atomic: | ||
| 146 | vfio_uninit_group_dev(&private->vdev); | ||
| 147 | atomic_inc(&private->avail); | ||
| 148 | private->mdev = NULL; | ||
| 149 | private->state = VFIO_CCW_STATE_IDLE; | ||
| 150 | return ret; | ||
| 136 | } | 151 | } |
| 137 | 152 | ||
| 138 | static int vfio_ccw_mdev_remove(struct mdev_device *mdev) | 153 | static void vfio_ccw_mdev_remove(struct mdev_device *mdev) |
| 139 | { | 154 | { |
| 140 | struct vfio_ccw_private *private = | 155 | struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent); |
| 141 | dev_get_drvdata(mdev_parent_dev(mdev)); | ||
| 142 | 156 | ||
| 143 | VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: remove\n", | 157 | VFIO_CCW_MSG_EVENT(2, "mdev %pUl, sch %x.%x.%04x: remove\n", |
| 144 | mdev_uuid(mdev), private->sch->schid.cssid, | 158 | mdev_uuid(mdev), private->sch->schid.cssid, |
| 145 | private->sch->schid.ssid, | 159 | private->sch->schid.ssid, |
| 146 | private->sch->schid.sch_no); | 160 | private->sch->schid.sch_no); |
| 147 | 161 | ||
| 162 | vfio_unregister_group_dev(&private->vdev); | ||
| 163 | |||
| 148 | if ((private->state != VFIO_CCW_STATE_NOT_OPER) && | 164 | if ((private->state != VFIO_CCW_STATE_NOT_OPER) && |
| 149 | (private->state != VFIO_CCW_STATE_STANDBY)) { | 165 | (private->state != VFIO_CCW_STATE_STANDBY)) { |
| 150 | if (!vfio_ccw_sch_quiesce(private->sch)) | 166 | if (!vfio_ccw_sch_quiesce(private->sch)) |
| @@ -152,23 +168,22 @@ static int vfio_ccw_mdev_remove(struct mdev_device *mdev) · 1 unmodified line | |||
| 152 | /* The state will be NOT_OPER on error. */ | 168 | /* The state will be NOT_OPER on error. */ |
| 153 | } | 169 | } |
| 154 | 170 | ||
| 171 | vfio_uninit_group_dev(&private->vdev); | ||
| 155 | cp_free(&private->cp); | 172 | cp_free(&private->cp); |
| 156 | private->mdev = NULL; | 173 | private->mdev = NULL; |
| 157 | atomic_inc(&private->avail); | 174 | atomic_inc(&private->avail); |
| 158 | |||
| 159 | return 0; | ||
| 160 | } | 175 | } |
| 161 | 176 | ||
| 162 | static int vfio_ccw_mdev_open_device(struct mdev_device *mdev) | 177 | static int vfio_ccw_mdev_open_device(struct vfio_device *vdev) |
| 163 | { | 178 | { |
| 164 | struct vfio_ccw_private *private = | 179 | struct vfio_ccw_private *private = |
| 165 | dev_get_drvdata(mdev_parent_dev(mdev)); | 180 | container_of(vdev, struct vfio_ccw_private, vdev); |
| 166 | unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP; | 181 | unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP; |
| 167 | int ret; | 182 | int ret; |
| 168 | 183 | ||
| 169 | private->nb.notifier_call = vfio_ccw_mdev_notifier; | 184 | private->nb.notifier_call = vfio_ccw_mdev_notifier; |
| 170 | 185 | ||
| 171 | ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, | 186 | ret = vfio_register_notifier(vdev->dev, VFIO_IOMMU_NOTIFY, |
| 172 | &events, &private->nb); | 187 | &events, &private->nb); |
| 173 | if (ret) | 188 | if (ret) |
| 174 | return ret; | 189 | return ret; |
| @@ -189,27 +204,26 @@ static int vfio_ccw_mdev_open_device(struct mdev_device *mdev) · 14 unmodified lines | |||
| 189 | 204 | ||
| 190 | out_unregister: | 205 | out_unregister: |
| 191 | vfio_ccw_unregister_dev_regions(private); | 206 | vfio_ccw_unregister_dev_regions(private); |
| 192 | vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, | 207 | vfio_unregister_notifier(vdev->dev, VFIO_IOMMU_NOTIFY, |
| 193 | &private->nb); | 208 | &private->nb); |
| 194 | return ret; | 209 | return ret; |
| 195 | } | 210 | } |
| 196 | 211 | ||
| 197 | static void vfio_ccw_mdev_close_device(struct mdev_device *mdev) | 212 | static void vfio_ccw_mdev_close_device(struct vfio_device *vdev) |
| 198 | { | 213 | { |
| 199 | struct vfio_ccw_private *private = | 214 | struct vfio_ccw_private *private = |
| 200 | dev_get_drvdata(mdev_parent_dev(mdev)); | 215 | container_of(vdev, struct vfio_ccw_private, vdev); |
| 201 | 216 | ||
| 202 | if ((private->state != VFIO_CCW_STATE_NOT_OPER) && | 217 | if ((private->state != VFIO_CCW_STATE_NOT_OPER) && |
| 203 | (private->state != VFIO_CCW_STATE_STANDBY)) { | 218 | (private->state != VFIO_CCW_STATE_STANDBY)) { |
| 204 | if (!vfio_ccw_mdev_reset(mdev)) | 219 | if (!vfio_ccw_mdev_reset(private)) |
| 205 | private->state = VFIO_CCW_STATE_STANDBY; | 220 | private->state = VFIO_CCW_STATE_STANDBY; |
| 206 | /* The state will be NOT_OPER on error. */ | 221 | /* The state will be NOT_OPER on error. */ |
| 207 | } | 222 | } |
| 208 | 223 | ||
| 209 | cp_free(&private->cp); | 224 | cp_free(&private->cp); |
| 210 | vfio_ccw_unregister_dev_regions(private); | 225 | vfio_ccw_unregister_dev_regions(private); |
| 211 | vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, | 226 | vfio_unregister_notifier(vdev->dev, VFIO_IOMMU_NOTIFY, &private->nb); |
| 212 | &private->nb); | ||
| 213 | } | 227 | } |
| 214 | 228 | ||
| 215 | static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private, | 229 | static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private, |
| @@ -233,15 +247,14 @@ static ssize_t vfio_ccw_mdev_read_io_region(struct vfio_ccw_private *private, · 17 unmodified lines | |||
| 233 | return ret; | 247 | return ret; |
| 234 | } | 248 | } |
| 235 | 249 | ||
| 236 | static ssize_t vfio_ccw_mdev_read(struct mdev_device *mdev, | 250 | static ssize_t vfio_ccw_mdev_read(struct vfio_device *vdev, |
| 237 | char __user *buf, | 251 | char __user *buf, |
| 238 | size_t count, | 252 | size_t count, |
| 239 | loff_t *ppos) | 253 | loff_t *ppos) |
| 240 | { | 254 | { |
| 255 | struct vfio_ccw_private *private = | ||
| 256 | container_of(vdev, struct vfio_ccw_private, vdev); | ||
| 241 | unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); | 257 | unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); |
| 242 | struct vfio_ccw_private *private; | ||
| 243 | |||
| 244 | private = dev_get_drvdata(mdev_parent_dev(mdev)); | ||
| 245 | 258 | ||
| 246 | if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) | 259 | if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) |
| 247 | return -EINVAL; | 260 | return -EINVAL; |
| @@ -286,15 +299,14 @@ out_unlock: · 38 unmodified lines | |||
| 286 | return ret; | 299 | return ret; |
| 287 | } | 300 | } |
| 288 | 301 | ||
| 289 | static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, | 302 | static ssize_t vfio_ccw_mdev_write(struct vfio_device *vdev, |
| 290 | const char __user *buf, | 303 | const char __user *buf, |
| 291 | size_t count, | 304 | size_t count, |
| 292 | loff_t *ppos) | 305 | loff_t *ppos) |
| 293 | { | 306 | { |
| 307 | struct vfio_ccw_private *private = | ||
| 308 | container_of(vdev, struct vfio_ccw_private, vdev); | ||
| 294 | unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); | 309 | unsigned int index = VFIO_CCW_OFFSET_TO_INDEX(*ppos); |
| 295 | struct vfio_ccw_private *private; | ||
| 296 | |||
| 297 | private = dev_get_drvdata(mdev_parent_dev(mdev)); | ||
| 298 | 310 | ||
| 299 | if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) | 311 | if (index >= VFIO_CCW_NUM_REGIONS + private->num_regions) |
| 300 | return -EINVAL; | 312 | return -EINVAL; |
| @@ -311,12 +323,9 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, · 10 unmodified lines | |||
| 311 | return -EINVAL; | 323 | return -EINVAL; |
| 312 | } | 324 | } |
| 313 | 325 | ||
| 314 | static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info, | 326 | static int vfio_ccw_mdev_get_device_info(struct vfio_ccw_private *private, |
| 315 | struct mdev_device *mdev) | 327 | struct vfio_device_info *info) |
| 316 | { | 328 | { |
| 317 | struct vfio_ccw_private *private; | ||
| 318 | |||
| 319 | private = dev_get_drvdata(mdev_parent_dev(mdev)); | ||
| 320 | info->flags = VFIO_DEVICE_FLAGS_CCW | VFIO_DEVICE_FLAGS_RESET; | 329 | info->flags = VFIO_DEVICE_FLAGS_CCW | VFIO_DEVICE_FLAGS_RESET; |
| 321 | info->num_regions = VFIO_CCW_NUM_REGIONS + private->num_regions; | 330 | info->num_regions = VFIO_CCW_NUM_REGIONS + private->num_regions; |
| 322 | info->num_irqs = VFIO_CCW_NUM_IRQS; | 331 | info->num_irqs = VFIO_CCW_NUM_IRQS; |
| @@ -324,14 +333,12 @@ static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info, · 1 unmodified line | |||
| 324 | return 0; | 333 | return 0; |
| 325 | } | 334 | } |
| 326 | 335 | ||
| 327 | static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info, | 336 | static int vfio_ccw_mdev_get_region_info(struct vfio_ccw_private *private, |
| 328 | struct mdev_device *mdev, | 337 | struct vfio_region_info *info, |
| 329 | unsigned long arg) | 338 | unsigned long arg) |
| 330 | { | 339 | { |
| 331 | struct vfio_ccw_private *private; | ||
| 332 | int i; | 340 | int i; |
| 333 | 341 | ||
| 334 | private = dev_get_drvdata(mdev_parent_dev(mdev)); | ||
| 335 | switch (info->index) { | 342 | switch (info->index) { |
| 336 | case VFIO_CCW_CONFIG_REGION_INDEX: | 343 | case VFIO_CCW_CONFIG_REGION_INDEX: |
| 337 | info->offset = 0; | 344 | info->offset = 0; |
| @@ -406,19 +413,16 @@ static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info) · 68 unmodified lines | |||
| 406 | return 0; | 413 | return 0; |
| 407 | } | 414 | } |
| 408 | 415 | ||
| 409 | static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev, | 416 | static int vfio_ccw_mdev_set_irqs(struct vfio_ccw_private *private, |
| 410 | uint32_t flags, | 417 | uint32_t flags, |
| 411 | uint32_t index, | 418 | uint32_t index, |
| 412 | void __user *data) | 419 | void __user *data) |
| 413 | { | 420 | { |
| 414 | struct vfio_ccw_private *private; | ||
| 415 | struct eventfd_ctx **ctx; | 421 | struct eventfd_ctx **ctx; |
| 416 | 422 | ||
| 417 | if (!(flags & VFIO_IRQ_SET_ACTION_TRIGGER)) | 423 | if (!(flags & VFIO_IRQ_SET_ACTION_TRIGGER)) |
| 418 | return -EINVAL; | 424 | return -EINVAL; |
| 419 | 425 | ||
| 420 | private = dev_get_drvdata(mdev_parent_dev(mdev)); | ||
| 421 | |||
| 422 | switch (index) { | 426 | switch (index) { |
| 423 | case VFIO_CCW_IO_IRQ_INDEX: | 427 | case VFIO_CCW_IO_IRQ_INDEX: |
| 424 | ctx = &private->io_trigger; | 428 | ctx = &private->io_trigger; |
| @@ -520,10 +524,12 @@ void vfio_ccw_unregister_dev_regions(struct vfio_ccw_private *private) · 95 unmodified lines | |||
| 520 | private->region = NULL; | 524 | private->region = NULL; |
| 521 | } | 525 | } |
| 522 | 526 | ||
| 523 | static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, | 527 | static ssize_t vfio_ccw_mdev_ioctl(struct vfio_device *vdev, |
| 524 | unsigned int cmd, | 528 | unsigned int cmd, |
| 525 | unsigned long arg) | 529 | unsigned long arg) |
| 526 | { | 530 | { |
| 531 | struct vfio_ccw_private *private = | ||
| 532 | container_of(vdev, struct vfio_ccw_private, vdev); | ||
| 527 | int ret = 0; | 533 | int ret = 0; |
| 528 | unsigned long minsz; | 534 | unsigned long minsz; |
| 529 | 535 | ||
| @@ -540,7 +546,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, · 10 unmodified lines | |||
| 540 | if (info.argsz < minsz) | 546 | if (info.argsz < minsz) |
| 541 | return -EINVAL; | 547 | return -EINVAL; |
| 542 | 548 | ||
| 543 | ret = vfio_ccw_mdev_get_device_info(&info, mdev); | 549 | ret = vfio_ccw_mdev_get_device_info(private, &info); |
| 544 | if (ret) | 550 | if (ret) |
| 545 | return ret; | 551 | return ret; |
| 546 | 552 | ||
| @@ -558,7 +564,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, · 11 unmodified lines | |||
| 558 | if (info.argsz < minsz) | 564 | if (info.argsz < minsz) |
| 559 | return -EINVAL; | 565 | return -EINVAL; |
| 560 | 566 | ||
| 561 | ret = vfio_ccw_mdev_get_region_info(&info, mdev, arg); | 567 | ret = vfio_ccw_mdev_get_region_info(private, &info, arg); |
| 562 | if (ret) | 568 | if (ret) |
| 563 | return ret; | 569 | return ret; |
| 564 | 570 | ||
| @@ -603,47 +609,59 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, · 38 unmodified lines | |||
| 603 | return ret; | 609 | return ret; |
| 604 | 610 | ||
| 605 | data = (void __user *)(arg + minsz); | 611 | data = (void __user *)(arg + minsz); |
| 606 | return vfio_ccw_mdev_set_irqs(mdev, hdr.flags, hdr.index, data); | 612 | return vfio_ccw_mdev_set_irqs(private, hdr.flags, hdr.index, |
| 613 | data); | ||
| 607 | } | 614 | } |
| 608 | case VFIO_DEVICE_RESET: | 615 | case VFIO_DEVICE_RESET: |
| 609 | return vfio_ccw_mdev_reset(mdev); | 616 | return vfio_ccw_mdev_reset(private); |
| 610 | default: | 617 | default: |
| 611 | return -ENOTTY; | 618 | return -ENOTTY; |
| 612 | } | 619 | } |
| 613 | } | 620 | } |
| 614 | 621 | ||
| 615 | /* Request removal of the device*/ | 622 | /* Request removal of the device*/ |
| 616 | static void vfio_ccw_mdev_request(struct mdev_device *mdev, unsigned int count) | 623 | static void vfio_ccw_mdev_request(struct vfio_device *vdev, unsigned int count) |
| 617 | { | 624 | { |
| 618 | struct vfio_ccw_private *private = dev_get_drvdata(mdev_parent_dev(mdev)); | 625 | struct vfio_ccw_private *private = |
| 619 | 626 | container_of(vdev, struct vfio_ccw_private, vdev); | |
| 620 | if (!private) | 627 | struct device *dev = vdev->dev; |
| 621 | return; | ||
| 622 | 628 | ||
| 623 | if (private->req_trigger) { | 629 | if (private->req_trigger) { |
| 624 | if (!(count % 10)) | 630 | if (!(count % 10)) |
| 625 | dev_notice_ratelimited(mdev_dev(private->mdev), | 631 | dev_notice_ratelimited(dev, |
| 626 | "Relaying device request to user (#%u)\n", | 632 | "Relaying device request to user (#%u)\n", |
| 627 | count); | 633 | count); |
| 628 | 634 | ||
| 629 | eventfd_signal(private->req_trigger, 1); | 635 | eventfd_signal(private->req_trigger, 1); |
| 630 | } else if (count == 0) { | 636 | } else if (count == 0) { |
| 631 | dev_notice(mdev_dev(private->mdev), | 637 | dev_notice(dev, |
| 632 | "No device request channel registered, blocked until released by user\n"); | 638 | "No device request channel registered, blocked until released by user\n"); |
| 633 | } | 639 | } |
| 634 | } | 640 | } |
| 635 | 641 | ||
| 642 | static const struct vfio_device_ops vfio_ccw_dev_ops = { | ||
| 643 | .open_device = vfio_ccw_mdev_open_device, | ||
| 644 | .close_device = vfio_ccw_mdev_close_device, | ||
| 645 | .read = vfio_ccw_mdev_read, | ||
| 646 | .write = vfio_ccw_mdev_write, | ||
| 647 | .ioctl = vfio_ccw_mdev_ioctl, | ||
| 648 | .request = vfio_ccw_mdev_request, | ||
| 649 | }; | ||
| 650 | |||
| 651 | struct mdev_driver vfio_ccw_mdev_driver = { | ||
| 652 | .driver = { | ||
| 653 | .name = "vfio_ccw_mdev", | ||
| 654 | .owner = THIS_MODULE, | ||
| 655 | .mod_name = KBUILD_MODNAME, | ||
| 656 | }, | ||
| 657 | .probe = vfio_ccw_mdev_probe, | ||
| 658 | .remove = vfio_ccw_mdev_remove, | ||
| 659 | }; | ||
| 660 | |||
| 636 | static const struct mdev_parent_ops vfio_ccw_mdev_ops = { | 661 | static const struct mdev_parent_ops vfio_ccw_mdev_ops = { |
| 637 | .owner = THIS_MODULE, | 662 | .owner = THIS_MODULE, |
| 663 | .device_driver = &vfio_ccw_mdev_driver, | ||
| 638 | .supported_type_groups = mdev_type_groups, | 664 | .supported_type_groups = mdev_type_groups, |
| 639 | .create = vfio_ccw_mdev_create, | ||
| 640 | .remove = vfio_ccw_mdev_remove, | ||
| 641 | .open_device = vfio_ccw_mdev_open_device, | ||
| 642 | .close_device = vfio_ccw_mdev_close_device, | ||
| 643 | .read = vfio_ccw_mdev_read, | ||
| 644 | .write = vfio_ccw_mdev_write, | ||
| 645 | .ioctl = vfio_ccw_mdev_ioctl, | ||
| 646 | .request = vfio_ccw_mdev_request, | ||
| 647 | }; | 665 | }; |
| 648 | 666 | ||
| 649 | int vfio_ccw_mdev_reg(struct subchannel *sch) | 667 | int vfio_ccw_mdev_reg(struct subchannel *sch) |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include <linux/eventfd.h> | 17 | #include <linux/eventfd.h> |
| 18 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
| 19 | #include <linux/vfio_ccw.h> | 19 | #include <linux/vfio_ccw.h> |
| 20 | #include <linux/vfio.h> | ||
| 20 | #include <asm/crw.h> | 21 | #include <asm/crw.h> |
| 21 | #include <asm/debug.h> | 22 | #include <asm/debug.h> |
| 22 | 23 | ||
| @@ -67,6 +68,7 @@ struct vfio_ccw_crw { · 44 unmodified lines | |||
| 67 | 68 | ||
| 68 | /** | 69 | /** |
| 69 | * struct vfio_ccw_private | 70 | * struct vfio_ccw_private |
| 71 | * @vdev: Embedded VFIO device | ||
| 70 | * @sch: pointer to the subchannel | 72 | * @sch: pointer to the subchannel |
| 71 | * @state: internal state of the device | 73 | * @state: internal state of the device |
| 72 | * @completion: synchronization helper of the I/O completion | 74 | * @completion: synchronization helper of the I/O completion |
| @@ -90,6 +92,7 @@ struct vfio_ccw_crw { · 17 unmodified lines | |||
| 90 | * @crw_work: work for deferral process of CRW handling | 92 | * @crw_work: work for deferral process of CRW handling |
| 91 | */ | 93 | */ |
| 92 | struct vfio_ccw_private { | 94 | struct vfio_ccw_private { |
| 95 | struct vfio_device vdev; | ||
| 93 | struct subchannel *sch; | 96 | struct subchannel *sch; |
| 94 | int state; | 97 | int state; |
| 95 | struct completion *completion; | 98 | struct completion *completion; |
| @@ -121,6 +124,8 @@ extern void vfio_ccw_mdev_unreg(struct subchannel *sch); · 25 unmodified lines | |||
| 121 | 124 | ||
| 122 | extern int vfio_ccw_sch_quiesce(struct subchannel *sch); | 125 | extern int vfio_ccw_sch_quiesce(struct subchannel *sch); |
| 123 | 126 | ||
| 127 | extern struct mdev_driver vfio_ccw_mdev_driver; | ||
| 128 | |||
| 124 | /* | 129 | /* |
| 125 | * States of the device statemachine. | 130 | * States of the device statemachine. |
| 126 | */ | 131 | */ |
| @@ -351,7 +351,7 @@ static int vfio_ap_mdev_probe(struct mdev_device *mdev) · 350 unmodified lines | |||
| 351 | list_add(&matrix_mdev->node, &matrix_dev->mdev_list); | 351 | list_add(&matrix_mdev->node, &matrix_dev->mdev_list); |
| 352 | mutex_unlock(&matrix_dev->lock); | 352 | mutex_unlock(&matrix_dev->lock); |
| 353 | 353 | ||
| 354 | ret = vfio_register_group_dev(&matrix_mdev->vdev); | 354 | ret = vfio_register_emulated_iommu_dev(&matrix_mdev->vdev); |
| 355 | if (ret) | 355 | if (ret) |
| 356 | goto err_list; | 356 | goto err_list; |
| 357 | dev_set_drvdata(&mdev->dev, matrix_mdev); | 357 | dev_set_drvdata(&mdev->dev, matrix_mdev); |
| @@ -65,6 +65,34 @@ static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev) · 64 unmodified lines | |||
| 65 | kfree(vdev->regions); | 65 | kfree(vdev->regions); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static int vfio_fsl_mc_reset_device(struct vfio_fsl_mc_device *vdev) | ||
| 69 | { | ||
| 70 | struct fsl_mc_device *mc_dev = vdev->mc_dev; | ||
| 71 | int ret = 0; | ||
| 72 | |||
| 73 | if (is_fsl_mc_bus_dprc(vdev->mc_dev)) { | ||
| 74 | return dprc_reset_container(mc_dev->mc_io, 0, | ||
| 75 | mc_dev->mc_handle, | ||
| 76 | mc_dev->obj_desc.id, | ||
| 77 | DPRC_RESET_OPTION_NON_RECURSIVE); | ||
| 78 | } else { | ||
| 79 | u16 token; | ||
| 80 | |||
| 81 | ret = fsl_mc_obj_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, | ||
| 82 | mc_dev->obj_desc.type, | ||
| 83 | &token); | ||
| 84 | if (ret) | ||
| 85 | goto out; | ||
| 86 | ret = fsl_mc_obj_reset(mc_dev->mc_io, 0, token); | ||
| 87 | if (ret) { | ||
| 88 | fsl_mc_obj_close(mc_dev->mc_io, 0, token); | ||
| 89 | goto out; | ||
| 90 | } | ||
| 91 | ret = fsl_mc_obj_close(mc_dev->mc_io, 0, token); | ||
| 92 | } | ||
| 93 | out: | ||
| 94 | return ret; | ||
| 95 | } | ||
| 68 | 96 | ||
| 69 | static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev) | 97 | static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev) |
| 70 | { | 98 | { |
| @@ -78,9 +106,7 @@ static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev) · 7 unmodified lines | |||
| 78 | vfio_fsl_mc_regions_cleanup(vdev); | 106 | vfio_fsl_mc_regions_cleanup(vdev); |
| 79 | 107 | ||
| 80 | /* reset the device before cleaning up the interrupts */ | 108 | /* reset the device before cleaning up the interrupts */ |
| 81 | ret = dprc_reset_container(mc_cont->mc_io, 0, mc_cont->mc_handle, | 109 | ret = vfio_fsl_mc_reset_device(vdev); |
| 82 | mc_cont->obj_desc.id, | ||
| 83 | DPRC_RESET_OPTION_NON_RECURSIVE); | ||
| 84 | 110 | ||
| 85 | if (WARN_ON(ret)) | 111 | if (WARN_ON(ret)) |
| 86 | dev_warn(&mc_cont->dev, | 112 | dev_warn(&mc_cont->dev, |
| @@ -203,18 +229,7 @@ static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev, · 116 unmodified lines | |||
| 203 | } | 229 | } |
| 204 | case VFIO_DEVICE_RESET: | 230 | case VFIO_DEVICE_RESET: |
| 205 | { | 231 | { |
| 206 | int ret; | 232 | return vfio_fsl_mc_reset_device(vdev); |
| 207 | struct fsl_mc_device *mc_dev = vdev->mc_dev; | ||
| 208 | |||
| 209 | /* reset is supported only for the DPRC */ | ||
| 210 | if (!is_fsl_mc_bus_dprc(mc_dev)) | ||
| 211 | return -ENOTTY; | ||
| 212 | |||
| 213 | ret = dprc_reset_container(mc_dev->mc_io, 0, | ||
| 214 | mc_dev->mc_handle, | ||
| 215 | mc_dev->obj_desc.id, | ||
| 216 | DPRC_RESET_OPTION_NON_RECURSIVE); | ||
| 217 | return ret; | ||
| 218 | 233 | ||
| 219 | } | 234 | } |
| 220 | default: | 235 | default: |
| @@ -505,22 +520,13 @@ static void vfio_fsl_uninit_device(struct vfio_fsl_mc_device *vdev) · 284 unmodified lines | |||
| 505 | 520 | ||
| 506 | static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev) | 521 | static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev) |
| 507 | { | 522 | { |
| 508 | struct iommu_group *group; | ||
| 509 | struct vfio_fsl_mc_device *vdev; | 523 | struct vfio_fsl_mc_device *vdev; |
| 510 | struct device *dev = &mc_dev->dev; | 524 | struct device *dev = &mc_dev->dev; |
| 511 | int ret; | 525 | int ret; |
| 512 | 526 | ||
| 513 | group = vfio_iommu_group_get(dev); | ||
| 514 | if (!group) { | ||
| 515 | dev_err(dev, "VFIO_FSL_MC: No IOMMU group\n"); | ||
| 516 | return -EINVAL; | ||
| 517 | } | ||
| 518 | |||
| 519 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); | 527 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); |
| 520 | if (!vdev) { | 528 | if (!vdev) |
| 521 | ret = -ENOMEM; | 529 | return -ENOMEM; |
| 522 | goto out_group_put; | ||
| 523 | } | ||
| 524 | 530 | ||
| 525 | vfio_init_group_dev(&vdev->vdev, dev, &vfio_fsl_mc_ops); | 531 | vfio_init_group_dev(&vdev->vdev, dev, &vfio_fsl_mc_ops); |
| 526 | vdev->mc_dev = mc_dev; | 532 | vdev->mc_dev = mc_dev; |
| @@ -556,8 +562,6 @@ out_device: · 29 unmodified lines | |||
| 556 | out_uninit: | 562 | out_uninit: |
| 557 | vfio_uninit_group_dev(&vdev->vdev); | 563 | vfio_uninit_group_dev(&vdev->vdev); |
| 558 | kfree(vdev); | 564 | kfree(vdev); |
| 559 | out_group_put: | ||
| 560 | vfio_iommu_group_put(group, dev); | ||
| 561 | return ret; | 565 | return ret; |
| 562 | } | 566 | } |
| 563 | 567 | ||
| @@ -574,8 +578,6 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) · 10 unmodified lines | |||
| 574 | 578 | ||
| 575 | vfio_uninit_group_dev(&vdev->vdev); | 579 | vfio_uninit_group_dev(&vdev->vdev); |
| 576 | kfree(vdev); | 580 | kfree(vdev); |
| 577 | vfio_iommu_group_put(mc_dev->dev.iommu_group, dev); | ||
| 578 | |||
| 579 | return 0; | 581 | return 0; |
| 580 | } | 582 | } |
| 581 | 583 | ||
| @@ -13,60 +13,23 @@ · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | #include "mdev_private.h" | 14 | #include "mdev_private.h" |
| 15 | 15 | ||
| 16 | static int mdev_attach_iommu(struct mdev_device *mdev) | ||
| 17 | { | ||
| 18 | int ret; | ||
| 19 | struct iommu_group *group; | ||
| 20 | |||
| 21 | group = iommu_group_alloc(); | ||
| 22 | if (IS_ERR(group)) | ||
| 23 | return PTR_ERR(group); | ||
| 24 | |||
| 25 | ret = iommu_group_add_device(group, &mdev->dev); | ||
| 26 | if (!ret) | ||
| 27 | dev_info(&mdev->dev, "MDEV: group_id = %d\n", | ||
| 28 | iommu_group_id(group)); | ||
| 29 | |||
| 30 | iommu_group_put(group); | ||
| 31 | return ret; | ||
| 32 | } | ||
| 33 | |||
| 34 | static void mdev_detach_iommu(struct mdev_device *mdev) | ||
| 35 | { | ||
| 36 | iommu_group_remove_device(&mdev->dev); | ||
| 37 | dev_info(&mdev->dev, "MDEV: detaching iommu\n"); | ||
| 38 | } | ||
| 39 | |||
| 40 | static int mdev_probe(struct device *dev) | 16 | static int mdev_probe(struct device *dev) |
| 41 | { | 17 | { |
| 42 | struct mdev_driver *drv = | 18 | struct mdev_driver *drv = |
| 43 | container_of(dev->driver, struct mdev_driver, driver); | 19 | container_of(dev->driver, struct mdev_driver, driver); |
| 44 | struct mdev_device *mdev = to_mdev_device(dev); | ||
| 45 | int ret; | ||
| 46 | 20 | ||
| 47 | ret = mdev_attach_iommu(mdev); | 21 | if (!drv->probe) |
| 48 | if (ret) | 22 | return 0; |
| 49 | return ret; | 23 | return drv->probe(to_mdev_device(dev)); |
| 50 | |||
| 51 | if (drv->probe) { | ||
| 52 | ret = drv->probe(mdev); | ||
| 53 | if (ret) | ||
| 54 | mdev_detach_iommu(mdev); | ||
| 55 | } | ||
| 56 | |||
| 57 | return ret; | ||
| 58 | } | 24 | } |
| 59 | 25 | ||
| 60 | static void mdev_remove(struct device *dev) | 26 | static void mdev_remove(struct device *dev) |
| 61 | { | 27 | { |
| 62 | struct mdev_driver *drv = | 28 | struct mdev_driver *drv = |
| 63 | container_of(dev->driver, struct mdev_driver, driver); | 29 | container_of(dev->driver, struct mdev_driver, driver); |
| 64 | struct mdev_device *mdev = to_mdev_device(dev); | ||
| 65 | 30 | ||
| 66 | if (drv->remove) | 31 | if (drv->remove) |
| 67 | drv->remove(mdev); | 32 | drv->remove(to_mdev_device(dev)); |
| 68 | |||
| 69 | mdev_detach_iommu(mdev); | ||
| 70 | } | 33 | } |
| 71 | 34 | ||
| 72 | static int mdev_match(struct device *dev, struct device_driver *drv) | 35 | static int mdev_match(struct device *dev, struct device_driver *drv) |
| @@ -119,7 +119,7 @@ static int vfio_mdev_probe(struct mdev_device *mdev) · 118 unmodified lines | |||
| 119 | return -ENOMEM; | 119 | return -ENOMEM; |
| 120 | 120 | ||
| 121 | vfio_init_group_dev(vdev, &mdev->dev, &vfio_mdev_dev_ops); | 121 | vfio_init_group_dev(vdev, &mdev->dev, &vfio_mdev_dev_ops); |
| 122 | ret = vfio_register_group_dev(vdev); | 122 | ret = vfio_register_emulated_iommu_dev(vdev); |
| 123 | if (ret) | 123 | if (ret) |
| 124 | goto out_uninit; | 124 | goto out_uninit; |
| 125 | 125 | ||
| @@ -1806,7 +1806,6 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_uninit_device); · 1805 unmodified lines | |||
| 1806 | int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) | 1806 | int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) |
| 1807 | { | 1807 | { |
| 1808 | struct pci_dev *pdev = vdev->pdev; | 1808 | struct pci_dev *pdev = vdev->pdev; |
| 1809 | struct iommu_group *group; | ||
| 1810 | int ret; | 1809 | int ret; |
| 1811 | 1810 | ||
| 1812 | if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) | 1811 | if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) |
| @@ -1825,10 +1824,6 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) · 12 unmodified lines | |||
| 1825 | return -EBUSY; | 1824 | return -EBUSY; |
| 1826 | } | 1825 | } |
| 1827 | 1826 | ||
| 1828 | group = vfio_iommu_group_get(&pdev->dev); | ||
| 1829 | if (!group) | ||
| 1830 | return -EINVAL; | ||
| 1831 | |||
| 1832 | if (pci_is_root_bus(pdev->bus)) { | 1827 | if (pci_is_root_bus(pdev->bus)) { |
| 1833 | ret = vfio_assign_device_set(&vdev->vdev, vdev); | 1828 | ret = vfio_assign_device_set(&vdev->vdev, vdev); |
| 1834 | } else if (!pci_probe_reset_slot(pdev->slot)) { | 1829 | } else if (!pci_probe_reset_slot(pdev->slot)) { |
| @@ -1842,10 +1837,10 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) · 7 unmodified lines | |||
| 1842 | } | 1837 | } |
| 1843 | 1838 | ||
| 1844 | if (ret) | 1839 | if (ret) |
| 1845 | goto out_group_put; | 1840 | return ret; |
| 1846 | ret = vfio_pci_vf_init(vdev); | 1841 | ret = vfio_pci_vf_init(vdev); |
| 1847 | if (ret) | 1842 | if (ret) |
| 1848 | goto out_group_put; | 1843 | return ret; |
| 1849 | ret = vfio_pci_vga_init(vdev); | 1844 | ret = vfio_pci_vga_init(vdev); |
| 1850 | if (ret) | 1845 | if (ret) |
| 1851 | goto out_vf; | 1846 | goto out_vf; |
| @@ -1876,8 +1871,6 @@ out_power: · 24 unmodified lines | |||
| 1876 | vfio_pci_set_power_state(vdev, PCI_D0); | 1871 | vfio_pci_set_power_state(vdev, PCI_D0); |
| 1877 | out_vf: | 1872 | out_vf: |
| 1878 | vfio_pci_vf_uninit(vdev); | 1873 | vfio_pci_vf_uninit(vdev); |
| 1879 | out_group_put: | ||
| 1880 | vfio_iommu_group_put(group, &pdev->dev); | ||
| 1881 | return ret; | 1874 | return ret; |
| 1882 | } | 1875 | } |
| 1883 | EXPORT_SYMBOL_GPL(vfio_pci_core_register_device); | 1876 | EXPORT_SYMBOL_GPL(vfio_pci_core_register_device); |
| @@ -1893,8 +1886,6 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev) · 9 unmodified lines | |||
| 1893 | vfio_pci_vf_uninit(vdev); | 1886 | vfio_pci_vf_uninit(vdev); |
| 1894 | vfio_pci_vga_uninit(vdev); | 1887 | vfio_pci_vga_uninit(vdev); |
| 1895 | 1888 | ||
| 1896 | vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev); | ||
| 1897 | |||
| 1898 | if (!disable_idle_d3) | 1889 | if (!disable_idle_d3) |
| 1899 | vfio_pci_set_power_state(vdev, PCI_D0); | 1890 | vfio_pci_set_power_state(vdev, PCI_D0); |
| 1900 | } | 1891 | } |
| @@ -25,20 +25,121 @@ · 24 unmodified lines | |||
| 25 | #define OPREGION_RVDS 0x3c2 | 25 | #define OPREGION_RVDS 0x3c2 |
| 26 | #define OPREGION_VERSION 0x16 | 26 | #define OPREGION_VERSION 0x16 |
| 27 | 27 | ||
| 28 | struct igd_opregion_vbt { | ||
| 29 | void *opregion; | ||
| 30 | void *vbt_ex; | ||
| 31 | }; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * igd_opregion_shift_copy() - Copy OpRegion to user buffer and shift position. | ||
| 35 | * @dst: User buffer ptr to copy to. | ||
| 36 | * @off: Offset to user buffer ptr. Increased by bytes on return. | ||
| 37 | * @src: Source buffer to copy from. | ||
| 38 | * @pos: Increased by bytes on return. | ||
| 39 | * @remaining: Decreased by bytes on return. | ||
| 40 | * @bytes: Bytes to copy and adjust off, pos and remaining. | ||
| 41 | * | ||
| 42 | * Copy OpRegion to offset from specific source ptr and shift the offset. | ||
| 43 | * | ||
| 44 | * Return: 0 on success, -EFAULT otherwise. | ||
| 45 | * | ||
| 46 | */ | ||
| 47 | static inline unsigned long igd_opregion_shift_copy(char __user *dst, | ||
| 48 | loff_t *off, | ||
| 49 | void *src, | ||
| 50 | loff_t *pos, | ||
| 51 | size_t *remaining, | ||
| 52 | size_t bytes) | ||
| 53 | { | ||
| 54 | if (copy_to_user(dst + (*off), src, bytes)) | ||
| 55 | return -EFAULT; | ||
| 56 | |||
| 57 | *off += bytes; | ||
| 58 | *pos += bytes; | ||
| 59 | *remaining -= bytes; | ||
| 60 | |||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 28 | static ssize_t vfio_pci_igd_rw(struct vfio_pci_core_device *vdev, | 64 | static ssize_t vfio_pci_igd_rw(struct vfio_pci_core_device *vdev, |
| 29 | char __user *buf, size_t count, loff_t *ppos, | 65 | char __user *buf, size_t count, loff_t *ppos, |
| 30 | bool iswrite) | 66 | bool iswrite) |
| 31 | { | 67 | { |
| 32 | unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS; | 68 | unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS; |
| 33 | void *base = vdev->region[i].data; | 69 | struct igd_opregion_vbt *opregionvbt = vdev->region[i].data; |
| 34 | loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK; | 70 | loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK, off = 0; |
| 71 | size_t remaining; | ||
| 35 | 72 | ||
| 36 | if (pos >= vdev->region[i].size || iswrite) | 73 | if (pos >= vdev->region[i].size || iswrite) |
| 37 | return -EINVAL; | 74 | return -EINVAL; |
| 38 | 75 | ||
| 39 | count = min(count, (size_t)(vdev->region[i].size - pos)); | 76 | count = min_t(size_t, count, vdev->region[i].size - pos); |
| 77 | remaining = count; | ||
| 78 | |||
| 79 | /* Copy until OpRegion version */ | ||
| 80 | if (remaining && pos < OPREGION_VERSION) { | ||
| 81 | size_t bytes = min_t(size_t, remaining, OPREGION_VERSION - pos); | ||
| 82 | |||
| 83 | if (igd_opregion_shift_copy(buf, &off, | ||
| 84 | opregionvbt->opregion + pos, &pos, | ||
| 85 | &remaining, bytes)) | ||
| 86 | return -EFAULT; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* Copy patched (if necessary) OpRegion version */ | ||
| 90 | if (remaining && pos < OPREGION_VERSION + sizeof(__le16)) { | ||
| 91 | size_t bytes = min_t(size_t, remaining, | ||
| 92 | OPREGION_VERSION + sizeof(__le16) - pos); | ||
| 93 | __le16 version = *(__le16 *)(opregionvbt->opregion + | ||
| 94 | OPREGION_VERSION); | ||
| 95 | |||
| 96 | /* Patch to 2.1 if OpRegion 2.0 has extended VBT */ | ||
| 97 | if (le16_to_cpu(version) == 0x0200 && opregionvbt->vbt_ex) | ||
| 98 | version = cpu_to_le16(0x0201); | ||
| 99 | |||
| 100 | if (igd_opregion_shift_copy(buf, &off, | ||
| 101 | &version + (pos - OPREGION_VERSION), | ||
| 102 | &pos, &remaining, bytes)) | ||
| 103 | return -EFAULT; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* Copy until RVDA */ | ||
| 107 | if (remaining && pos < OPREGION_RVDA) { | ||
| 108 | size_t bytes = min_t(size_t, remaining, OPREGION_RVDA - pos); | ||
| 40 | 109 | ||
| 41 | if (copy_to_user(buf, base + pos, count)) | 110 | if (igd_opregion_shift_copy(buf, &off, |
| 111 | opregionvbt->opregion + pos, &pos, | ||
| 112 | &remaining, bytes)) | ||
| 113 | return -EFAULT; | ||
| 114 | } | ||
| 115 | |||
| 116 | /* Copy modified (if necessary) RVDA */ | ||
| 117 | if (remaining && pos < OPREGION_RVDA + sizeof(__le64)) { | ||
| 118 | size_t bytes = min_t(size_t, remaining, | ||
| 119 | OPREGION_RVDA + sizeof(__le64) - pos); | ||
| 120 | __le64 rvda = cpu_to_le64(opregionvbt->vbt_ex ? | ||
| 121 | OPREGION_SIZE : 0); | ||
| 122 | |||
| 123 | if (igd_opregion_shift_copy(buf, &off, | ||
| 124 | &rvda + (pos - OPREGION_RVDA), | ||
| 125 | &pos, &remaining, bytes)) | ||
| 126 | return -EFAULT; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* Copy the rest of OpRegion */ | ||
| 130 | if (remaining && pos < OPREGION_SIZE) { | ||
| 131 | size_t bytes = min_t(size_t, remaining, OPREGION_SIZE - pos); | ||
| 132 | |||
| 133 | if (igd_opregion_shift_copy(buf, &off, | ||
| 134 | opregionvbt->opregion + pos, &pos, | ||
| 135 | &remaining, bytes)) | ||
| 136 | return -EFAULT; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* Copy extended VBT if exists */ | ||
| 140 | if (remaining && | ||
| 141 | copy_to_user(buf + off, opregionvbt->vbt_ex + (pos - OPREGION_SIZE), | ||
| 142 | remaining)) | ||
| 42 | return -EFAULT; | 143 | return -EFAULT; |
| 43 | 144 | ||
| 44 | *ppos += count; | 145 | *ppos += count; |
| @@ -49,7 +150,13 @@ static ssize_t vfio_pci_igd_rw(struct vfio_pci_core_device *vdev, · 4 unmodified lines | |||
| 49 | static void vfio_pci_igd_release(struct vfio_pci_core_device *vdev, | 150 | static void vfio_pci_igd_release(struct vfio_pci_core_device *vdev, |
| 50 | struct vfio_pci_region *region) | 151 | struct vfio_pci_region *region) |
| 51 | { | 152 | { |
| 52 | memunmap(region->data); | 153 | struct igd_opregion_vbt *opregionvbt = region->data; |
| 154 | |||
| 155 | if (opregionvbt->vbt_ex) | ||
| 156 | memunmap(opregionvbt->vbt_ex); | ||
| 157 | |||
| 158 | memunmap(opregionvbt->opregion); | ||
| 159 | kfree(opregionvbt); | ||
| 53 | } | 160 | } |
| 54 | 161 | ||
| 55 | static const struct vfio_pci_regops vfio_pci_igd_regops = { | 162 | static const struct vfio_pci_regops vfio_pci_igd_regops = { |
| @@ -61,7 +168,7 @@ static int vfio_pci_igd_opregion_init(struct vfio_pci_core_device *vdev) · 5 unmodified lines | |||
| 61 | { | 168 | { |
| 62 | __le32 *dwordp = (__le32 *)(vdev->vconfig + OPREGION_PCI_ADDR); | 169 | __le32 *dwordp = (__le32 *)(vdev->vconfig + OPREGION_PCI_ADDR); |
| 63 | u32 addr, size; | 170 | u32 addr, size; |
| 64 | void *base; | 171 | struct igd_opregion_vbt *opregionvbt; |
| 65 | int ret; | 172 | int ret; |
| 66 | u16 version; | 173 | u16 version; |
| 67 | 174 | ||
| @@ -72,84 +179,93 @@ static int vfio_pci_igd_opregion_init(struct vfio_pci_core_device *vdev) · 4 unmodified lines | |||
| 72 | if (!addr || !(~addr)) | 179 | if (!addr || !(~addr)) |
| 73 | return -ENODEV; | 180 | return -ENODEV; |
| 74 | 181 | ||
| 75 | base = memremap(addr, OPREGION_SIZE, MEMREMAP_WB); | 182 | opregionvbt = kzalloc(sizeof(*opregionvbt), GFP_KERNEL); |
| 76 | if (!base) | 183 | if (!opregionvbt) |
| 184 | return -ENOMEM; | ||
| 185 | |||
| 186 | opregionvbt->opregion = memremap(addr, OPREGION_SIZE, MEMREMAP_WB); | ||
| 187 | if (!opregionvbt->opregion) { | ||
| 188 | kfree(opregionvbt); | ||
| 77 | return -ENOMEM; | 189 | return -ENOMEM; |
| 190 | } | ||
| 78 | 191 | ||
| 79 | if (memcmp(base, OPREGION_SIGNATURE, 16)) { | 192 | if (memcmp(opregionvbt->opregion, OPREGION_SIGNATURE, 16)) { |
| 80 | memunmap(base); | 193 | memunmap(opregionvbt->opregion); |
| 194 | kfree(opregionvbt); | ||
| 81 | return -EINVAL; | 195 | return -EINVAL; |
| 82 | } | 196 | } |
| 83 | 197 | ||
| 84 | size = le32_to_cpu(*(__le32 *)(base + 16)); | 198 | size = le32_to_cpu(*(__le32 *)(opregionvbt->opregion + 16)); |
| 85 | if (!size) { | 199 | if (!size) { |
| 86 | memunmap(base); | 200 | memunmap(opregionvbt->opregion); |
| 201 | kfree(opregionvbt); | ||
| 87 | return -EINVAL; | 202 | return -EINVAL; |
| 88 | } | 203 | } |
| 89 | 204 | ||
| 90 | size *= 1024; /* In KB */ | 205 | size *= 1024; /* In KB */ |
| 91 | 206 | ||
| 92 | /* | 207 | /* |
| 93 | * Support opregion v2.1+ | 208 | * OpRegion and VBT: |
| 94 | * When VBT data exceeds 6KB size and cannot be within mailbox #4, then | 209 | * When VBT data doesn't exceed 6KB, it's stored in Mailbox #4. |
| 95 | * the Extended VBT region next to opregion is used to hold the VBT data. | 210 | * When VBT data exceeds 6KB size, Mailbox #4 is no longer large enough |
| 96 | * RVDA (Relative Address of VBT Data from Opregion Base) and RVDS | 211 | * to hold the VBT data, the Extended VBT region is introduced since |
| 97 | * (Raw VBT Data Size) from opregion structure member are used to hold the | 212 | * OpRegion 2.0 to hold the VBT data. Since OpRegion 2.0, RVDA/RVDS are |
| 98 | * address from region base and size of VBT data. RVDA/RVDS are not | 213 | * introduced to define the extended VBT data location and size. |
| 99 | * defined before opregion 2.0. | 214 | * OpRegion 2.0: RVDA defines the absolute physical address of the |
| 100 | * | 215 | * extended VBT data, RVDS defines the VBT data size. |
| 101 | * opregion 2.1+: RVDA is unsigned, relative offset from | 216 | * OpRegion 2.1 and above: RVDA defines the relative address of the |
| 102 | * opregion base, and should point to the end of opregion. | 217 | * extended VBT data to OpRegion base, RVDS defines the VBT data size. |
| 103 | * otherwise, exposing to userspace to allow read access to everything between | ||
| 104 | * the OpRegion and VBT is not safe. | ||
| 105 | * RVDS is defined as size in bytes. | ||
| 106 | * | 218 | * |
| 107 | * opregion 2.0: rvda is the physical VBT address. | 219 | * Due to the RVDA definition diff in OpRegion VBT (also the only diff |
| 108 | * Since rvda is HPA it cannot be directly used in guest. | 220 | * between 2.0 and 2.1), exposing OpRegion and VBT as a contiguous range |
| 109 | * And it should not be practically available for end user,so it is not supported. | 221 | * for OpRegion 2.0 and above makes it possible to support the |
| 222 | * non-contiguous VBT through a single vfio region. From r/w ops view, | ||
| 223 | * only contiguous VBT after OpRegion with version 2.1+ is exposed, | ||
| 224 | * regardless the host OpRegion is 2.0 or non-contiguous 2.1+. The r/w | ||
| 225 | * ops will on-the-fly shift the actural offset into VBT so that data at | ||
| 226 | * correct position can be returned to the requester. | ||
| 110 | */ | 227 | */ |
| 111 | version = le16_to_cpu(*(__le16 *)(base + OPREGION_VERSION)); | 228 | version = le16_to_cpu(*(__le16 *)(opregionvbt->opregion + |
| 229 | OPREGION_VERSION)); | ||
| 112 | if (version >= 0x0200) { | 230 | if (version >= 0x0200) { |
| 113 | u64 rvda; | 231 | u64 rvda = le64_to_cpu(*(__le64 *)(opregionvbt->opregion + |
| 114 | u32 rvds; | 232 | OPREGION_RVDA)); |
| 233 | u32 rvds = le32_to_cpu(*(__le32 *)(opregionvbt->opregion + | ||
| 234 | OPREGION_RVDS)); | ||
| 115 | 235 | ||
| 116 | rvda = le64_to_cpu(*(__le64 *)(base + OPREGION_RVDA)); | 236 | /* The extended VBT is valid only when RVDA/RVDS are non-zero */ |
| 117 | rvds = le32_to_cpu(*(__le32 *)(base + OPREGION_RVDS)); | ||
| 118 | if (rvda && rvds) { | 237 | if (rvda && rvds) { |
| 119 | /* no support for opregion v2.0 with physical VBT address */ | 238 | size += rvds; |
| 120 | if (version == 0x0200) { | ||
| 121 | memunmap(base); | ||
| 122 | pci_err(vdev->pdev, | ||
| 123 | "IGD assignment does not support opregion v2.0 with an extended VBT region\n"); | ||
| 124 | return -EINVAL; | ||
| 125 | } | ||
| 126 | 239 | ||
| 127 | if (rvda != size) { | 240 | /* |
| 128 | memunmap(base); | 241 | * Extended VBT location by RVDA: |
| 129 | pci_err(vdev->pdev, | 242 | * Absolute physical addr for 2.0. |
| 130 | "Extended VBT does not follow opregion on version 0x%04x\n", | 243 | * Relative addr to OpRegion header for 2.1+. |
| 131 | version); | 244 | */ |
| 132 | return -EINVAL; | 245 | if (version == 0x0200) |
| 246 | addr = rvda; | ||
| 247 | else | ||
| 248 | addr += rvda; | ||
| 249 | |||
| 250 | opregionvbt->vbt_ex = memremap(addr, rvds, MEMREMAP_WB); | ||
| 251 | if (!opregionvbt->vbt_ex) { | ||
| 252 | memunmap(opregionvbt->opregion); | ||
| 253 | kfree(opregionvbt); | ||
| 254 | return -ENOMEM; | ||
| 133 | } | 255 | } |
| 134 | |||
| 135 | /* region size for opregion v2.0+: opregion and VBT size. */ | ||
| 136 | size += rvds; | ||
| 137 | } | 256 | } |
| 138 | } | 257 | } |
| 139 | 258 | ||
| 140 | if (size != OPREGION_SIZE) { | ||
| 141 | memunmap(base); | ||
| 142 | base = memremap(addr, size, MEMREMAP_WB); | ||
| 143 | if (!base) | ||
| 144 | return -ENOMEM; | ||
| 145 | } | ||
| 146 | |||
| 147 | ret = vfio_pci_register_dev_region(vdev, | 259 | ret = vfio_pci_register_dev_region(vdev, |
| 148 | PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE, | 260 | PCI_VENDOR_ID_INTEL | VFIO_REGION_TYPE_PCI_VENDOR_TYPE, |
| 149 | VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, | 261 | VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &vfio_pci_igd_regops, |
| 150 | &vfio_pci_igd_regops, size, VFIO_REGION_INFO_FLAG_READ, base); | 262 | size, VFIO_REGION_INFO_FLAG_READ, opregionvbt); |
| 151 | if (ret) { | 263 | if (ret) { |
| 152 | memunmap(base); | 264 | if (opregionvbt->vbt_ex) |
| 265 | memunmap(opregionvbt->vbt_ex); | ||
| 266 | |||
| 267 | memunmap(opregionvbt->opregion); | ||
| 268 | kfree(opregionvbt); | ||
| 153 | return ret; | 269 | return ret; |
| 154 | } | 270 | } |
| 155 | 271 | ||
| @@ -642,7 +642,6 @@ static int vfio_platform_of_probe(struct vfio_platform_device *vdev, · 641 unmodified lines | |||
| 642 | int vfio_platform_probe_common(struct vfio_platform_device *vdev, | 642 | int vfio_platform_probe_common(struct vfio_platform_device *vdev, |
| 643 | struct device *dev) | 643 | struct device *dev) |
| 644 | { | 644 | { |
| 645 | struct iommu_group *group; | ||
| 646 | int ret; | 645 | int ret; |
| 647 | 646 | ||
| 648 | vfio_init_group_dev(&vdev->vdev, dev, &vfio_platform_ops); | 647 | vfio_init_group_dev(&vdev->vdev, dev, &vfio_platform_ops); |
| @@ -663,24 +662,15 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev, · 14 unmodified lines | |||
| 663 | goto out_uninit; | 662 | goto out_uninit; |
| 664 | } | 663 | } |
| 665 | 664 | ||
| 666 | group = vfio_iommu_group_get(dev); | ||
| 667 | if (!group) { | ||
| 668 | dev_err(dev, "No IOMMU group for device %s\n", vdev->name); | ||
| 669 | ret = -EINVAL; | ||
| 670 | goto put_reset; | ||
| 671 | } | ||
| 672 | |||
| 673 | ret = vfio_register_group_dev(&vdev->vdev); | 665 | ret = vfio_register_group_dev(&vdev->vdev); |
| 674 | if (ret) | 666 | if (ret) |
| 675 | goto put_iommu; | 667 | goto put_reset; |
| 676 | 668 | ||
| 677 | mutex_init(&vdev->igate); | 669 | mutex_init(&vdev->igate); |
| 678 | 670 | ||
| 679 | pm_runtime_enable(dev); | 671 | pm_runtime_enable(dev); |
| 680 | return 0; | 672 | return 0; |
| 681 | 673 | ||
| 682 | put_iommu: | ||
| 683 | vfio_iommu_group_put(group, dev); | ||
| 684 | put_reset: | 674 | put_reset: |
| 685 | vfio_platform_put_reset(vdev); | 675 | vfio_platform_put_reset(vdev); |
| 686 | out_uninit: | 676 | out_uninit: |
| @@ -696,7 +686,6 @@ void vfio_platform_remove_common(struct vfio_platform_device *vdev) · 9 unmodified lines | |||
| 696 | pm_runtime_disable(vdev->device); | 686 | pm_runtime_disable(vdev->device); |
| 697 | vfio_platform_put_reset(vdev); | 687 | vfio_platform_put_reset(vdev); |
| 698 | vfio_uninit_group_dev(&vdev->vdev); | 688 | vfio_uninit_group_dev(&vdev->vdev); |
| 699 | vfio_iommu_group_put(vdev->vdev.dev->iommu_group, vdev->vdev.dev); | ||
| 700 | } | 689 | } |
| 701 | EXPORT_SYMBOL_GPL(vfio_platform_remove_common); | 690 | EXPORT_SYMBOL_GPL(vfio_platform_remove_common); |
| 702 | 691 | ||
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | #include <linux/vfio.h> | 32 | #include <linux/vfio.h> |
| 33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
| 34 | #include <linux/sched/signal.h> | 34 | #include <linux/sched/signal.h> |
| 35 | #include "vfio.h" | ||
| 35 | 36 | ||
| 36 | #define DRIVER_VERSION "0.3" | 37 | #define DRIVER_VERSION "0.3" |
| 37 | #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>" | 38 | #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>" |
| @@ -42,9 +43,8 @@ static struct vfio { · 4 unmodified lines | |||
| 42 | struct list_head iommu_drivers_list; | 43 | struct list_head iommu_drivers_list; |
| 43 | struct mutex iommu_drivers_lock; | 44 | struct mutex iommu_drivers_lock; |
| 44 | struct list_head group_list; | 45 | struct list_head group_list; |
| 45 | struct idr group_idr; | 46 | struct mutex group_lock; /* locks group_list */ |
| 46 | struct mutex group_lock; | 47 | struct ida group_ida; |
| 47 | struct cdev group_cdev; | ||
| 48 | dev_t group_devt; | 48 | dev_t group_devt; |
| 49 | } vfio; | 49 | } vfio; |
| 50 | 50 | ||
| @@ -68,14 +68,14 @@ struct vfio_unbound_dev { · 17 unmodified lines | |||
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | struct vfio_group { | 70 | struct vfio_group { |
| 71 | struct kref kref; | 71 | struct device dev; |
| 72 | int minor; | 72 | struct cdev cdev; |
| 73 | refcount_t users; | ||
| 73 | atomic_t container_users; | 74 | atomic_t container_users; |
| 74 | struct iommu_group *iommu_group; | 75 | struct iommu_group *iommu_group; |
| 75 | struct vfio_container *container; | 76 | struct vfio_container *container; |
| 76 | struct list_head device_list; | 77 | struct list_head device_list; |
| 77 | struct mutex device_lock; | 78 | struct mutex device_lock; |
| 78 | struct device *dev; | ||
| 79 | struct notifier_block nb; | 79 | struct notifier_block nb; |
| 80 | struct list_head vfio_next; | 80 | struct list_head vfio_next; |
| 81 | struct list_head container_next; | 81 | struct list_head container_next; |
| @@ -83,7 +83,7 @@ struct vfio_group { · 1 unmodified line | |||
| 83 | struct mutex unbound_lock; | 83 | struct mutex unbound_lock; |
| 84 | atomic_t opened; | 84 | atomic_t opened; |
| 85 | wait_queue_head_t container_q; | 85 | wait_queue_head_t container_q; |
| 86 | bool noiommu; | 86 | enum vfio_group_type type; |
| 87 | unsigned int dev_counter; | 87 | unsigned int dev_counter; |
| 88 | struct kvm *kvm; | 88 | struct kvm *kvm; |
| 89 | struct blocking_notifier_head notifier; | 89 | struct blocking_notifier_head notifier; |
| @@ -97,6 +97,7 @@ MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. Thi · 7 unmodified lines | |||
| 97 | #endif | 97 | #endif |
| 98 | 98 | ||
| 99 | static DEFINE_XARRAY(vfio_device_set_xa); | 99 | static DEFINE_XARRAY(vfio_device_set_xa); |
| 100 | static const struct file_operations vfio_group_fops; | ||
| 100 | 101 | ||
| 101 | int vfio_assign_device_set(struct vfio_device *device, void *set_id) | 102 | int vfio_assign_device_set(struct vfio_device *device, void *set_id) |
| 102 | { | 103 | { |
| @@ -169,70 +170,6 @@ static void vfio_release_device_set(struct vfio_device *device) · 66 unmodified lines | |||
| 169 | xa_unlock(&vfio_device_set_xa); | 170 | xa_unlock(&vfio_device_set_xa); |
| 170 | } | 171 | } |
| 171 | 172 | ||
| 172 | /* | ||
| 173 | * vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe | ||
| 174 | * and remove functions, any use cases other than acquiring the first | ||
| 175 | * reference for the purpose of calling vfio_register_group_dev() or removing | ||
| 176 | * that symmetric reference after vfio_unregister_group_dev() should use the raw | ||
| 177 | * iommu_group_{get,put} functions. In particular, vfio_iommu_group_put() | ||
| 178 | * removes the device from the dummy group and cannot be nested. | ||
| 179 | */ | ||
| 180 | struct iommu_group *vfio_iommu_group_get(struct device *dev) | ||
| 181 | { | ||
| 182 | struct iommu_group *group; | ||
| 183 | int __maybe_unused ret; | ||
| 184 | |||
| 185 | group = iommu_group_get(dev); | ||
| 186 | |||
| 187 | #ifdef CONFIG_VFIO_NOIOMMU | ||
| 188 | /* | ||
| 189 | * With noiommu enabled, an IOMMU group will be created for a device | ||
| 190 | * that doesn't already have one and doesn't have an iommu_ops on their | ||
| 191 | * bus. We set iommudata simply to be able to identify these groups | ||
| 192 | * as special use and for reclamation later. | ||
| 193 | */ | ||
| 194 | if (group || !noiommu || iommu_present(dev->bus)) | ||
| 195 | return group; | ||
| 196 | |||
| 197 | group = iommu_group_alloc(); | ||
| 198 | if (IS_ERR(group)) | ||
| 199 | return NULL; | ||
| 200 | |||
| 201 | iommu_group_set_name(group, "vfio-noiommu"); | ||
| 202 | iommu_group_set_iommudata(group, &noiommu, NULL); | ||
| 203 | ret = iommu_group_add_device(group, dev); | ||
| 204 | if (ret) { | ||
| 205 | iommu_group_put(group); | ||
| 206 | return NULL; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* | ||
| 210 | * Where to taint? At this point we've added an IOMMU group for a | ||
| 211 | * device that is not backed by iommu_ops, therefore any iommu_ | ||
| 212 | * callback using iommu_ops can legitimately Oops. So, while we may | ||
| 213 | * be about to give a DMA capable device to a user without IOMMU | ||
| 214 | * protection, which is clearly taint-worthy, let's go ahead and do | ||
| 215 | * it here. | ||
| 216 | */ | ||
| 217 | add_taint(TAINT_USER, LOCKDEP_STILL_OK); | ||
| 218 | dev_warn(dev, "Adding kernel taint for vfio-noiommu group on device\n"); | ||
| 219 | #endif | ||
| 220 | |||
| 221 | return group; | ||
| 222 | } | ||
| 223 | EXPORT_SYMBOL_GPL(vfio_iommu_group_get); | ||
| 224 | |||
| 225 | void vfio_iommu_group_put(struct iommu_group *group, struct device *dev) | ||
| 226 | { | ||
| 227 | #ifdef CONFIG_VFIO_NOIOMMU | ||
| 228 | if (iommu_group_get_iommudata(group) == &noiommu) | ||
| 229 | iommu_group_remove_device(dev); | ||
| 230 | #endif | ||
| 231 | |||
| 232 | iommu_group_put(group); | ||
| 233 | } | ||
| 234 | EXPORT_SYMBOL_GPL(vfio_iommu_group_put); | ||
| 235 | |||
| 236 | #ifdef CONFIG_VFIO_NOIOMMU | 173 | #ifdef CONFIG_VFIO_NOIOMMU |
| 237 | static void *vfio_noiommu_open(unsigned long arg) | 174 | static void *vfio_noiommu_open(unsigned long arg) |
| 238 | { | 175 | { |
| @@ -258,9 +195,9 @@ static long vfio_noiommu_ioctl(void *iommu_data, · 19 unmodified lines | |||
| 258 | } | 195 | } |
| 259 | 196 | ||
| 260 | static int vfio_noiommu_attach_group(void *iommu_data, | 197 | static int vfio_noiommu_attach_group(void *iommu_data, |
| 261 | struct iommu_group *iommu_group) | 198 | struct iommu_group *iommu_group, enum vfio_group_type type) |
| 262 | { | 199 | { |
| 263 | return iommu_group_get_iommudata(iommu_group) == &noiommu ? 0 : -EINVAL; | 200 | return 0; |
| 264 | } | 201 | } |
| 265 | 202 | ||
| 266 | static void vfio_noiommu_detach_group(void *iommu_data, | 203 | static void vfio_noiommu_detach_group(void *iommu_data, |
| @@ -277,8 +214,23 @@ static const struct vfio_iommu_driver_ops vfio_noiommu_ops = { · 10 unmodified lines | |||
| 277 | .attach_group = vfio_noiommu_attach_group, | 214 | .attach_group = vfio_noiommu_attach_group, |
| 278 | .detach_group = vfio_noiommu_detach_group, | 215 | .detach_group = vfio_noiommu_detach_group, |
| 279 | }; | 216 | }; |
| 280 | #endif | ||
| 281 | 217 | ||
| 218 | /* | ||
| 219 | * Only noiommu containers can use vfio-noiommu and noiommu containers can only | ||
| 220 | * use vfio-noiommu. | ||
| 221 | */ | ||
| 222 | static inline bool vfio_iommu_driver_allowed(struct vfio_container *container, | ||
| 223 | const struct vfio_iommu_driver *driver) | ||
| 224 | { | ||
| 225 | return container->noiommu == (driver->ops == &vfio_noiommu_ops); | ||
| 226 | } | ||
| 227 | #else | ||
| 228 | static inline bool vfio_iommu_driver_allowed(struct vfio_container *container, | ||
| 229 | const struct vfio_iommu_driver *driver) | ||
| 230 | { | ||
| 231 | return true; | ||
| 232 | } | ||
| 233 | #endif /* CONFIG_VFIO_NOIOMMU */ | ||
| 282 | 234 | ||
| 283 | /** | 235 | /** |
| 284 | * IOMMU driver registration | 236 | * IOMMU driver registration |
| @@ -329,19 +281,6 @@ void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops) · 44 unmodified lines | |||
| 329 | } | 281 | } |
| 330 | EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver); | 282 | EXPORT_SYMBOL_GPL(vfio_unregister_iommu_driver); |
| 331 | 283 | ||
| 332 | /** | ||
| 333 | * Group minor allocation/free - both called with vfio.group_lock held | ||
| 334 | */ | ||
| 335 | static int vfio_alloc_group_minor(struct vfio_group *group) | ||
| 336 | { | ||
| 337 | return idr_alloc(&vfio.group_idr, group, 0, MINORMASK + 1, GFP_KERNEL); | ||
| 338 | } | ||
| 339 | |||
| 340 | static void vfio_free_group_minor(int minor) | ||
| 341 | { | ||
| 342 | idr_remove(&vfio.group_idr, minor); | ||
| 343 | } | ||
| 344 | |||
| 345 | static int vfio_iommu_group_notifier(struct notifier_block *nb, | 284 | static int vfio_iommu_group_notifier(struct notifier_block *nb, |
| 346 | unsigned long action, void *data); | 285 | unsigned long action, void *data); |
| 347 | static void vfio_group_get(struct vfio_group *group); | 286 | static void vfio_group_get(struct vfio_group *group); |
| @@ -370,105 +309,38 @@ static void vfio_container_put(struct vfio_container *container) · 22 unmodified lines | |||
| 370 | kref_put(&container->kref, vfio_container_release); | 309 | kref_put(&container->kref, vfio_container_release); |
| 371 | } | 310 | } |
| 372 | 311 | ||
| 373 | static void vfio_group_unlock_and_free(struct vfio_group *group) | ||
| 374 | { | ||
| 375 | mutex_unlock(&vfio.group_lock); | ||
| 376 | /* | ||
| 377 | * Unregister outside of lock. A spurious callback is harmless now | ||
| 378 | * that the group is no longer in vfio.group_list. | ||
| 379 | */ | ||
| 380 | iommu_group_unregister_notifier(group->iommu_group, &group->nb); | ||
| 381 | kfree(group); | ||
| 382 | } | ||
| 383 | |||
| 384 | /** | 312 | /** |
| 385 | * Group objects - create, release, get, put, search | 313 | * Group objects - create, release, get, put, search |
| 386 | */ | 314 | */ |
| 387 | static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group) | 315 | static struct vfio_group * |
| 316 | __vfio_group_get_from_iommu(struct iommu_group *iommu_group) | ||
| 388 | { | 317 | { |
| 389 | struct vfio_group *group, *tmp; | 318 | struct vfio_group *group; |
| 390 | struct device *dev; | ||
| 391 | int ret, minor; | ||
| 392 | |||
| 393 | group = kzalloc(sizeof(*group), GFP_KERNEL); | ||
| 394 | if (!group) | ||
| 395 | return ERR_PTR(-ENOMEM); | ||
| 396 | |||
| 397 | kref_init(&group->kref); | ||
| 398 | INIT_LIST_HEAD(&group->device_list); | ||
| 399 | mutex_init(&group->device_lock); | ||
| 400 | INIT_LIST_HEAD(&group->unbound_list); | ||
| 401 | mutex_init(&group->unbound_lock); | ||
| 402 | atomic_set(&group->container_users, 0); | ||
| 403 | atomic_set(&group->opened, 0); | ||
| 404 | init_waitqueue_head(&group->container_q); | ||
| 405 | group->iommu_group = iommu_group; | ||
| 406 | #ifdef CONFIG_VFIO_NOIOMMU | ||
| 407 | group->noiommu = (iommu_group_get_iommudata(iommu_group) == &noiommu); | ||
| 408 | #endif | ||
| 409 | BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier); | ||
| 410 | |||
| 411 | group->nb.notifier_call = vfio_iommu_group_notifier; | ||
| 412 | |||
| 413 | /* | ||
| 414 | * blocking notifiers acquire a rwsem around registering and hold | ||
| 415 | * it around callback. Therefore, need to register outside of | ||
| 416 | * vfio.group_lock to avoid A-B/B-A contention. Our callback won't | ||
| 417 | * do anything unless it can find the group in vfio.group_list, so | ||
| 418 | * no harm in registering early. | ||
| 419 | */ | ||
| 420 | ret = iommu_group_register_notifier(iommu_group, &group->nb); | ||
| 421 | if (ret) { | ||
| 422 | kfree(group); | ||
| 423 | return ERR_PTR(ret); | ||
| 424 | } | ||
| 425 | |||
| 426 | mutex_lock(&vfio.group_lock); | ||
| 427 | 319 | ||
| 428 | /* Did we race creating this group? */ | 320 | list_for_each_entry(group, &vfio.group_list, vfio_next) { |
| 429 | list_for_each_entry(tmp, &vfio.group_list, vfio_next) { | 321 | if (group->iommu_group == iommu_group) { |
| 430 | if (tmp->iommu_group == iommu_group) { | 322 | vfio_group_get(group); |
| 431 | vfio_group_get(tmp); | 323 | return group; |
| 432 | vfio_group_unlock_and_free(group); | ||
| 433 | return tmp; | ||
| 434 | } | 324 | } |
| 435 | } | 325 | } |
| 326 | return NULL; | ||
| 327 | } | ||
| 436 | 328 | ||
| 437 | minor = vfio_alloc_group_minor(group); | 329 | static struct vfio_group * |
| 438 | if (minor < 0) { | 330 | vfio_group_get_from_iommu(struct iommu_group *iommu_group) |
| 439 | vfio_group_unlock_and_free(group); | 331 | { |
| 440 | return ERR_PTR(minor); | 332 | struct vfio_group *group; |
| 441 | } | ||
| 442 | |||
| 443 | dev = device_create(vfio.class, NULL, | ||
| 444 | MKDEV(MAJOR(vfio.group_devt), minor), | ||
| 445 | group, "%s%d", group->noiommu ? "noiommu-" : "", | ||
| 446 | iommu_group_id(iommu_group)); | ||
| 447 | if (IS_ERR(dev)) { | ||
| 448 | vfio_free_group_minor(minor); | ||
| 449 | vfio_group_unlock_and_free(group); | ||
| 450 | return ERR_CAST(dev); | ||
| 451 | } | ||
| 452 | |||
| 453 | group->minor = minor; | ||
| 454 | group->dev = dev; | ||
| 455 | |||
| 456 | list_add(&group->vfio_next, &vfio.group_list); | ||
| 457 | 333 | ||
| 334 | mutex_lock(&vfio.group_lock); | ||
| 335 | group = __vfio_group_get_from_iommu(iommu_group); | ||
| 458 | mutex_unlock(&vfio.group_lock); | 336 | mutex_unlock(&vfio.group_lock); |
| 459 | |||
| 460 | return group; | 337 | return group; |
| 461 | } | 338 | } |
| 462 | 339 | ||
| 463 | /* called with vfio.group_lock held */ | 340 | static void vfio_group_release(struct device *dev) |
| 464 | static void vfio_group_release(struct kref *kref) | ||
| 465 | { | 341 | { |
| 466 | struct vfio_group *group = container_of(kref, struct vfio_group, kref); | 342 | struct vfio_group *group = container_of(dev, struct vfio_group, dev); |
| 467 | struct vfio_unbound_dev *unbound, *tmp; | 343 | struct vfio_unbound_dev *unbound, *tmp; |
| 468 | struct iommu_group *iommu_group = group->iommu_group; | ||
| 469 | |||
| 470 | WARN_ON(!list_empty(&group->device_list)); | ||
| 471 | WARN_ON(group->notifier.head); | ||
| 472 | 344 | ||
| 473 | list_for_each_entry_safe(unbound, tmp, | 345 | list_for_each_entry_safe(unbound, tmp, |
| 474 | &group->unbound_list, unbound_next) { | 346 | &group->unbound_list, unbound_next) { |
| @@ -476,105 +348,129 @@ static void vfio_group_release(struct kref *kref) · 1 unmodified line | |||
| 476 | kfree(unbound); | 348 | kfree(unbound); |
| 477 | } | 349 | } |
| 478 | 350 | ||
| 479 | device_destroy(vfio.class, MKDEV(MAJOR(vfio.group_devt), group->minor)); | 351 | mutex_destroy(&group->device_lock); |
| 480 | list_del(&group->vfio_next); | 352 | mutex_destroy(&group->unbound_lock); |
| 481 | vfio_free_group_minor(group->minor); | 353 | iommu_group_put(group->iommu_group); |
| 482 | vfio_group_unlock_and_free(group); | 354 | ida_free(&vfio.group_ida, MINOR(group->dev.devt)); |
| 483 | iommu_group_put(iommu_group); | 355 | kfree(group); |
| 484 | } | 356 | } |
| 485 | 357 | ||
| 486 | static void vfio_group_put(struct vfio_group *group) | 358 | static struct vfio_group *vfio_group_alloc(struct iommu_group *iommu_group, |
| 359 | enum vfio_group_type type) | ||
| 487 | { | 360 | { |
| 488 | kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock); | ||
| 489 | } | ||
| 490 | |||
| 491 | struct vfio_group_put_work { | ||
| 492 | struct work_struct work; | ||
| 493 | struct vfio_group *group; | 361 | struct vfio_group *group; |
| 494 | }; | 362 | int minor; |
| 495 | 363 | ||
| 496 | static void vfio_group_put_bg(struct work_struct *work) | 364 | group = kzalloc(sizeof(*group), GFP_KERNEL); |
| 497 | { | 365 | if (!group) |
| 498 | struct vfio_group_put_work *do_work; | 366 | return ERR_PTR(-ENOMEM); |
| 499 | |||
| 500 | do_work = container_of(work, struct vfio_group_put_work, work); | ||
| 501 | 367 | ||
| 502 | vfio_group_put(do_work->group); | 368 | minor = ida_alloc_max(&vfio.group_ida, MINORMASK, GFP_KERNEL); |
| 503 | kfree(do_work); | 369 | if (minor < 0) { |
| 504 | } | 370 | kfree(group); |
| 371 | return ERR_PTR(minor); | ||
| 372 | } | ||
| 505 | 373 | ||
| 506 | static void vfio_group_schedule_put(struct vfio_group *group) | 374 | device_initialize(&group->dev); |
| 507 | { | 375 | group->dev.devt = MKDEV(MAJOR(vfio.group_devt), minor); |
| 508 | struct vfio_group_put_work *do_work; | 376 | group->dev.class = vfio.class; |
| 377 | group->dev.release = vfio_group_release; | ||
| 378 | cdev_init(&group->cdev, &vfio_group_fops); | ||
| 379 | group->cdev.owner = THIS_MODULE; | ||
| 509 | 380 | ||
| 510 | do_work = kmalloc(sizeof(*do_work), GFP_KERNEL); | 381 | refcount_set(&group->users, 1); |
| 511 | if (WARN_ON(!do_work)) | 382 | INIT_LIST_HEAD(&group->device_list); |
| 512 | return; | 383 | mutex_init(&group->device_lock); |
| 384 | INIT_LIST_HEAD(&group->unbound_list); | ||
| 385 | mutex_init(&group->unbound_lock); | ||
| 386 | init_waitqueue_head(&group->container_q); | ||
| 387 | group->iommu_group = iommu_group; | ||
| 388 | /* put in vfio_group_release() */ | ||
| 389 | iommu_group_ref_get(iommu_group); | ||
| 390 | group->type = type; | ||
| 391 | BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier); | ||
| 513 | 392 | ||
| 514 | INIT_WORK(&do_work->work, vfio_group_put_bg); | 393 | return group; |
| 515 | do_work->group = group; | ||
| 516 | schedule_work(&do_work->work); | ||
| 517 | } | 394 | } |
| 518 | 395 | ||
| 519 | /* Assume group_lock or group reference is held */ | 396 | static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group, |
| 520 | static void vfio_group_get(struct vfio_group *group) | 397 | enum vfio_group_type type) |
| 521 | { | 398 | { |
| 522 | kref_get(&group->kref); | 399 | struct vfio_group *group; |
| 523 | } | 400 | struct vfio_group *ret; |
| 401 | int err; | ||
| 524 | 402 | ||
| 525 | /* | 403 | group = vfio_group_alloc(iommu_group, type); |
| 526 | * Not really a try as we will sleep for mutex, but we need to make | 404 | if (IS_ERR(group)) |
| 527 | * sure the group pointer is valid under lock and get a reference. | 405 | return group; |
| 528 | */ | ||
| 529 | static struct vfio_group *vfio_group_try_get(struct vfio_group *group) | ||
| 530 | { | ||
| 531 | struct vfio_group *target = group; | ||
| 532 | 406 | ||
| 533 | mutex_lock(&vfio.group_lock); | 407 | err = dev_set_name(&group->dev, "%s%d", |
| 534 | list_for_each_entry(group, &vfio.group_list, vfio_next) { | 408 | group->type == VFIO_NO_IOMMU ? "noiommu-" : "", |
| 535 | if (group == target) { | 409 | iommu_group_id(iommu_group)); |
| 536 | vfio_group_get(group); | 410 | if (err) { |
| 537 | mutex_unlock(&vfio.group_lock); | 411 | ret = ERR_PTR(err); |
| 538 | return group; | 412 | goto err_put; |
| 539 | } | ||
| 540 | } | 413 | } |
| 541 | mutex_unlock(&vfio.group_lock); | ||
| 542 | 414 | ||
| 543 | return NULL; | 415 | group->nb.notifier_call = vfio_iommu_group_notifier; |
| 544 | } | 416 | err = iommu_group_register_notifier(iommu_group, &group->nb); |
| 545 | 417 | if (err) { | |
| 546 | static | 418 | ret = ERR_PTR(err); |
| 547 | struct vfio_group *vfio_group_get_from_iommu(struct iommu_group *iommu_group) | 419 | goto err_put; |
| 548 | { | 420 | } |
| 549 | struct vfio_group *group; | ||
| 550 | 421 | ||
| 551 | mutex_lock(&vfio.group_lock); | 422 | mutex_lock(&vfio.group_lock); |
| 552 | list_for_each_entry(group, &vfio.group_list, vfio_next) { | 423 | |
| 553 | if (group->iommu_group == iommu_group) { | 424 | /* Did we race creating this group? */ |
| 554 | vfio_group_get(group); | 425 | ret = __vfio_group_get_from_iommu(iommu_group); |
| 555 | mutex_unlock(&vfio.group_lock); | 426 | if (ret) |
| 556 | return group; | 427 | goto err_unlock; |
| 557 | } | 428 | |
| 429 | err = cdev_device_add(&group->cdev, &group->dev); | ||
| 430 | if (err) { | ||
| 431 | ret = ERR_PTR(err); | ||
| 432 | goto err_unlock; | ||
| 558 | } | 433 | } |
| 434 | |||
| 435 | list_add(&group->vfio_next, &vfio.group_list); | ||
| 436 | |||
| 559 | mutex_unlock(&vfio.group_lock); | 437 | mutex_unlock(&vfio.group_lock); |
| 438 | return group; | ||
| 560 | 439 | ||
| 561 | return NULL; | 440 | err_unlock: |
| 441 | mutex_unlock(&vfio.group_lock); | ||
| 442 | iommu_group_unregister_notifier(group->iommu_group, &group->nb); | ||
| 443 | err_put: | ||
| 444 | put_device(&group->dev); | ||
| 445 | return ret; | ||
| 562 | } | 446 | } |
| 563 | 447 | ||
| 564 | static struct vfio_group *vfio_group_get_from_minor(int minor) | 448 | static void vfio_group_put(struct vfio_group *group) |
| 565 | { | 449 | { |
| 566 | struct vfio_group *group; | 450 | if (!refcount_dec_and_mutex_lock(&group->users, &vfio.group_lock)) |
| 451 | return; | ||
| 567 | 452 | ||
| 568 | mutex_lock(&vfio.group_lock); | 453 | /* |
| 569 | group = idr_find(&vfio.group_idr, minor); | 454 | * These data structures all have paired operations that can only be |
| 570 | if (!group) { | 455 | * undone when the caller holds a live reference on the group. Since all |
| 571 | mutex_unlock(&vfio.group_lock); | 456 | * pairs must be undone these WARN_ON's indicate some caller did not |
| 572 | return NULL; | 457 | * properly hold the group reference. |
| 573 | } | 458 | */ |
| 574 | vfio_group_get(group); | 459 | WARN_ON(!list_empty(&group->device_list)); |
| 460 | WARN_ON(atomic_read(&group->container_users)); | ||
| 461 | WARN_ON(group->notifier.head); | ||
| 462 | |||
| 463 | list_del(&group->vfio_next); | ||
| 464 | cdev_device_del(&group->cdev, &group->dev); | ||
| 575 | mutex_unlock(&vfio.group_lock); | 465 | mutex_unlock(&vfio.group_lock); |
| 576 | 466 | ||
| 577 | return group; | 467 | iommu_group_unregister_notifier(group->iommu_group, &group->nb); |
| 468 | put_device(&group->dev); | ||
| 469 | } | ||
| 470 | |||
| 471 | static void vfio_group_get(struct vfio_group *group) | ||
| 472 | { | ||
| 473 | refcount_inc(&group->users); | ||
| 578 | } | 474 | } |
| 579 | 475 | ||
| 580 | static struct vfio_group *vfio_group_get_from_dev(struct device *dev) | 476 | static struct vfio_group *vfio_group_get_from_dev(struct device *dev) |
| @@ -740,14 +636,6 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, · 159 unmodified lines | |||
| 740 | struct device *dev = data; | 636 | struct device *dev = data; |
| 741 | struct vfio_unbound_dev *unbound; | 637 | struct vfio_unbound_dev *unbound; |
| 742 | 638 | ||
| 743 | /* | ||
| 744 | * Need to go through a group_lock lookup to get a reference or we | ||
| 745 | * risk racing a group being removed. Ignore spurious notifies. | ||
| 746 | */ | ||
| 747 | group = vfio_group_try_get(group); | ||
| 748 | if (!group) | ||
| 749 | return NOTIFY_OK; | ||
| 750 | |||
| 751 | switch (action) { | 639 | switch (action) { |
| 752 | case IOMMU_GROUP_NOTIFY_ADD_DEVICE: | 640 | case IOMMU_GROUP_NOTIFY_ADD_DEVICE: |
| 753 | vfio_group_nb_add_dev(group, dev); | 641 | vfio_group_nb_add_dev(group, dev); |
| @@ -798,15 +686,6 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, · 44 unmodified lines | |||
| 798 | mutex_unlock(&group->unbound_lock); | 686 | mutex_unlock(&group->unbound_lock); |
| 799 | break; | 687 | break; |
| 800 | } | 688 | } |
| 801 | |||
| 802 | /* | ||
| 803 | * If we're the last reference to the group, the group will be | ||
| 804 | * released, which includes unregistering the iommu group notifier. | ||
| 805 | * We hold a read-lock on that notifier list, unregistering needs | ||
| 806 | * a write-lock... deadlock. Release our reference asynchronously | ||
| 807 | * to avoid that situation. | ||
| 808 | */ | ||
| 809 | vfio_group_schedule_put(group); | ||
| 810 | return NOTIFY_OK; | 689 | return NOTIFY_OK; |
| 811 | } | 690 | } |
| 812 | 691 | ||
| @@ -828,11 +707,78 @@ void vfio_uninit_group_dev(struct vfio_device *device) · 15 unmodified lines | |||
| 828 | } | 707 | } |
| 829 | EXPORT_SYMBOL_GPL(vfio_uninit_group_dev); | 708 | EXPORT_SYMBOL_GPL(vfio_uninit_group_dev); |
| 830 | 709 | ||
| 831 | int vfio_register_group_dev(struct vfio_device *device) | 710 | static struct vfio_group *vfio_noiommu_group_alloc(struct device *dev, |
| 711 | enum vfio_group_type type) | ||
| 832 | { | 712 | { |
| 833 | struct vfio_device *existing_device; | ||
| 834 | struct iommu_group *iommu_group; | 713 | struct iommu_group *iommu_group; |
| 835 | struct vfio_group *group; | 714 | struct vfio_group *group; |
| 715 | int ret; | ||
| 716 | |||
| 717 | iommu_group = iommu_group_alloc(); | ||
| 718 | if (IS_ERR(iommu_group)) | ||
| 719 | return ERR_CAST(iommu_group); | ||
| 720 | |||
| 721 | iommu_group_set_name(iommu_group, "vfio-noiommu"); | ||
| 722 | ret = iommu_group_add_device(iommu_group, dev); | ||
| 723 | if (ret) | ||
| 724 | goto out_put_group; | ||
| 725 | |||
| 726 | group = vfio_create_group(iommu_group, type); | ||
| 727 | if (IS_ERR(group)) { | ||
| 728 | ret = PTR_ERR(group); | ||
| 729 | goto out_remove_device; | ||
| 730 | } | ||
| 731 | iommu_group_put(iommu_group); | ||
| 732 | return group; | ||
| 733 | |||
| 734 | out_remove_device: | ||
| 735 | iommu_group_remove_device(dev); | ||
| 736 | out_put_group: | ||
| 737 | iommu_group_put(iommu_group); | ||
| 738 | return ERR_PTR(ret); | ||
| 739 | } | ||
| 740 | |||
| 741 | static struct vfio_group *vfio_group_find_or_alloc(struct device *dev) | ||
| 742 | { | ||
| 743 | struct iommu_group *iommu_group; | ||
| 744 | struct vfio_group *group; | ||
| 745 | |||
| 746 | iommu_group = iommu_group_get(dev); | ||
| 747 | #ifdef CONFIG_VFIO_NOIOMMU | ||
| 748 | if (!iommu_group && noiommu && !iommu_present(dev->bus)) { | ||
| 749 | /* | ||
| 750 | * With noiommu enabled, create an IOMMU group for devices that | ||
| 751 | * don't already have one and don't have an iommu_ops on their | ||
| 752 | * bus. Taint the kernel because we're about to give a DMA | ||
| 753 | * capable device to a user without IOMMU protection. | ||
| 754 | */ | ||
| 755 | group = vfio_noiommu_group_alloc(dev, VFIO_NO_IOMMU); | ||
| 756 | if (!IS_ERR(group)) { | ||
| 757 | add_taint(TAINT_USER, LOCKDEP_STILL_OK); | ||
| 758 | dev_warn(dev, "Adding kernel taint for vfio-noiommu group on device\n"); | ||
| 759 | } | ||
| 760 | return group; | ||
| 761 | } | ||
| 762 | #endif | ||
| 763 | if (!iommu_group) | ||
| 764 | return ERR_PTR(-EINVAL); | ||
| 765 | |||
| 766 | group = vfio_group_get_from_iommu(iommu_group); | ||
| 767 | if (!group) | ||
| 768 | group = vfio_create_group(iommu_group, VFIO_IOMMU); | ||
| 769 | |||
| 770 | /* The vfio_group holds a reference to the iommu_group */ | ||
| 771 | iommu_group_put(iommu_group); | ||
| 772 | return group; | ||
| 773 | } | ||
| 774 | |||
| 775 | static int __vfio_register_dev(struct vfio_device *device, | ||
| 776 | struct vfio_group *group) | ||
| 777 | { | ||
| 778 | struct vfio_device *existing_device; | ||
| 779 | |||
| 780 | if (IS_ERR(group)) | ||
| 781 | return PTR_ERR(group); | ||
| 836 | 782 | ||
| 837 | /* | 783 | /* |
| 838 | * If the driver doesn't specify a set then the device is added to a | 784 | * If the driver doesn't specify a set then the device is added to a |
| @@ -841,30 +787,14 @@ int vfio_register_group_dev(struct vfio_device *device) · 2 unmodified lines | |||
| 841 | if (!device->dev_set) | 787 | if (!device->dev_set) |
| 842 | vfio_assign_device_set(device, device); | 788 | vfio_assign_device_set(device, device); |
| 843 | 789 | ||
| 844 | iommu_group = iommu_group_get(device->dev); | ||
| 845 | if (!iommu_group) | ||
| 846 | return -EINVAL; | ||
| 847 | |||
| 848 | group = vfio_group_get_from_iommu(iommu_group); | ||
| 849 | if (!group) { | ||
| 850 | group = vfio_create_group(iommu_group); | ||
| 851 | if (IS_ERR(group)) { | ||
| 852 | iommu_group_put(iommu_group); | ||
| 853 | return PTR_ERR(group); | ||
| 854 | } | ||
| 855 | } else { | ||
| 856 | /* | ||
| 857 | * A found vfio_group already holds a reference to the | ||
| 858 | * iommu_group. A created vfio_group keeps the reference. | ||
| 859 | */ | ||
| 860 | iommu_group_put(iommu_group); | ||
| 861 | } | ||
| 862 | |||
| 863 | existing_device = vfio_group_get_device(group, device->dev); | 790 | existing_device = vfio_group_get_device(group, device->dev); |
| 864 | if (existing_device) { | 791 | if (existing_device) { |
| 865 | dev_WARN(device->dev, "Device already exists on group %d\n", | 792 | dev_WARN(device->dev, "Device already exists on group %d\n", |
| 866 | iommu_group_id(iommu_group)); | 793 | iommu_group_id(group->iommu_group)); |
| 867 | vfio_device_put(existing_device); | 794 | vfio_device_put(existing_device); |
| 795 | if (group->type == VFIO_NO_IOMMU || | ||
| 796 | group->type == VFIO_EMULATED_IOMMU) | ||
| 797 | iommu_group_remove_device(device->dev); | ||
| 868 | vfio_group_put(group); | 798 | vfio_group_put(group); |
| 869 | return -EBUSY; | 799 | return -EBUSY; |
| 870 | } | 800 | } |
| @@ -882,8 +812,25 @@ int vfio_register_group_dev(struct vfio_device *device) · 11 unmodified lines | |||
| 882 | 812 | ||
| 883 | return 0; | 813 | return 0; |
| 884 | } | 814 | } |
| 815 | |||
| 816 | int vfio_register_group_dev(struct vfio_device *device) | ||
| 817 | { | ||
| 818 | return __vfio_register_dev(device, | ||
| 819 | vfio_group_find_or_alloc(device->dev)); | ||
| 820 | } | ||
| 885 | EXPORT_SYMBOL_GPL(vfio_register_group_dev); | 821 | EXPORT_SYMBOL_GPL(vfio_register_group_dev); |
| 886 | 822 | ||
| 823 | /* | ||
| 824 | * Register a virtual device without IOMMU backing. The user of this | ||
| 825 | * device must not be able to directly trigger unmediated DMA. | ||
| 826 | */ | ||
| 827 | int vfio_register_emulated_iommu_dev(struct vfio_device *device) | ||
| 828 | { | ||
| 829 | return __vfio_register_dev(device, | ||
| 830 | vfio_noiommu_group_alloc(device->dev, VFIO_EMULATED_IOMMU)); | ||
| 831 | } | ||
| 832 | EXPORT_SYMBOL_GPL(vfio_register_emulated_iommu_dev); | ||
| 833 | |||
| 887 | /** | 834 | /** |
| 888 | * Get a reference to the vfio_device for a device. Even if the | 835 | * Get a reference to the vfio_device for a device. Even if the |
| 889 | * caller thinks they own the device, they could be racing with a | 836 | * caller thinks they own the device, they could be racing with a |
| @@ -1010,6 +957,9 @@ void vfio_unregister_group_dev(struct vfio_device *device) · 120 unmodified lines | |||
| 1010 | if (list_empty(&group->device_list)) | 957 | if (list_empty(&group->device_list)) |
| 1011 | wait_event(group->container_q, !group->container); | 958 | wait_event(group->container_q, !group->container); |
| 1012 | 959 | ||
| 960 | if (group->type == VFIO_NO_IOMMU || group->type == VFIO_EMULATED_IOMMU) | ||
| 961 | iommu_group_remove_device(device->dev); | ||
| 962 | |||
| 1013 | /* Matches the get in vfio_register_group_dev() */ | 963 | /* Matches the get in vfio_register_group_dev() */ |
| 1014 | vfio_group_put(group); | 964 | vfio_group_put(group); |
| 1015 | } | 965 | } |
| @@ -1042,13 +992,10 @@ static long vfio_ioctl_check_extension(struct vfio_container *container, · 26 unmodified lines | |||
| 1042 | list_for_each_entry(driver, &vfio.iommu_drivers_list, | 992 | list_for_each_entry(driver, &vfio.iommu_drivers_list, |
| 1043 | vfio_next) { | 993 | vfio_next) { |
| 1044 | 994 | ||
| 1045 | #ifdef CONFIG_VFIO_NOIOMMU | ||
| 1046 | if (!list_empty(&container->group_list) && | 995 | if (!list_empty(&container->group_list) && |
| 1047 | (container->noiommu != | 996 | !vfio_iommu_driver_allowed(container, |
| 1048 | (driver->ops == &vfio_noiommu_ops))) | 997 | driver)) |
| 1049 | continue; | 998 | continue; |
| 1050 | #endif | ||
| 1051 | |||
| 1052 | if (!try_module_get(driver->ops->owner)) | 999 | if (!try_module_get(driver->ops->owner)) |
| 1053 | continue; | 1000 | continue; |
| 1054 | 1001 | ||
| @@ -1079,7 +1026,8 @@ static int __vfio_container_attach_groups(struct vfio_container *container, · 24 unmodified lines | |||
| 1079 | int ret = -ENODEV; | 1026 | int ret = -ENODEV; |
| 1080 | 1027 | ||
| 1081 | list_for_each_entry(group, &container->group_list, container_next) { | 1028 | list_for_each_entry(group, &container->group_list, container_next) { |
| 1082 | ret = driver->ops->attach_group(data, group->iommu_group); | 1029 | ret = driver->ops->attach_group(data, group->iommu_group, |
| 1030 | group->type); | ||
| 1083 | if (ret) | 1031 | if (ret) |
| 1084 | goto unwind; | 1032 | goto unwind; |
| 1085 | } | 1033 | } |
| @@ -1120,15 +1068,8 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container, · 34 unmodified lines | |||
| 1120 | list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) { | 1068 | list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) { |
| 1121 | void *data; | 1069 | void *data; |
| 1122 | 1070 | ||
| 1123 | #ifdef CONFIG_VFIO_NOIOMMU | 1071 | if (!vfio_iommu_driver_allowed(container, driver)) |
| 1124 | /* | ||
| 1125 | * Only noiommu containers can use vfio-noiommu and noiommu | ||
| 1126 | * containers can only use vfio-noiommu. | ||
| 1127 | */ | ||
| 1128 | if (container->noiommu != (driver->ops == &vfio_noiommu_ops)) | ||
| 1129 | continue; | 1072 | continue; |
| 1130 | #endif | ||
| 1131 | |||
| 1132 | if (!try_module_get(driver->ops->owner)) | 1073 | if (!try_module_get(driver->ops->owner)) |
| 1133 | continue; | 1074 | continue; |
| 1134 | 1075 | ||
| @@ -1234,62 +1175,12 @@ static int vfio_fops_release(struct inode *inode, struct file *filep) · 99 unmodified lines | |||
| 1234 | return 0; | 1175 | return 0; |
| 1235 | } | 1176 | } |
| 1236 | 1177 | ||
| 1237 | /* | ||
| 1238 | * Once an iommu driver is set, we optionally pass read/write/mmap | ||
| 1239 | * on to the driver, allowing management interfaces beyond ioctl. | ||
| 1240 | */ | ||
| 1241 | static ssize_t vfio_fops_read(struct file *filep, char __user *buf, | ||
| 1242 | size_t count, loff_t *ppos) | ||
| 1243 | { | ||
| 1244 | struct vfio_container *container = filep->private_data; | ||
| 1245 | struct vfio_iommu_driver *driver; | ||
| 1246 | ssize_t ret = -EINVAL; | ||
| 1247 | |||
| 1248 | driver = container->iommu_driver; | ||
| 1249 | if (likely(driver && driver->ops->read)) | ||
| 1250 | ret = driver->ops->read(container->iommu_data, | ||
| 1251 | buf, count, ppos); | ||
| 1252 | |||
| 1253 | return ret; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | static ssize_t vfio_fops_write(struct file *filep, const char __user *buf, | ||
| 1257 | size_t count, loff_t *ppos) | ||
| 1258 | { | ||
| 1259 | struct vfio_container *container = filep->private_data; | ||
| 1260 | struct vfio_iommu_driver *driver; | ||
| 1261 | ssize_t ret = -EINVAL; | ||
| 1262 | |||
| 1263 | driver = container->iommu_driver; | ||
| 1264 | if (likely(driver && driver->ops->write)) | ||
| 1265 | ret = driver->ops->write(container->iommu_data, | ||
| 1266 | buf, count, ppos); | ||
| 1267 | |||
| 1268 | return ret; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | static int vfio_fops_mmap(struct file *filep, struct vm_area_struct *vma) | ||
| 1272 | { | ||
| 1273 | struct vfio_container *container = filep->private_data; | ||
| 1274 | struct vfio_iommu_driver *driver; | ||
| 1275 | int ret = -EINVAL; | ||
| 1276 | |||
| 1277 | driver = container->iommu_driver; | ||
| 1278 | if (likely(driver && driver->ops->mmap)) | ||
| 1279 | ret = driver->ops->mmap(container->iommu_data, vma); | ||
| 1280 | |||
| 1281 | return ret; | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | static const struct file_operations vfio_fops = { | 1178 | static const struct file_operations vfio_fops = { |
| 1285 | .owner = THIS_MODULE, | 1179 | .owner = THIS_MODULE, |
| 1286 | .open = vfio_fops_open, | 1180 | .open = vfio_fops_open, |
| 1287 | .release = vfio_fops_release, | 1181 | .release = vfio_fops_release, |
| 1288 | .read = vfio_fops_read, | ||
| 1289 | .write = vfio_fops_write, | ||
| 1290 | .unlocked_ioctl = vfio_fops_unl_ioctl, | 1182 | .unlocked_ioctl = vfio_fops_unl_ioctl, |
| 1291 | .compat_ioctl = compat_ptr_ioctl, | 1183 | .compat_ioctl = compat_ptr_ioctl, |
| 1292 | .mmap = vfio_fops_mmap, | ||
| 1293 | }; | 1184 | }; |
| 1294 | 1185 | ||
| 1295 | /** | 1186 | /** |
| @@ -1366,7 +1257,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd) · 70 unmodified lines | |||
| 1366 | if (atomic_read(&group->container_users)) | 1257 | if (atomic_read(&group->container_users)) |
| 1367 | return -EINVAL; | 1258 | return -EINVAL; |
| 1368 | 1259 | ||
| 1369 | if (group->noiommu && !capable(CAP_SYS_RAWIO)) | 1260 | if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) |
| 1370 | return -EPERM; | 1261 | return -EPERM; |
| 1371 | 1262 | ||
| 1372 | f = fdget(container_fd); | 1263 | f = fdget(container_fd); |
| @@ -1386,7 +1277,7 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd) · 13 unmodified lines | |||
| 1386 | 1277 | ||
| 1387 | /* Real groups and fake groups cannot mix */ | 1278 | /* Real groups and fake groups cannot mix */ |
| 1388 | if (!list_empty(&container->group_list) && | 1279 | if (!list_empty(&container->group_list) && |
| 1389 | container->noiommu != group->noiommu) { | 1280 | container->noiommu != (group->type == VFIO_NO_IOMMU)) { |
| 1390 | ret = -EPERM; | 1281 | ret = -EPERM; |
| 1391 | goto unlock_out; | 1282 | goto unlock_out; |
| 1392 | } | 1283 | } |
| @@ -1394,13 +1285,14 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd) · 1 unmodified line | |||
| 1394 | driver = container->iommu_driver; | 1285 | driver = container->iommu_driver; |
| 1395 | if (driver) { | 1286 | if (driver) { |
| 1396 | ret = driver->ops->attach_group(container->iommu_data, | 1287 | ret = driver->ops->attach_group(container->iommu_data, |
| 1397 | group->iommu_group); | 1288 | group->iommu_group, |
| 1289 | group->type); | ||
| 1398 | if (ret) | 1290 | if (ret) |
| 1399 | goto unlock_out; | 1291 | goto unlock_out; |
| 1400 | } | 1292 | } |
| 1401 | 1293 | ||
| 1402 | group->container = container; | 1294 | group->container = container; |
| 1403 | container->noiommu = group->noiommu; | 1295 | container->noiommu = (group->type == VFIO_NO_IOMMU); |
| 1404 | list_add(&group->container_next, &container->group_list); | 1296 | list_add(&group->container_next, &container->group_list); |
| 1405 | 1297 | ||
| 1406 | /* Get a reference on the container and mark a user within the group */ | 1298 | /* Get a reference on the container and mark a user within the group */ |
| @@ -1424,7 +1316,7 @@ static int vfio_group_add_container_user(struct vfio_group *group) · 17 unmodified lines | |||
| 1424 | if (!atomic_inc_not_zero(&group->container_users)) | 1316 | if (!atomic_inc_not_zero(&group->container_users)) |
| 1425 | return -EINVAL; | 1317 | return -EINVAL; |
| 1426 | 1318 | ||
| 1427 | if (group->noiommu) { | 1319 | if (group->type == VFIO_NO_IOMMU) { |
| 1428 | atomic_dec(&group->container_users); | 1320 | atomic_dec(&group->container_users); |
| 1429 | return -EPERM; | 1321 | return -EPERM; |
| 1430 | } | 1322 | } |
| @@ -1449,7 +1341,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) · 18 unmodified lines | |||
| 1449 | !group->container->iommu_driver || !vfio_group_viable(group)) | 1341 | !group->container->iommu_driver || !vfio_group_viable(group)) |
| 1450 | return -EINVAL; | 1342 | return -EINVAL; |
| 1451 | 1343 | ||
| 1452 | if (group->noiommu && !capable(CAP_SYS_RAWIO)) | 1344 | if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) |
| 1453 | return -EPERM; | 1345 | return -EPERM; |
| 1454 | 1346 | ||
| 1455 | device = vfio_device_get_from_name(group, buf); | 1347 | device = vfio_device_get_from_name(group, buf); |
| @@ -1496,7 +1388,7 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) · 40 unmodified lines | |||
| 1496 | 1388 | ||
| 1497 | fd_install(fdno, filep); | 1389 | fd_install(fdno, filep); |
| 1498 | 1390 | ||
| 1499 | if (group->noiommu) | 1391 | if (group->type == VFIO_NO_IOMMU) |
| 1500 | dev_warn(device->dev, "vfio-noiommu device opened by user " | 1392 | dev_warn(device->dev, "vfio-noiommu device opened by user " |
| 1501 | "(%s:%d)\n", current->comm, task_pid_nr(current)); | 1393 | "(%s:%d)\n", current->comm, task_pid_nr(current)); |
| 1502 | return fdno; | 1394 | return fdno; |
| @@ -1585,14 +1477,15 @@ static long vfio_group_fops_unl_ioctl(struct file *filep, · 82 unmodified lines | |||
| 1585 | 1477 | ||
| 1586 | static int vfio_group_fops_open(struct inode *inode, struct file *filep) | 1478 | static int vfio_group_fops_open(struct inode *inode, struct file *filep) |
| 1587 | { | 1479 | { |
| 1588 | struct vfio_group *group; | 1480 | struct vfio_group *group = |
| 1481 | container_of(inode->i_cdev, struct vfio_group, cdev); | ||
| 1589 | int opened; | 1482 | int opened; |
| 1590 | 1483 | ||
| 1591 | group = vfio_group_get_from_minor(iminor(inode)); | 1484 | /* users can be zero if this races with vfio_group_put() */ |
| 1592 | if (!group) | 1485 | if (!refcount_inc_not_zero(&group->users)) |
| 1593 | return -ENODEV; | 1486 | return -ENODEV; |
| 1594 | 1487 | ||
| 1595 | if (group->noiommu && !capable(CAP_SYS_RAWIO)) { | 1488 | if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) { |
| 1596 | vfio_group_put(group); | 1489 | vfio_group_put(group); |
| 1597 | return -EPERM; | 1490 | return -EPERM; |
| 1598 | } | 1491 | } |
| @@ -1757,6 +1650,9 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep) · 158 unmodified lines | |||
| 1757 | if (ret) | 1650 | if (ret) |
| 1758 | return ERR_PTR(ret); | 1651 | return ERR_PTR(ret); |
| 1759 | 1652 | ||
| 1653 | /* | ||
| 1654 | * Since the caller holds the fget on the file group->users must be >= 1 | ||
| 1655 | */ | ||
| 1760 | vfio_group_get(group); | 1656 | vfio_group_get(group); |
| 1761 | 1657 | ||
| 1762 | return group; | 1658 | return group; |
| @@ -2396,7 +2292,7 @@ static int __init vfio_init(void) · 633 unmodified lines | |||
| 2396 | { | 2292 | { |
| 2397 | int ret; | 2293 | int ret; |
| 2398 | 2294 | ||
| 2399 | idr_init(&vfio.group_idr); | 2295 | ida_init(&vfio.group_ida); |
| 2400 | mutex_init(&vfio.group_lock); | 2296 | mutex_init(&vfio.group_lock); |
| 2401 | mutex_init(&vfio.iommu_drivers_lock); | 2297 | mutex_init(&vfio.iommu_drivers_lock); |
| 2402 | INIT_LIST_HEAD(&vfio.group_list); | 2298 | INIT_LIST_HEAD(&vfio.group_list); |
| @@ -2421,11 +2317,6 @@ static int __init vfio_init(void) · 18 unmodified lines | |||
| 2421 | if (ret) | 2317 | if (ret) |
| 2422 | goto err_alloc_chrdev; | 2318 | goto err_alloc_chrdev; |
| 2423 | 2319 | ||
| 2424 | cdev_init(&vfio.group_cdev, &vfio_group_fops); | ||
| 2425 | ret = cdev_add(&vfio.group_cdev, vfio.group_devt, MINORMASK + 1); | ||
| 2426 | if (ret) | ||
| 2427 | goto err_cdev_add; | ||
| 2428 | |||
| 2429 | pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 2320 | pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
| 2430 | 2321 | ||
| 2431 | #ifdef CONFIG_VFIO_NOIOMMU | 2322 | #ifdef CONFIG_VFIO_NOIOMMU |
| @@ -2433,8 +2324,6 @@ static int __init vfio_init(void) · 1 unmodified line | |||
| 2433 | #endif | 2324 | #endif |
| 2434 | return 0; | 2325 | return 0; |
| 2435 | 2326 | ||
| 2436 | err_cdev_add: | ||
| 2437 | unregister_chrdev_region(vfio.group_devt, MINORMASK + 1); | ||
| 2438 | err_alloc_chrdev: | 2327 | err_alloc_chrdev: |
| 2439 | class_destroy(vfio.class); | 2328 | class_destroy(vfio.class); |
| 2440 | vfio.class = NULL; | 2329 | vfio.class = NULL; |
| @@ -2450,8 +2339,7 @@ static void __exit vfio_cleanup(void) · 9 unmodified lines | |||
| 2450 | #ifdef CONFIG_VFIO_NOIOMMU | 2339 | #ifdef CONFIG_VFIO_NOIOMMU |
| 2451 | vfio_unregister_iommu_driver(&vfio_noiommu_ops); | 2340 | vfio_unregister_iommu_driver(&vfio_noiommu_ops); |
| 2452 | #endif | 2341 | #endif |
| 2453 | idr_destroy(&vfio.group_idr); | 2342 | ida_destroy(&vfio.group_ida); |
| 2454 | cdev_del(&vfio.group_cdev); | ||
| 2455 | unregister_chrdev_region(vfio.group_devt, MINORMASK + 1); | 2343 | unregister_chrdev_region(vfio.group_devt, MINORMASK + 1); |
| 2456 | class_destroy(vfio.class); | 2344 | class_destroy(vfio.class); |
| 2457 | vfio.class = NULL; | 2345 | vfio.class = NULL; |
| @@ -0,0 +1,72 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2012 Red Hat, Inc. All rights reserved. | ||
| 4 | * Author: Alex Williamson <alex.williamson@redhat.com> | ||
| 5 | */ | ||
| 6 | |||
| 7 | enum vfio_group_type { | ||
| 8 | /* | ||
| 9 | * Physical device with IOMMU backing. | ||
| 10 | */ | ||
| 11 | VFIO_IOMMU, | ||
| 12 | |||
| 13 | /* | ||
| 14 | * Virtual device without IOMMU backing. The VFIO core fakes up an | ||
| 15 | * iommu_group as the iommu_group sysfs interface is part of the | ||
| 16 | * userspace ABI. The user of these devices must not be able to | ||
| 17 | * directly trigger unmediated DMA. | ||
| 18 | */ | ||
| 19 | VFIO_EMULATED_IOMMU, | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Physical device without IOMMU backing. The VFIO core fakes up an | ||
| 23 | * iommu_group as the iommu_group sysfs interface is part of the | ||
| 24 | * userspace ABI. Users can trigger unmediated DMA by the device, | ||
| 25 | * usage is highly dangerous, requires an explicit opt-in and will | ||
| 26 | * taint the kernel. | ||
| 27 | */ | ||
| 28 | VFIO_NO_IOMMU, | ||
| 29 | }; | ||
| 30 | |||
| 31 | /* events for the backend driver notify callback */ | ||
| 32 | enum vfio_iommu_notify_type { | ||
| 33 | VFIO_IOMMU_CONTAINER_CLOSE = 0, | ||
| 34 | }; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks | ||
| 38 | */ | ||
| 39 | struct vfio_iommu_driver_ops { | ||
| 40 | char *name; | ||
| 41 | struct module *owner; | ||
| 42 | void *(*open)(unsigned long arg); | ||
| 43 | void (*release)(void *iommu_data); | ||
| 44 | long (*ioctl)(void *iommu_data, unsigned int cmd, | ||
| 45 | unsigned long arg); | ||
| 46 | int (*attach_group)(void *iommu_data, | ||
| 47 | struct iommu_group *group, | ||
| 48 | enum vfio_group_type); | ||
| 49 | void (*detach_group)(void *iommu_data, | ||
| 50 | struct iommu_group *group); | ||
| 51 | int (*pin_pages)(void *iommu_data, | ||
| 52 | struct iommu_group *group, | ||
| 53 | unsigned long *user_pfn, | ||
| 54 | int npage, int prot, | ||
| 55 | unsigned long *phys_pfn); | ||
| 56 | int (*unpin_pages)(void *iommu_data, | ||
| 57 | unsigned long *user_pfn, int npage); | ||
| 58 | int (*register_notifier)(void *iommu_data, | ||
| 59 | unsigned long *events, | ||
| 60 | struct notifier_block *nb); | ||
| 61 | int (*unregister_notifier)(void *iommu_data, | ||
| 62 | struct notifier_block *nb); | ||
| 63 | int (*dma_rw)(void *iommu_data, dma_addr_t user_iova, | ||
| 64 | void *data, size_t count, bool write); | ||
| 65 | struct iommu_domain *(*group_iommu_domain)(void *iommu_data, | ||
| 66 | struct iommu_group *group); | ||
| 67 | void (*notify)(void *iommu_data, | ||
| 68 | enum vfio_iommu_notify_type event); | ||
| 69 | }; | ||
| 70 | |||
| 71 | int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops); | ||
| 72 | void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops); | ||
| @@ -20,6 +20,7 @@ · 19 unmodified lines | |||
| 20 | #include <linux/sched/mm.h> | 20 | #include <linux/sched/mm.h> |
| 21 | #include <linux/sched/signal.h> | 21 | #include <linux/sched/signal.h> |
| 22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
| 23 | #include "vfio.h" | ||
| 23 | 24 | ||
| 24 | #include <asm/iommu.h> | 25 | #include <asm/iommu.h> |
| 25 | #include <asm/tce.h> | 26 | #include <asm/tce.h> |
| @@ -1238,13 +1239,16 @@ release_exit: · 1212 unmodified lines | |||
| 1238 | } | 1239 | } |
| 1239 | 1240 | ||
| 1240 | static int tce_iommu_attach_group(void *iommu_data, | 1241 | static int tce_iommu_attach_group(void *iommu_data, |
| 1241 | struct iommu_group *iommu_group) | 1242 | struct iommu_group *iommu_group, enum vfio_group_type type) |
| 1242 | { | 1243 | { |
| 1243 | int ret = 0; | 1244 | int ret = 0; |
| 1244 | struct tce_container *container = iommu_data; | 1245 | struct tce_container *container = iommu_data; |
| 1245 | struct iommu_table_group *table_group; | 1246 | struct iommu_table_group *table_group; |
| 1246 | struct tce_iommu_group *tcegrp = NULL; | 1247 | struct tce_iommu_group *tcegrp = NULL; |
| 1247 | 1248 | ||
| 1249 | if (type == VFIO_EMULATED_IOMMU) | ||
| 1250 | return -EINVAL; | ||
| 1251 | |||
| 1248 | mutex_lock(&container->lock); | 1252 | mutex_lock(&container->lock); |
| 1249 | 1253 | ||
| 1250 | /* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n", | 1254 | /* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n", |
| @@ -36,10 +36,10 @@ · 35 unmodified lines | |||
| 36 | #include <linux/uaccess.h> | 36 | #include <linux/uaccess.h> |
| 37 | #include <linux/vfio.h> | 37 | #include <linux/vfio.h> |
| 38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
| 39 | #include <linux/mdev.h> | ||
| 40 | #include <linux/notifier.h> | 39 | #include <linux/notifier.h> |
| 41 | #include <linux/dma-iommu.h> | 40 | #include <linux/dma-iommu.h> |
| 42 | #include <linux/irqdomain.h> | 41 | #include <linux/irqdomain.h> |
| 42 | #include "vfio.h" | ||
| 43 | 43 | ||
| 44 | #define DRIVER_VERSION "0.2" | 44 | #define DRIVER_VERSION "0.2" |
| 45 | #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>" | 45 | #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>" |
| @@ -65,7 +65,6 @@ MODULE_PARM_DESC(dma_entry_limit, · 19 unmodified lines | |||
| 65 | struct vfio_iommu { | 65 | struct vfio_iommu { |
| 66 | struct list_head domain_list; | 66 | struct list_head domain_list; |
| 67 | struct list_head iova_list; | 67 | struct list_head iova_list; |
| 68 | struct vfio_domain *external_domain; /* domain for external user */ | ||
| 69 | struct mutex lock; | 68 | struct mutex lock; |
| 70 | struct rb_root dma_list; | 69 | struct rb_root dma_list; |
| 71 | struct blocking_notifier_head notifier; | 70 | struct blocking_notifier_head notifier; |
| @@ -78,6 +77,7 @@ struct vfio_iommu { · 6 unmodified lines | |||
| 78 | bool nesting; | 77 | bool nesting; |
| 79 | bool dirty_page_tracking; | 78 | bool dirty_page_tracking; |
| 80 | bool container_open; | 79 | bool container_open; |
| 80 | struct list_head emulated_iommu_groups; | ||
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | struct vfio_domain { | 83 | struct vfio_domain { |
| @@ -113,7 +113,6 @@ struct vfio_batch { · 29 unmodified lines | |||
| 113 | struct vfio_iommu_group { | 113 | struct vfio_iommu_group { |
| 114 | struct iommu_group *iommu_group; | 114 | struct iommu_group *iommu_group; |
| 115 | struct list_head next; | 115 | struct list_head next; |
| 116 | bool mdev_group; /* An mdev group */ | ||
| 117 | bool pinned_page_dirty_scope; | 116 | bool pinned_page_dirty_scope; |
| 118 | }; | 117 | }; |
| 119 | 118 | ||
| @@ -140,9 +139,6 @@ struct vfio_regions { · 20 unmodified lines | |||
| 140 | size_t len; | 139 | size_t len; |
| 141 | }; | 140 | }; |
| 142 | 141 | ||
| 143 | #define IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu) \ | ||
| 144 | (!list_empty(&iommu->domain_list)) | ||
| 145 | |||
| 146 | #define DIRTY_BITMAP_BYTES(n) (ALIGN(n, BITS_PER_TYPE(u64)) / BITS_PER_BYTE) | 142 | #define DIRTY_BITMAP_BYTES(n) (ALIGN(n, BITS_PER_TYPE(u64)) / BITS_PER_BYTE) |
| 147 | 143 | ||
| 148 | /* | 144 | /* |
| @@ -880,7 +876,7 @@ again: · 731 unmodified lines | |||
| 880 | * already pinned and accounted. Accounting should be done if there is no | 876 | * already pinned and accounted. Accounting should be done if there is no |
| 881 | * iommu capable domain in the container. | 877 | * iommu capable domain in the container. |
| 882 | */ | 878 | */ |
| 883 | do_accounting = !IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu); | 879 | do_accounting = list_empty(&iommu->domain_list); |
| 884 | 880 | ||
| 885 | for (i = 0; i < npage; i++) { | 881 | for (i = 0; i < npage; i++) { |
| 886 | struct vfio_pfn *vpfn; | 882 | struct vfio_pfn *vpfn; |
| @@ -969,7 +965,7 @@ static int vfio_iommu_type1_unpin_pages(void *iommu_data, · 82 unmodified lines | |||
| 969 | 965 | ||
| 970 | mutex_lock(&iommu->lock); | 966 | mutex_lock(&iommu->lock); |
| 971 | 967 | ||
| 972 | do_accounting = !IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu); | 968 | do_accounting = list_empty(&iommu->domain_list); |
| 973 | for (i = 0; i < npage; i++) { | 969 | for (i = 0; i < npage; i++) { |
| 974 | struct vfio_dma *dma; | 970 | struct vfio_dma *dma; |
| 975 | dma_addr_t iova; | 971 | dma_addr_t iova; |
| @@ -1090,7 +1086,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma, · 114 unmodified lines | |||
| 1090 | if (!dma->size) | 1086 | if (!dma->size) |
| 1091 | return 0; | 1087 | return 0; |
| 1092 | 1088 | ||
| 1093 | if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) | 1089 | if (list_empty(&iommu->domain_list)) |
| 1094 | return 0; | 1090 | return 0; |
| 1095 | 1091 | ||
| 1096 | /* | 1092 | /* |
| @@ -1667,7 +1663,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, · 570 unmodified lines | |||
| 1667 | vfio_link_dma(iommu, dma); | 1663 | vfio_link_dma(iommu, dma); |
| 1668 | 1664 | ||
| 1669 | /* Don't pin and map if container doesn't contain IOMMU capable domain*/ | 1665 | /* Don't pin and map if container doesn't contain IOMMU capable domain*/ |
| 1670 | if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) | 1666 | if (list_empty(&iommu->domain_list)) |
| 1671 | dma->size = size; | 1667 | dma->size = size; |
| 1672 | else | 1668 | else |
| 1673 | ret = vfio_pin_map_dma(iommu, dma, size); | 1669 | ret = vfio_pin_map_dma(iommu, dma, size); |
| @@ -1893,8 +1889,8 @@ static struct vfio_iommu_group* · 219 unmodified lines | |||
| 1893 | vfio_iommu_find_iommu_group(struct vfio_iommu *iommu, | 1889 | vfio_iommu_find_iommu_group(struct vfio_iommu *iommu, |
| 1894 | struct iommu_group *iommu_group) | 1890 | struct iommu_group *iommu_group) |
| 1895 | { | 1891 | { |
| 1892 | struct vfio_iommu_group *group; | ||
| 1896 | struct vfio_domain *domain; | 1893 | struct vfio_domain *domain; |
| 1897 | struct vfio_iommu_group *group = NULL; | ||
| 1898 | 1894 | ||
| 1899 | list_for_each_entry(domain, &iommu->domain_list, next) { | 1895 | list_for_each_entry(domain, &iommu->domain_list, next) { |
| 1900 | group = find_iommu_group(domain, iommu_group); | 1896 | group = find_iommu_group(domain, iommu_group); |
| @@ -1902,10 +1898,10 @@ vfio_iommu_find_iommu_group(struct vfio_iommu *iommu, · 1 unmodified line | |||
| 1902 | return group; | 1898 | return group; |
| 1903 | } | 1899 | } |
| 1904 | 1900 | ||
| 1905 | if (iommu->external_domain) | 1901 | list_for_each_entry(group, &iommu->emulated_iommu_groups, next) |
| 1906 | group = find_iommu_group(iommu->external_domain, iommu_group); | 1902 | if (group->iommu_group == iommu_group) |
| 1907 | 1903 | return group; | |
| 1908 | return group; | 1904 | return NULL; |
| 1909 | } | 1905 | } |
| 1910 | 1906 | ||
| 1911 | static bool vfio_iommu_has_sw_msi(struct list_head *group_resv_regions, | 1907 | static bool vfio_iommu_has_sw_msi(struct list_head *group_resv_regions, |
| @@ -1934,89 +1930,6 @@ static bool vfio_iommu_has_sw_msi(struct list_head *group_resv_regions, · 22 unmodified lines | |||
| 1934 | return ret; | 1930 | return ret; |
| 1935 | } | 1931 | } |
| 1936 | 1932 | ||
| 1937 | static int vfio_mdev_attach_domain(struct device *dev, void *data) | ||
| 1938 | { | ||
| 1939 | struct mdev_device *mdev = to_mdev_device(dev); | ||
| 1940 | struct iommu_domain *domain = data; | ||
| 1941 | struct device *iommu_device; | ||
| 1942 | |||
| 1943 | iommu_device = mdev_get_iommu_device(mdev); | ||
| 1944 | if (iommu_device) { | ||
| 1945 | if (iommu_dev_feature_enabled(iommu_device, IOMMU_DEV_FEAT_AUX)) | ||
| 1946 | return iommu_aux_attach_device(domain, iommu_device); | ||
| 1947 | else | ||
| 1948 | return iommu_attach_device(domain, iommu_device); | ||
| 1949 | } | ||
| 1950 | |||
| 1951 | return -EINVAL; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | static int vfio_mdev_detach_domain(struct device *dev, void *data) | ||
| 1955 | { | ||
| 1956 | struct mdev_device *mdev = to_mdev_device(dev); | ||
| 1957 | struct iommu_domain *domain = data; | ||
| 1958 | struct device *iommu_device; | ||
| 1959 | |||
| 1960 | iommu_device = mdev_get_iommu_device(mdev); | ||
| 1961 | if (iommu_device) { | ||
| 1962 | if (iommu_dev_feature_enabled(iommu_device, IOMMU_DEV_FEAT_AUX)) | ||
| 1963 | iommu_aux_detach_device(domain, iommu_device); | ||
| 1964 | else | ||
| 1965 | iommu_detach_device(domain, iommu_device); | ||
| 1966 | } | ||
| 1967 | |||
| 1968 | return 0; | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | static int vfio_iommu_attach_group(struct vfio_domain *domain, | ||
| 1972 | struct vfio_iommu_group *group) | ||
| 1973 | { | ||
| 1974 | if (group->mdev_group) | ||
| 1975 | return iommu_group_for_each_dev(group->iommu_group, | ||
| 1976 | domain->domain, | ||
| 1977 | vfio_mdev_attach_domain); | ||
| 1978 | else | ||
| 1979 | return iommu_attach_group(domain->domain, group->iommu_group); | ||
| 1980 | } | ||
| 1981 | |||
| 1982 | static void vfio_iommu_detach_group(struct vfio_domain *domain, | ||
| 1983 | struct vfio_iommu_group *group) | ||
| 1984 | { | ||
| 1985 | if (group->mdev_group) | ||
| 1986 | iommu_group_for_each_dev(group->iommu_group, domain->domain, | ||
| 1987 | vfio_mdev_detach_domain); | ||
| 1988 | else | ||
| 1989 | iommu_detach_group(domain->domain, group->iommu_group); | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | static bool vfio_bus_is_mdev(struct bus_type *bus) | ||
| 1993 | { | ||
| 1994 | struct bus_type *mdev_bus; | ||
| 1995 | bool ret = false; | ||
| 1996 | |||
| 1997 | mdev_bus = symbol_get(mdev_bus_type); | ||
| 1998 | if (mdev_bus) { | ||
| 1999 | ret = (bus == mdev_bus); | ||
| 2000 | symbol_put(mdev_bus_type); | ||
| 2001 | } | ||
| 2002 | |||
| 2003 | return ret; | ||
| 2004 | } | ||
| 2005 | |||
| 2006 | static int vfio_mdev_iommu_device(struct device *dev, void *data) | ||
| 2007 | { | ||
| 2008 | struct mdev_device *mdev = to_mdev_device(dev); | ||
| 2009 | struct device **old = data, *new; | ||
| 2010 | |||
| 2011 | new = mdev_get_iommu_device(mdev); | ||
| 2012 | if (!new || (*old && *old != new)) | ||
| 2013 | return -EINVAL; | ||
| 2014 | |||
| 2015 | *old = new; | ||
| 2016 | |||
| 2017 | return 0; | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | /* | 1933 | /* |
| 2021 | * This is a helper function to insert an address range to iova list. | 1934 | * This is a helper function to insert an address range to iova list. |
| 2022 | * The list is initially created with a single entry corresponding to | 1935 | * The list is initially created with a single entry corresponding to |
| @@ -2241,81 +2154,58 @@ static void vfio_iommu_iova_insert_copy(struct vfio_iommu *iommu, · 218 unmodified lines | |||
| 2241 | } | 2154 | } |
| 2242 | 2155 | ||
| 2243 | static int vfio_iommu_type1_attach_group(void *iommu_data, | 2156 | static int vfio_iommu_type1_attach_group(void *iommu_data, |
| 2244 | struct iommu_group *iommu_group) | 2157 | struct iommu_group *iommu_group, enum vfio_group_type type) |
| 2245 | { | 2158 | { |
| 2246 | struct vfio_iommu *iommu = iommu_data; | 2159 | struct vfio_iommu *iommu = iommu_data; |
| 2247 | struct vfio_iommu_group *group; | 2160 | struct vfio_iommu_group *group; |
| 2248 | struct vfio_domain *domain, *d; | 2161 | struct vfio_domain *domain, *d; |
| 2249 | struct bus_type *bus = NULL; | 2162 | struct bus_type *bus = NULL; |
| 2250 | int ret; | ||
| 2251 | bool resv_msi, msi_remap; | 2163 | bool resv_msi, msi_remap; |
| 2252 | phys_addr_t resv_msi_base = 0; | 2164 | phys_addr_t resv_msi_base = 0; |
| 2253 | struct iommu_domain_geometry *geo; | 2165 | struct iommu_domain_geometry *geo; |
| 2254 | LIST_HEAD(iova_copy); | 2166 | LIST_HEAD(iova_copy); |
| 2255 | LIST_HEAD(group_resv_regions); | 2167 | LIST_HEAD(group_resv_regions); |
| 2168 | int ret = -EINVAL; | ||
| 2256 | 2169 | ||
| 2257 | mutex_lock(&iommu->lock); | 2170 | mutex_lock(&iommu->lock); |
| 2258 | 2171 | ||
| 2259 | /* Check for duplicates */ | 2172 | /* Check for duplicates */ |
| 2260 | if (vfio_iommu_find_iommu_group(iommu, iommu_group)) { | 2173 | if (vfio_iommu_find_iommu_group(iommu, iommu_group)) |
| 2261 | mutex_unlock(&iommu->lock); | 2174 | goto out_unlock; |
| 2262 | return -EINVAL; | ||
| 2263 | } | ||
| 2264 | 2175 | ||
| 2176 | ret = -ENOMEM; | ||
| 2265 | group = kzalloc(sizeof(*group), GFP_KERNEL); | 2177 | group = kzalloc(sizeof(*group), GFP_KERNEL); |
| 2266 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | 2178 | if (!group) |
| 2267 | if (!group || !domain) { | 2179 | goto out_unlock; |
| 2268 | ret = -ENOMEM; | ||
| 2269 | goto out_free; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | group->iommu_group = iommu_group; | 2180 | group->iommu_group = iommu_group; |
| 2273 | 2181 | ||
| 2182 | if (type == VFIO_EMULATED_IOMMU) { | ||
| 2183 | list_add(&group->next, &iommu->emulated_iommu_groups); | ||
| 2184 | /* | ||
| 2185 | * An emulated IOMMU group cannot dirty memory directly, it can | ||
| 2186 | * only use interfaces that provide dirty tracking. | ||
| 2187 | * The iommu scope can only be promoted with the addition of a | ||
| 2188 | * dirty tracking group. | ||
| 2189 | */ | ||
| 2190 | group->pinned_page_dirty_scope = true; | ||
| 2191 | ret = 0; | ||
| 2192 | goto out_unlock; | ||
| 2193 | } | ||
| 2194 | |||
| 2274 | /* Determine bus_type in order to allocate a domain */ | 2195 | /* Determine bus_type in order to allocate a domain */ |
| 2275 | ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type); | 2196 | ret = iommu_group_for_each_dev(iommu_group, &bus, vfio_bus_type); |
| 2276 | if (ret) | 2197 | if (ret) |
| 2277 | goto out_free; | 2198 | goto out_free_group; |
| 2278 | |||
| 2279 | if (vfio_bus_is_mdev(bus)) { | ||
| 2280 | struct device *iommu_device = NULL; | ||
| 2281 | |||
| 2282 | group->mdev_group = true; | ||
| 2283 | |||
| 2284 | /* Determine the isolation type */ | ||
| 2285 | ret = iommu_group_for_each_dev(iommu_group, &iommu_device, | ||
| 2286 | vfio_mdev_iommu_device); | ||
| 2287 | if (ret || !iommu_device) { | ||
| 2288 | if (!iommu->external_domain) { | ||
| 2289 | INIT_LIST_HEAD(&domain->group_list); | ||
| 2290 | iommu->external_domain = domain; | ||
| 2291 | vfio_update_pgsize_bitmap(iommu); | ||
| 2292 | } else { | ||
| 2293 | kfree(domain); | ||
| 2294 | } | ||
| 2295 | |||
| 2296 | list_add(&group->next, | ||
| 2297 | &iommu->external_domain->group_list); | ||
| 2298 | /* | ||
| 2299 | * Non-iommu backed group cannot dirty memory directly, | ||
| 2300 | * it can only use interfaces that provide dirty | ||
| 2301 | * tracking. | ||
| 2302 | * The iommu scope can only be promoted with the | ||
| 2303 | * addition of a dirty tracking group. | ||
| 2304 | */ | ||
| 2305 | group->pinned_page_dirty_scope = true; | ||
| 2306 | mutex_unlock(&iommu->lock); | ||
| 2307 | 2199 | ||
| 2308 | return 0; | 2200 | ret = -ENOMEM; |
| 2309 | } | 2201 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); |
| 2310 | 2202 | if (!domain) | |
| 2311 | bus = iommu_device->bus; | 2203 | goto out_free_group; |
| 2312 | } | ||
| 2313 | 2204 | ||
| 2205 | ret = -EIO; | ||
| 2314 | domain->domain = iommu_domain_alloc(bus); | 2206 | domain->domain = iommu_domain_alloc(bus); |
| 2315 | if (!domain->domain) { | 2207 | if (!domain->domain) |
| 2316 | ret = -EIO; | 2208 | goto out_free_domain; |
| 2317 | goto out_free; | ||
| 2318 | } | ||
| 2319 | 2209 | ||
| 2320 | if (iommu->nesting) { | 2210 | if (iommu->nesting) { |
| 2321 | ret = iommu_enable_nesting(domain->domain); | 2211 | ret = iommu_enable_nesting(domain->domain); |
| @@ -2323,7 +2213,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, · 1 unmodified line | |||
| 2323 | goto out_domain; | 2213 | goto out_domain; |
| 2324 | } | 2214 | } |
| 2325 | 2215 | ||
| 2326 | ret = vfio_iommu_attach_group(domain, group); | 2216 | ret = iommu_attach_group(domain->domain, group->iommu_group); |
| 2327 | if (ret) | 2217 | if (ret) |
| 2328 | goto out_domain; | 2218 | goto out_domain; |
| 2329 | 2219 | ||
| @@ -2390,15 +2280,17 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, · 60 unmodified lines | |||
| 2390 | list_for_each_entry(d, &iommu->domain_list, next) { | 2280 | list_for_each_entry(d, &iommu->domain_list, next) { |
| 2391 | if (d->domain->ops == domain->domain->ops && | 2281 | if (d->domain->ops == domain->domain->ops && |
| 2392 | d->prot == domain->prot) { | 2282 | d->prot == domain->prot) { |
| 2393 | vfio_iommu_detach_group(domain, group); | 2283 | iommu_detach_group(domain->domain, group->iommu_group); |
| 2394 | if (!vfio_iommu_attach_group(d, group)) { | 2284 | if (!iommu_attach_group(d->domain, |
| 2285 | group->iommu_group)) { | ||
| 2395 | list_add(&group->next, &d->group_list); | 2286 | list_add(&group->next, &d->group_list); |
| 2396 | iommu_domain_free(domain->domain); | 2287 | iommu_domain_free(domain->domain); |
| 2397 | kfree(domain); | 2288 | kfree(domain); |
| 2398 | goto done; | 2289 | goto done; |
| 2399 | } | 2290 | } |
| 2400 | 2291 | ||
| 2401 | ret = vfio_iommu_attach_group(domain, group); | 2292 | ret = iommu_attach_group(domain->domain, |
| 2293 | group->iommu_group); | ||
| 2402 | if (ret) | 2294 | if (ret) |
| 2403 | goto out_domain; | 2295 | goto out_domain; |
| 2404 | } | 2296 | } |
| @@ -2435,14 +2327,16 @@ done: · 30 unmodified lines | |||
| 2435 | return 0; | 2327 | return 0; |
| 2436 | 2328 | ||
| 2437 | out_detach: | 2329 | out_detach: |
| 2438 | vfio_iommu_detach_group(domain, group); | 2330 | iommu_detach_group(domain->domain, group->iommu_group); |
| 2439 | out_domain: | 2331 | out_domain: |
| 2440 | iommu_domain_free(domain->domain); | 2332 | iommu_domain_free(domain->domain); |
| 2441 | vfio_iommu_iova_free(&iova_copy); | 2333 | vfio_iommu_iova_free(&iova_copy); |
| 2442 | vfio_iommu_resv_free(&group_resv_regions); | 2334 | vfio_iommu_resv_free(&group_resv_regions); |
| 2443 | out_free: | 2335 | out_free_domain: |
| 2444 | kfree(domain); | 2336 | kfree(domain); |
| 2337 | out_free_group: | ||
| 2445 | kfree(group); | 2338 | kfree(group); |
| 2339 | out_unlock: | ||
| 2446 | mutex_unlock(&iommu->lock); | 2340 | mutex_unlock(&iommu->lock); |
| 2447 | return ret; | 2341 | return ret; |
| 2448 | } | 2342 | } |
| @@ -2567,25 +2461,19 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, · 118 unmodified lines | |||
| 2567 | LIST_HEAD(iova_copy); | 2461 | LIST_HEAD(iova_copy); |
| 2568 | 2462 | ||
| 2569 | mutex_lock(&iommu->lock); | 2463 | mutex_lock(&iommu->lock); |
| 2464 | list_for_each_entry(group, &iommu->emulated_iommu_groups, next) { | ||
| 2465 | if (group->iommu_group != iommu_group) | ||
| 2466 | continue; | ||
| 2467 | update_dirty_scope = !group->pinned_page_dirty_scope; | ||
| 2468 | list_del(&group->next); | ||
| 2469 | kfree(group); | ||
| 2570 | 2470 | ||
| 2571 | if (iommu->external_domain) { | 2471 | if (list_empty(&iommu->emulated_iommu_groups) && |
| 2572 | group = find_iommu_group(iommu->external_domain, iommu_group); | 2472 | list_empty(&iommu->domain_list)) { |
| 2573 | if (group) { | 2473 | WARN_ON(iommu->notifier.head); |
| 2574 | update_dirty_scope = !group->pinned_page_dirty_scope; | 2474 | vfio_iommu_unmap_unpin_all(iommu); |
| 2575 | list_del(&group->next); | ||
| 2576 | kfree(group); | ||
| 2577 | |||
| 2578 | if (list_empty(&iommu->external_domain->group_list)) { | ||
| 2579 | if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) { | ||
| 2580 | WARN_ON(iommu->notifier.head); | ||
| 2581 | vfio_iommu_unmap_unpin_all(iommu); | ||
| 2582 | } | ||
| 2583 | |||
| 2584 | kfree(iommu->external_domain); | ||
| 2585 | iommu->external_domain = NULL; | ||
| 2586 | } | ||
| 2587 | goto detach_group_done; | ||
| 2588 | } | 2475 | } |
| 2476 | goto detach_group_done; | ||
| 2589 | } | 2477 | } |
| 2590 | 2478 | ||
| 2591 | /* | 2479 | /* |
| @@ -2600,7 +2488,7 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, · 8 unmodified lines | |||
| 2600 | if (!group) | 2488 | if (!group) |
| 2601 | continue; | 2489 | continue; |
| 2602 | 2490 | ||
| 2603 | vfio_iommu_detach_group(domain, group); | 2491 | iommu_detach_group(domain->domain, group->iommu_group); |
| 2604 | update_dirty_scope = !group->pinned_page_dirty_scope; | 2492 | update_dirty_scope = !group->pinned_page_dirty_scope; |
| 2605 | list_del(&group->next); | 2493 | list_del(&group->next); |
| 2606 | kfree(group); | 2494 | kfree(group); |
| @@ -2613,7 +2501,7 @@ static void vfio_iommu_type1_detach_group(void *iommu_data, · 6 unmodified lines | |||
| 2613 | */ | 2501 | */ |
| 2614 | if (list_empty(&domain->group_list)) { | 2502 | if (list_empty(&domain->group_list)) { |
| 2615 | if (list_is_singular(&iommu->domain_list)) { | 2503 | if (list_is_singular(&iommu->domain_list)) { |
| 2616 | if (!iommu->external_domain) { | 2504 | if (list_empty(&iommu->emulated_iommu_groups)) { |
| 2617 | WARN_ON(iommu->notifier.head); | 2505 | WARN_ON(iommu->notifier.head); |
| 2618 | vfio_iommu_unmap_unpin_all(iommu); | 2506 | vfio_iommu_unmap_unpin_all(iommu); |
| 2619 | } else { | 2507 | } else { |
| @@ -2677,41 +2565,43 @@ static void *vfio_iommu_type1_open(unsigned long arg) · 57 unmodified lines | |||
| 2677 | mutex_init(&iommu->lock); | 2565 | mutex_init(&iommu->lock); |
| 2678 | BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); | 2566 | BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier); |
| 2679 | init_waitqueue_head(&iommu->vaddr_wait); | 2567 | init_waitqueue_head(&iommu->vaddr_wait); |
| 2568 | iommu->pgsize_bitmap = PAGE_MASK; | ||
| 2569 | INIT_LIST_HEAD(&iommu->emulated_iommu_groups); | ||
| 2680 | 2570 | ||
| 2681 | return iommu; | 2571 | return iommu; |
| 2682 | } | 2572 | } |
| 2683 | 2573 | ||
| 2684 | static void vfio_release_domain(struct vfio_domain *domain, bool external) | 2574 | static void vfio_release_domain(struct vfio_domain *domain) |
| 2685 | { | 2575 | { |
| 2686 | struct vfio_iommu_group *group, *group_tmp; | 2576 | struct vfio_iommu_group *group, *group_tmp; |
| 2687 | 2577 | ||
| 2688 | list_for_each_entry_safe(group, group_tmp, | 2578 | list_for_each_entry_safe(group, group_tmp, |
| 2689 | &domain->group_list, next) { | 2579 | &domain->group_list, next) { |
| 2690 | if (!external) | 2580 | iommu_detach_group(domain->domain, group->iommu_group); |
| 2691 | vfio_iommu_detach_group(domain, group); | ||
| 2692 | list_del(&group->next); | 2581 | list_del(&group->next); |
| 2693 | kfree(group); | 2582 | kfree(group); |
| 2694 | } | 2583 | } |
| 2695 | 2584 | ||
| 2696 | if (!external) | 2585 | iommu_domain_free(domain->domain); |
| 2697 | iommu_domain_free(domain->domain); | ||
| 2698 | } | 2586 | } |
| 2699 | 2587 | ||
| 2700 | static void vfio_iommu_type1_release(void *iommu_data) | 2588 | static void vfio_iommu_type1_release(void *iommu_data) |
| 2701 | { | 2589 | { |
| 2702 | struct vfio_iommu *iommu = iommu_data; | 2590 | struct vfio_iommu *iommu = iommu_data; |
| 2703 | struct vfio_domain *domain, *domain_tmp; | 2591 | struct vfio_domain *domain, *domain_tmp; |
| 2592 | struct vfio_iommu_group *group, *next_group; | ||
| 2704 | 2593 | ||
| 2705 | if (iommu->external_domain) { | 2594 | list_for_each_entry_safe(group, next_group, |
| 2706 | vfio_release_domain(iommu->external_domain, true); | 2595 | &iommu->emulated_iommu_groups, next) { |
| 2707 | kfree(iommu->external_domain); | 2596 | list_del(&group->next); |
| 2597 | kfree(group); | ||
| 2708 | } | 2598 | } |
| 2709 | 2599 | ||
| 2710 | vfio_iommu_unmap_unpin_all(iommu); | 2600 | vfio_iommu_unmap_unpin_all(iommu); |
| 2711 | 2601 | ||
| 2712 | list_for_each_entry_safe(domain, domain_tmp, | 2602 | list_for_each_entry_safe(domain, domain_tmp, |
| 2713 | &iommu->domain_list, next) { | 2603 | &iommu->domain_list, next) { |
| 2714 | vfio_release_domain(domain, false); | 2604 | vfio_release_domain(domain); |
| 2715 | list_del(&domain->next); | 2605 | list_del(&domain->next); |
| 2716 | kfree(domain); | 2606 | kfree(domain); |
| 2717 | } | 2607 | } |
| @@ -620,6 +620,20 @@ int dpcon_reset(struct fsl_mc_io *mc_io, · 619 unmodified lines | |||
| 620 | u32 cmd_flags, | 620 | u32 cmd_flags, |
| 621 | u16 token); | 621 | u16 token); |
| 622 | 622 | ||
| 623 | int fsl_mc_obj_open(struct fsl_mc_io *mc_io, | ||
| 624 | u32 cmd_flags, | ||
| 625 | int obj_id, | ||
| 626 | char *obj_type, | ||
| 627 | u16 *token); | ||
| 628 | |||
| 629 | int fsl_mc_obj_close(struct fsl_mc_io *mc_io, | ||
| 630 | u32 cmd_flags, | ||
| 631 | u16 token); | ||
| 632 | |||
| 633 | int fsl_mc_obj_reset(struct fsl_mc_io *mc_io, | ||
| 634 | u32 cmd_flags, | ||
| 635 | u16 token); | ||
| 636 | |||
| 623 | /** | 637 | /** |
| 624 | * struct dpcon_attr - Structure representing DPCON attributes | 638 | * struct dpcon_attr - Structure representing DPCON attributes |
| 625 | * @id: DPCON object ID | 639 | * @id: DPCON object ID |
| @@ -18,7 +18,6 @@ struct mdev_device { · 17 unmodified lines | |||
| 18 | void *driver_data; | 18 | void *driver_data; |
| 19 | struct list_head next; | 19 | struct list_head next; |
| 20 | struct mdev_type *type; | 20 | struct mdev_type *type; |
| 21 | struct device *iommu_device; | ||
| 22 | bool active; | 21 | bool active; |
| 23 | }; | 22 | }; |
| 24 | 23 | ||
| @@ -27,25 +26,6 @@ static inline struct mdev_device *to_mdev_device(struct device *dev) · 2 unmodified lines | |||
| 27 | return container_of(dev, struct mdev_device, dev); | 26 | return container_of(dev, struct mdev_device, dev); |
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | /* | ||
| 31 | * Called by the parent device driver to set the device which represents | ||
| 32 | * this mdev in iommu protection scope. By default, the iommu device is | ||
| 33 | * NULL, that indicates using vendor defined isolation. | ||
| 34 | * | ||
| 35 | * @dev: the mediated device that iommu will isolate. | ||
| 36 | * @iommu_device: a pci device which represents the iommu for @dev. | ||
| 37 | */ | ||
| 38 | static inline void mdev_set_iommu_device(struct mdev_device *mdev, | ||
| 39 | struct device *iommu_device) | ||
| 40 | { | ||
| 41 | mdev->iommu_device = iommu_device; | ||
| 42 | } | ||
| 43 | |||
| 44 | static inline struct device *mdev_get_iommu_device(struct mdev_device *mdev) | ||
| 45 | { | ||
| 46 | return mdev->iommu_device; | ||
| 47 | } | ||
| 48 | |||
| 49 | unsigned int mdev_get_type_group_id(struct mdev_device *mdev); | 29 | unsigned int mdev_get_type_group_id(struct mdev_device *mdev); |
| 50 | unsigned int mtype_get_type_group_id(struct mdev_type *mtype); | 30 | unsigned int mtype_get_type_group_id(struct mdev_type *mtype); |
| 51 | struct device *mtype_get_parent_dev(struct mdev_type *mtype); | 31 | struct device *mtype_get_parent_dev(struct mdev_type *mtype); |
| @@ -71,68 +71,17 @@ struct vfio_device_ops { · 70 unmodified lines | |||
| 71 | int (*match)(struct vfio_device *vdev, char *buf); | 71 | int (*match)(struct vfio_device *vdev, char *buf); |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | extern struct iommu_group *vfio_iommu_group_get(struct device *dev); | ||
| 75 | extern void vfio_iommu_group_put(struct iommu_group *group, struct device *dev); | ||
| 76 | |||
| 77 | void vfio_init_group_dev(struct vfio_device *device, struct device *dev, | 74 | void vfio_init_group_dev(struct vfio_device *device, struct device *dev, |
| 78 | const struct vfio_device_ops *ops); | 75 | const struct vfio_device_ops *ops); |
| 79 | void vfio_uninit_group_dev(struct vfio_device *device); | 76 | void vfio_uninit_group_dev(struct vfio_device *device); |
| 80 | int vfio_register_group_dev(struct vfio_device *device); | 77 | int vfio_register_group_dev(struct vfio_device *device); |
| 78 | int vfio_register_emulated_iommu_dev(struct vfio_device *device); | ||
| 81 | void vfio_unregister_group_dev(struct vfio_device *device); | 79 | void vfio_unregister_group_dev(struct vfio_device *device); |
| 82 | extern struct vfio_device *vfio_device_get_from_dev(struct device *dev); | 80 | extern struct vfio_device *vfio_device_get_from_dev(struct device *dev); |
| 83 | extern void vfio_device_put(struct vfio_device *device); | 81 | extern void vfio_device_put(struct vfio_device *device); |
| 84 | 82 | ||
| 85 | int vfio_assign_device_set(struct vfio_device *device, void *set_id); | 83 | int vfio_assign_device_set(struct vfio_device *device, void *set_id); |
| 86 | 84 | ||
| 87 | /* events for the backend driver notify callback */ | ||
| 88 | enum vfio_iommu_notify_type { | ||
| 89 | VFIO_IOMMU_CONTAINER_CLOSE = 0, | ||
| 90 | }; | ||
| 91 | |||
| 92 | /** | ||
| 93 | * struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks | ||
| 94 | */ | ||
| 95 | struct vfio_iommu_driver_ops { | ||
| 96 | char *name; | ||
| 97 | struct module *owner; | ||
| 98 | void *(*open)(unsigned long arg); | ||
| 99 | void (*release)(void *iommu_data); | ||
| 100 | ssize_t (*read)(void *iommu_data, char __user *buf, | ||
| 101 | size_t count, loff_t *ppos); | ||
| 102 | ssize_t (*write)(void *iommu_data, const char __user *buf, | ||
| 103 | size_t count, loff_t *size); | ||
| 104 | long (*ioctl)(void *iommu_data, unsigned int cmd, | ||
| 105 | unsigned long arg); | ||
| 106 | int (*mmap)(void *iommu_data, struct vm_area_struct *vma); | ||
| 107 | int (*attach_group)(void *iommu_data, | ||
| 108 | struct iommu_group *group); | ||
| 109 | void (*detach_group)(void *iommu_data, | ||
| 110 | struct iommu_group *group); | ||
| 111 | int (*pin_pages)(void *iommu_data, | ||
| 112 | struct iommu_group *group, | ||
| 113 | unsigned long *user_pfn, | ||
| 114 | int npage, int prot, | ||
| 115 | unsigned long *phys_pfn); | ||
| 116 | int (*unpin_pages)(void *iommu_data, | ||
| 117 | unsigned long *user_pfn, int npage); | ||
| 118 | int (*register_notifier)(void *iommu_data, | ||
| 119 | unsigned long *events, | ||
| 120 | struct notifier_block *nb); | ||
| 121 | int (*unregister_notifier)(void *iommu_data, | ||
| 122 | struct notifier_block *nb); | ||
| 123 | int (*dma_rw)(void *iommu_data, dma_addr_t user_iova, | ||
| 124 | void *data, size_t count, bool write); | ||
| 125 | struct iommu_domain *(*group_iommu_domain)(void *iommu_data, | ||
| 126 | struct iommu_group *group); | ||
| 127 | void (*notify)(void *iommu_data, | ||
| 128 | enum vfio_iommu_notify_type event); | ||
| 129 | }; | ||
| 130 | |||
| 131 | extern int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops); | ||
| 132 | |||
| 133 | extern void vfio_unregister_iommu_driver( | ||
| 134 | const struct vfio_iommu_driver_ops *ops); | ||
| 135 | |||
| 136 | /* | 85 | /* |
| 137 | * External user API | 86 | * External user API |
| 138 | */ | 87 | */ |
| @@ -553,7 +553,7 @@ static int mbochs_probe(struct mdev_device *mdev) · 552 unmodified lines | |||
| 553 | mbochs_create_config_space(mdev_state); | 553 | mbochs_create_config_space(mdev_state); |
| 554 | mbochs_reset(mdev_state); | 554 | mbochs_reset(mdev_state); |
| 555 | 555 | ||
| 556 | ret = vfio_register_group_dev(&mdev_state->vdev); | 556 | ret = vfio_register_emulated_iommu_dev(&mdev_state->vdev); |
| 557 | if (ret) | 557 | if (ret) |
| 558 | goto err_mem; | 558 | goto err_mem; |
| 559 | dev_set_drvdata(&mdev->dev, mdev_state); | 559 | dev_set_drvdata(&mdev->dev, mdev_state); |
| @@ -258,7 +258,7 @@ static int mdpy_probe(struct mdev_device *mdev) · 257 unmodified lines | |||
| 258 | 258 | ||
| 259 | mdpy_count++; | 259 | mdpy_count++; |
| 260 | 260 | ||
| 261 | ret = vfio_register_group_dev(&mdev_state->vdev); | 261 | ret = vfio_register_emulated_iommu_dev(&mdev_state->vdev); |
| 262 | if (ret) | 262 | if (ret) |
| 263 | goto err_mem; | 263 | goto err_mem; |
| 264 | dev_set_drvdata(&mdev->dev, mdev_state); | 264 | dev_set_drvdata(&mdev->dev, mdev_state); |
| @@ -741,7 +741,7 @@ static int mtty_probe(struct mdev_device *mdev) · 740 unmodified lines | |||
| 741 | 741 | ||
| 742 | mtty_create_config_space(mdev_state); | 742 | mtty_create_config_space(mdev_state); |
| 743 | 743 | ||
| 744 | ret = vfio_register_group_dev(&mdev_state->vdev); | 744 | ret = vfio_register_emulated_iommu_dev(&mdev_state->vdev); |
| 745 | if (ret) | 745 | if (ret) |
| 746 | goto err_vconfig; | 746 | goto err_vconfig; |
| 747 | dev_set_drvdata(&mdev->dev, mdev_state); | 747 | dev_set_drvdata(&mdev->dev, mdev_state); |