Loading Documentation/driver-api/vfio-mediated-device.rst +5 −22 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ structure to represent a mediated device's driver:: struct mdev_driver { int (*probe) (struct mdev_device *dev); void (*remove) (struct mdev_device *dev); struct attribute_group **supported_type_groups; struct device_driver driver; }; Loading @@ -119,33 +120,15 @@ to register and unregister itself with the core driver: extern void mdev_unregister_driver(struct mdev_driver *drv); The mediated bus driver is responsible for adding mediated devices to the VFIO group when devices are bound to the driver and removing mediated devices from the VFIO when devices are unbound from the driver. Physical Device Driver Interface -------------------------------- The physical device driver interface provides the mdev_parent_ops[3] structure to define the APIs to manage work in the mediated core driver that is related to the physical device. The structures in the mdev_parent_ops structure are as follows: * dev_attr_groups: attributes of the parent device * mdev_attr_groups: attributes of the mediated device * supported_config: attributes to define supported configurations * device_driver: device driver to bind for mediated device instances The mdev_parent_ops also still has various functions pointers. Theses exist for historical reasons only and shall not be used for new drivers. The mediated bus driver's probe function should create a vfio_device on top of the mdev_device and connect it to an appropriate implementation of vfio_device_ops. When a driver wants to add the GUID creation sysfs to an existing device it has probe'd to then it should call:: extern int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops); struct mdev_driver *mdev_driver); This will provide the 'mdev_supported_types/XX/create' files which can then be used to trigger the creation of a mdev_device. The created mdev_device will be Loading drivers/gpu/drm/i915/Kconfig +13 −23 Original line number Diff line number Diff line Loading @@ -102,40 +102,30 @@ config DRM_I915_USERPTR If in doubt, say "Y". config DRM_I915_GVT bool "Enable Intel GVT-g graphics virtualization host support" bool config DRM_I915_GVT_KVMGT tristate "Enable KVM host support Intel GVT-g graphics virtualization" depends on DRM_I915 depends on X86 depends on 64BIT default n depends on KVM depends on VFIO_MDEV select DRM_I915_GVT select KVM_EXTERNAL_WRITE_TRACKING help Choose this option if you want to enable Intel GVT-g graphics virtualization technology host support with integrated graphics. With GVT-g, it's possible to have one integrated graphics device shared by multiple VMs under different hypervisors. Note that at least one hypervisor like Xen or KVM is required for this driver to work, and it only supports newer device from Broadwell+. For further information and setup guide, you can visit: http://01.org/igvt-g. device shared by multiple VMs under KVM. Now it's just a stub to support the modifications of i915 for GVT device model. It requires at least one MPT modules for Xen/KVM and other components of GVT device model to work. Use it under you own risk. Note that this driver only supports newer device from Broadwell on. For further information and setup guide, you can visit: http://01.org/igvt-g. If in doubt, say "N". config DRM_I915_GVT_KVMGT tristate "Enable KVM/VFIO support for Intel GVT-g" depends on DRM_I915_GVT depends on KVM depends on VFIO_MDEV select KVM_EXTERNAL_WRITE_TRACKING default n help Choose this option if you want to enable KVMGT support for Intel GVT-g. config DRM_I915_PXP bool "Enable Intel PXP support" depends on DRM_I915 Loading drivers/gpu/drm/i915/Makefile +4 −4 Original line number Diff line number Diff line Loading @@ -320,13 +320,13 @@ i915-$(CONFIG_DRM_I915_SELFTEST) += \ # virtual gpu code i915-y += i915_vgpu.o ifeq ($(CONFIG_DRM_I915_GVT),y) i915-y += intel_gvt.o i915-$(CONFIG_DRM_I915_GVT) += \ intel_gvt.o \ intel_gvt_mmio_table.o include $(src)/gvt/Makefile endif obj-$(CONFIG_DRM_I915) += i915.o obj-$(CONFIG_DRM_I915_GVT_KVMGT) += gvt/kvmgt.o obj-$(CONFIG_DRM_I915_GVT_KVMGT) += kvmgt.o # header test Loading drivers/gpu/drm/i915/gvt/Makefile +23 −7 Original line number Diff line number Diff line # SPDX-License-Identifier: GPL-2.0 GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ execlist.o scheduler.o sched_policy.o mmio_context.o cmd_parser.o debugfs.o \ fb_decoder.o dmabuf.o page_track.o ccflags-y += -I $(srctree)/$(src) -I $(srctree)/$(src)/$(GVT_DIR)/ i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) kvmgt-$(CONFIG_DRM_I915_GVT) += \ gvt/aperture_gm.o \ gvt/cfg_space.o \ gvt/cmd_parser.o \ gvt/debugfs.o \ gvt/display.o \ gvt/dmabuf.o \ gvt/edid.o \ gvt/execlist.o \ gvt/fb_decoder.o \ gvt/firmware.o \ gvt/gtt.o \ gvt/handlers.o \ gvt/interrupt.o \ gvt/kvmgt.o \ gvt/mmio.o \ gvt/mmio_context.o \ gvt/opregion.o \ gvt/page_track.o \ gvt/sched_policy.o \ gvt/scheduler.o \ gvt/trace_points.o \ gvt/vgpu.o drivers/gpu/drm/i915/gvt/cfg_space.c +17 −72 Original line number Diff line number Diff line Loading @@ -129,60 +129,16 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, return 0; } static int map_aperture(struct intel_vgpu *vgpu, bool map) static void map_aperture(struct intel_vgpu *vgpu, bool map) { phys_addr_t aperture_pa = vgpu_aperture_pa_base(vgpu); unsigned long aperture_sz = vgpu_aperture_sz(vgpu); u64 first_gfn; u64 val; int ret; if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) return 0; val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2]; if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); else val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT; ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn, aperture_pa >> PAGE_SHIFT, aperture_sz >> PAGE_SHIFT, map); if (ret) return ret; if (map != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; return 0; } static int trap_gttmmio(struct intel_vgpu *vgpu, bool trap) static void trap_gttmmio(struct intel_vgpu *vgpu, bool trap) { u64 start, end; u64 val; int ret; if (trap == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked) return 0; val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_0]; if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) start = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); else start = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); start &= ~GENMASK(3, 0); end = start + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size - 1; ret = intel_gvt_hypervisor_set_trap_area(vgpu, start, end, trap); if (ret) return ret; if (trap != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked) vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap; return 0; } static int emulate_pci_command_write(struct intel_vgpu *vgpu, Loading @@ -191,26 +147,17 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu, u8 old = vgpu_cfg_space(vgpu)[offset]; u8 new = *(u8 *)p_data; u8 changed = old ^ new; int ret; vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); if (!(changed & PCI_COMMAND_MEMORY)) return 0; if (old & PCI_COMMAND_MEMORY) { ret = trap_gttmmio(vgpu, false); if (ret) return ret; ret = map_aperture(vgpu, false); if (ret) return ret; trap_gttmmio(vgpu, false); map_aperture(vgpu, false); } else { ret = trap_gttmmio(vgpu, true); if (ret) return ret; ret = map_aperture(vgpu, true); if (ret) return ret; trap_gttmmio(vgpu, true); map_aperture(vgpu, true); } return 0; Loading @@ -230,13 +177,12 @@ static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu, return 0; } static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, static void emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { u32 new = *(u32 *)(p_data); bool lo = IS_ALIGNED(offset, 8); u64 size; int ret = 0; bool mmio_enabled = vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY; struct intel_vgpu_pci_bar *bars = vgpu->cfg_space.bar; Loading @@ -259,14 +205,14 @@ static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, * Untrap the BAR, since guest hasn't configured a * valid GPA */ ret = trap_gttmmio(vgpu, false); trap_gttmmio(vgpu, false); break; case PCI_BASE_ADDRESS_2: case PCI_BASE_ADDRESS_3: size = ~(bars[INTEL_GVT_PCI_BAR_APERTURE].size -1); intel_vgpu_write_pci_bar(vgpu, offset, size >> (lo ? 0 : 32), lo); ret = map_aperture(vgpu, false); map_aperture(vgpu, false); break; default: /* Unimplemented BARs */ Loading @@ -282,19 +228,18 @@ static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, */ trap_gttmmio(vgpu, false); intel_vgpu_write_pci_bar(vgpu, offset, new, lo); ret = trap_gttmmio(vgpu, mmio_enabled); trap_gttmmio(vgpu, mmio_enabled); break; case PCI_BASE_ADDRESS_2: case PCI_BASE_ADDRESS_3: map_aperture(vgpu, false); intel_vgpu_write_pci_bar(vgpu, offset, new, lo); ret = map_aperture(vgpu, mmio_enabled); map_aperture(vgpu, mmio_enabled); break; default: intel_vgpu_write_pci_bar(vgpu, offset, new, lo); } } return ret; } /** Loading Loading @@ -336,8 +281,8 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5: if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) return -EINVAL; return emulate_pci_bar_write(vgpu, offset, p_data, bytes); emulate_pci_bar_write(vgpu, offset, p_data, bytes); break; case INTEL_GVT_PCI_SWSCI: if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) return -EINVAL; Loading Loading
Documentation/driver-api/vfio-mediated-device.rst +5 −22 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ structure to represent a mediated device's driver:: struct mdev_driver { int (*probe) (struct mdev_device *dev); void (*remove) (struct mdev_device *dev); struct attribute_group **supported_type_groups; struct device_driver driver; }; Loading @@ -119,33 +120,15 @@ to register and unregister itself with the core driver: extern void mdev_unregister_driver(struct mdev_driver *drv); The mediated bus driver is responsible for adding mediated devices to the VFIO group when devices are bound to the driver and removing mediated devices from the VFIO when devices are unbound from the driver. Physical Device Driver Interface -------------------------------- The physical device driver interface provides the mdev_parent_ops[3] structure to define the APIs to manage work in the mediated core driver that is related to the physical device. The structures in the mdev_parent_ops structure are as follows: * dev_attr_groups: attributes of the parent device * mdev_attr_groups: attributes of the mediated device * supported_config: attributes to define supported configurations * device_driver: device driver to bind for mediated device instances The mdev_parent_ops also still has various functions pointers. Theses exist for historical reasons only and shall not be used for new drivers. The mediated bus driver's probe function should create a vfio_device on top of the mdev_device and connect it to an appropriate implementation of vfio_device_ops. When a driver wants to add the GUID creation sysfs to an existing device it has probe'd to then it should call:: extern int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops); struct mdev_driver *mdev_driver); This will provide the 'mdev_supported_types/XX/create' files which can then be used to trigger the creation of a mdev_device. The created mdev_device will be Loading
drivers/gpu/drm/i915/Kconfig +13 −23 Original line number Diff line number Diff line Loading @@ -102,40 +102,30 @@ config DRM_I915_USERPTR If in doubt, say "Y". config DRM_I915_GVT bool "Enable Intel GVT-g graphics virtualization host support" bool config DRM_I915_GVT_KVMGT tristate "Enable KVM host support Intel GVT-g graphics virtualization" depends on DRM_I915 depends on X86 depends on 64BIT default n depends on KVM depends on VFIO_MDEV select DRM_I915_GVT select KVM_EXTERNAL_WRITE_TRACKING help Choose this option if you want to enable Intel GVT-g graphics virtualization technology host support with integrated graphics. With GVT-g, it's possible to have one integrated graphics device shared by multiple VMs under different hypervisors. Note that at least one hypervisor like Xen or KVM is required for this driver to work, and it only supports newer device from Broadwell+. For further information and setup guide, you can visit: http://01.org/igvt-g. device shared by multiple VMs under KVM. Now it's just a stub to support the modifications of i915 for GVT device model. It requires at least one MPT modules for Xen/KVM and other components of GVT device model to work. Use it under you own risk. Note that this driver only supports newer device from Broadwell on. For further information and setup guide, you can visit: http://01.org/igvt-g. If in doubt, say "N". config DRM_I915_GVT_KVMGT tristate "Enable KVM/VFIO support for Intel GVT-g" depends on DRM_I915_GVT depends on KVM depends on VFIO_MDEV select KVM_EXTERNAL_WRITE_TRACKING default n help Choose this option if you want to enable KVMGT support for Intel GVT-g. config DRM_I915_PXP bool "Enable Intel PXP support" depends on DRM_I915 Loading
drivers/gpu/drm/i915/Makefile +4 −4 Original line number Diff line number Diff line Loading @@ -320,13 +320,13 @@ i915-$(CONFIG_DRM_I915_SELFTEST) += \ # virtual gpu code i915-y += i915_vgpu.o ifeq ($(CONFIG_DRM_I915_GVT),y) i915-y += intel_gvt.o i915-$(CONFIG_DRM_I915_GVT) += \ intel_gvt.o \ intel_gvt_mmio_table.o include $(src)/gvt/Makefile endif obj-$(CONFIG_DRM_I915) += i915.o obj-$(CONFIG_DRM_I915_GVT_KVMGT) += gvt/kvmgt.o obj-$(CONFIG_DRM_I915_GVT_KVMGT) += kvmgt.o # header test Loading
drivers/gpu/drm/i915/gvt/Makefile +23 −7 Original line number Diff line number Diff line # SPDX-License-Identifier: GPL-2.0 GVT_DIR := gvt GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ execlist.o scheduler.o sched_policy.o mmio_context.o cmd_parser.o debugfs.o \ fb_decoder.o dmabuf.o page_track.o ccflags-y += -I $(srctree)/$(src) -I $(srctree)/$(src)/$(GVT_DIR)/ i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) kvmgt-$(CONFIG_DRM_I915_GVT) += \ gvt/aperture_gm.o \ gvt/cfg_space.o \ gvt/cmd_parser.o \ gvt/debugfs.o \ gvt/display.o \ gvt/dmabuf.o \ gvt/edid.o \ gvt/execlist.o \ gvt/fb_decoder.o \ gvt/firmware.o \ gvt/gtt.o \ gvt/handlers.o \ gvt/interrupt.o \ gvt/kvmgt.o \ gvt/mmio.o \ gvt/mmio_context.o \ gvt/opregion.o \ gvt/page_track.o \ gvt/sched_policy.o \ gvt/scheduler.o \ gvt/trace_points.o \ gvt/vgpu.o
drivers/gpu/drm/i915/gvt/cfg_space.c +17 −72 Original line number Diff line number Diff line Loading @@ -129,60 +129,16 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, return 0; } static int map_aperture(struct intel_vgpu *vgpu, bool map) static void map_aperture(struct intel_vgpu *vgpu, bool map) { phys_addr_t aperture_pa = vgpu_aperture_pa_base(vgpu); unsigned long aperture_sz = vgpu_aperture_sz(vgpu); u64 first_gfn; u64 val; int ret; if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) return 0; val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2]; if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); else val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT; ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn, aperture_pa >> PAGE_SHIFT, aperture_sz >> PAGE_SHIFT, map); if (ret) return ret; if (map != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; return 0; } static int trap_gttmmio(struct intel_vgpu *vgpu, bool trap) static void trap_gttmmio(struct intel_vgpu *vgpu, bool trap) { u64 start, end; u64 val; int ret; if (trap == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked) return 0; val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_0]; if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) start = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); else start = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); start &= ~GENMASK(3, 0); end = start + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size - 1; ret = intel_gvt_hypervisor_set_trap_area(vgpu, start, end, trap); if (ret) return ret; if (trap != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked) vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap; return 0; } static int emulate_pci_command_write(struct intel_vgpu *vgpu, Loading @@ -191,26 +147,17 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu, u8 old = vgpu_cfg_space(vgpu)[offset]; u8 new = *(u8 *)p_data; u8 changed = old ^ new; int ret; vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); if (!(changed & PCI_COMMAND_MEMORY)) return 0; if (old & PCI_COMMAND_MEMORY) { ret = trap_gttmmio(vgpu, false); if (ret) return ret; ret = map_aperture(vgpu, false); if (ret) return ret; trap_gttmmio(vgpu, false); map_aperture(vgpu, false); } else { ret = trap_gttmmio(vgpu, true); if (ret) return ret; ret = map_aperture(vgpu, true); if (ret) return ret; trap_gttmmio(vgpu, true); map_aperture(vgpu, true); } return 0; Loading @@ -230,13 +177,12 @@ static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu, return 0; } static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, static void emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { u32 new = *(u32 *)(p_data); bool lo = IS_ALIGNED(offset, 8); u64 size; int ret = 0; bool mmio_enabled = vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY; struct intel_vgpu_pci_bar *bars = vgpu->cfg_space.bar; Loading @@ -259,14 +205,14 @@ static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, * Untrap the BAR, since guest hasn't configured a * valid GPA */ ret = trap_gttmmio(vgpu, false); trap_gttmmio(vgpu, false); break; case PCI_BASE_ADDRESS_2: case PCI_BASE_ADDRESS_3: size = ~(bars[INTEL_GVT_PCI_BAR_APERTURE].size -1); intel_vgpu_write_pci_bar(vgpu, offset, size >> (lo ? 0 : 32), lo); ret = map_aperture(vgpu, false); map_aperture(vgpu, false); break; default: /* Unimplemented BARs */ Loading @@ -282,19 +228,18 @@ static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, */ trap_gttmmio(vgpu, false); intel_vgpu_write_pci_bar(vgpu, offset, new, lo); ret = trap_gttmmio(vgpu, mmio_enabled); trap_gttmmio(vgpu, mmio_enabled); break; case PCI_BASE_ADDRESS_2: case PCI_BASE_ADDRESS_3: map_aperture(vgpu, false); intel_vgpu_write_pci_bar(vgpu, offset, new, lo); ret = map_aperture(vgpu, mmio_enabled); map_aperture(vgpu, mmio_enabled); break; default: intel_vgpu_write_pci_bar(vgpu, offset, new, lo); } } return ret; } /** Loading Loading @@ -336,8 +281,8 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5: if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) return -EINVAL; return emulate_pci_bar_write(vgpu, offset, p_data, bytes); emulate_pci_bar_write(vgpu, offset, p_data, bytes); break; case INTEL_GVT_PCI_SWSCI: if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) return -EINVAL; Loading