2013-09-09 10:02:56 +10:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 Red Hat, Inc.
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Dave Airlie <airlied@redhat.com>
|
|
|
|
* Gerd Hoffmann <kraxel@redhat.com>
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2024-09-30 15:03:23 +02:00
|
|
|
#include <linux/aperture.h>
|
2013-09-09 10:02:56 +10:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/pci.h>
|
2021-09-21 16:20:23 -07:00
|
|
|
#include <linux/poll.h>
|
drm/virtio: Lock the VGA resources during initialization
If another driver for a VGA compatible GPU (that is passthrough'd)
locks the VGA resources (by calling vga_get()), then virtio_gpu
driver would encounter the following errors and fail to load during
probe and initialization:
Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected
Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected
virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1
virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22
This issue is only seen if virtio-gpu and the other GPU are on
different PCI buses, which can happen if the user includes an
additional PCIe port and associates the VGA compatible GPU with
it while launching Qemu:
qemu-system-x86_64...
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on
-device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ...
In the above example, the device 03:00.0 is an Intel DG2 card and
this issue is seen when both i915 driver and virtio_gpu driver are
loading (or initializing) concurrently or when i915 is loaded first.
Note that during initalization, i915 driver does the following in
intel_vga_reset_io_mem():
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MIS_R), VGA_MIS_W);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
Although, virtio-gpu might own the VGA resources initially, the
above call (in i915) to vga_get_uninterruptible() would result in
these resources being taken away, which means that virtio-gpu would
not be able to decode VGA anymore. This happens in __vga_tryget()
when it calls
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
where
pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO
flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE
Therefore, to solve this issue, virtio-gpu driver needs to call
vga_get() whenever it needs to reclaim and access VGA resources,
which is during initial probe and setup. After that, a call to
vga_put() would release the lock to allow other VGA compatible
devices to access these shared VGA resources.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Reported-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
2024-12-10 22:43:43 -08:00
|
|
|
#include <linux/vgaarb.h>
|
2021-09-21 16:20:23 -07:00
|
|
|
#include <linux/wait.h>
|
2019-06-30 08:19:16 +02:00
|
|
|
|
2024-11-08 16:42:38 +01:00
|
|
|
#include <drm/clients/drm_client_setup.h>
|
2017-04-24 13:50:34 +09:00
|
|
|
#include <drm/drm.h>
|
2020-02-11 14:58:04 +01:00
|
|
|
#include <drm/drm_atomic_helper.h>
|
2019-06-30 08:19:16 +02:00
|
|
|
#include <drm/drm_drv.h>
|
2024-04-19 10:29:12 +02:00
|
|
|
#include <drm/drm_fbdev_shmem.h>
|
2019-06-30 08:19:16 +02:00
|
|
|
#include <drm/drm_file.h>
|
2013-09-09 10:02:56 +10:00
|
|
|
|
|
|
|
#include "virtgpu_drv.h"
|
2019-06-30 08:19:16 +02:00
|
|
|
|
drm/virtio: Lock the VGA resources during initialization
If another driver for a VGA compatible GPU (that is passthrough'd)
locks the VGA resources (by calling vga_get()), then virtio_gpu
driver would encounter the following errors and fail to load during
probe and initialization:
Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected
Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected
virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1
virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22
This issue is only seen if virtio-gpu and the other GPU are on
different PCI buses, which can happen if the user includes an
additional PCIe port and associates the VGA compatible GPU with
it while launching Qemu:
qemu-system-x86_64...
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on
-device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ...
In the above example, the device 03:00.0 is an Intel DG2 card and
this issue is seen when both i915 driver and virtio_gpu driver are
loading (or initializing) concurrently or when i915 is loaded first.
Note that during initalization, i915 driver does the following in
intel_vga_reset_io_mem():
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MIS_R), VGA_MIS_W);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
Although, virtio-gpu might own the VGA resources initially, the
above call (in i915) to vga_get_uninterruptible() would result in
these resources being taken away, which means that virtio-gpu would
not be able to decode VGA anymore. This happens in __vga_tryget()
when it calls
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
where
pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO
flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE
Therefore, to solve this issue, virtio-gpu driver needs to call
vga_get() whenever it needs to reclaim and access VGA resources,
which is during initial probe and setup. After that, a call to
vga_put() would release the lock to allow other VGA compatible
devices to access these shared VGA resources.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Reported-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
2024-12-10 22:43:43 -08:00
|
|
|
#define PCI_DEVICE_ID_VIRTIO_GPU 0x1050
|
|
|
|
|
2020-11-04 11:04:24 +01:00
|
|
|
static const struct drm_driver driver;
|
2013-09-09 10:02:56 +10:00
|
|
|
|
|
|
|
static int virtio_gpu_modeset = -1;
|
|
|
|
|
|
|
|
MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
|
|
|
|
module_param_named(modeset, virtio_gpu_modeset, int, 0400);
|
|
|
|
|
2022-06-30 23:07:24 +03:00
|
|
|
static int virtio_gpu_pci_quirk(struct drm_device *dev)
|
2019-01-08 11:59:30 -03:00
|
|
|
{
|
2022-06-30 23:07:24 +03:00
|
|
|
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
2019-01-08 11:59:30 -03:00
|
|
|
const char *pname = dev_name(&pdev->dev);
|
2023-08-30 19:15:31 +08:00
|
|
|
bool vga = pci_is_vga(pdev);
|
2021-04-12 15:10:42 +02:00
|
|
|
int ret;
|
2019-01-08 11:59:30 -03:00
|
|
|
|
|
|
|
DRM_INFO("pci: %s detected at %s\n",
|
|
|
|
vga ? "virtio-vga" : "virtio-gpu-pci",
|
|
|
|
pname);
|
2021-04-12 15:10:42 +02:00
|
|
|
if (vga) {
|
2024-09-30 15:03:23 +02:00
|
|
|
ret = aperture_remove_conflicting_pci_devices(pdev, driver.name);
|
2021-04-12 15:10:42 +02:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
2019-01-08 11:59:30 -03:00
|
|
|
|
2022-06-30 23:07:24 +03:00
|
|
|
return 0;
|
2019-01-08 11:59:30 -03:00
|
|
|
}
|
|
|
|
|
2013-09-09 10:02:56 +10:00
|
|
|
static int virtio_gpu_probe(struct virtio_device *vdev)
|
|
|
|
{
|
2019-01-08 11:59:30 -03:00
|
|
|
struct drm_device *dev;
|
2018-12-13 14:49:15 +01:00
|
|
|
int ret;
|
|
|
|
|
2021-11-12 14:32:27 +01:00
|
|
|
if (drm_firmware_drivers_only() && virtio_gpu_modeset == -1)
|
2013-09-09 10:02:56 +10:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (virtio_gpu_modeset == 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2022-06-30 23:07:24 +03:00
|
|
|
/*
|
|
|
|
* The virtio-gpu device is a virtual device that doesn't have DMA
|
|
|
|
* ops assigned to it, nor DMA mask set and etc. Its parent device
|
|
|
|
* is actual GPU device we want to use it for the DRM's device in
|
|
|
|
* order to benefit from using generic DRM APIs.
|
|
|
|
*/
|
|
|
|
dev = drm_dev_alloc(&driver, vdev->dev.parent);
|
2019-01-08 11:59:30 -03:00
|
|
|
if (IS_ERR(dev))
|
|
|
|
return PTR_ERR(dev);
|
|
|
|
vdev->priv = dev;
|
|
|
|
|
2022-06-30 23:07:25 +03:00
|
|
|
if (dev_is_pci(vdev->dev.parent)) {
|
2022-06-30 23:07:24 +03:00
|
|
|
ret = virtio_gpu_pci_quirk(dev);
|
2019-01-08 11:59:30 -03:00
|
|
|
if (ret)
|
|
|
|
goto err_free;
|
|
|
|
}
|
|
|
|
|
2024-01-23 19:14:14 +01:00
|
|
|
dma_set_max_seg_size(dev->dev, dma_max_mapping_size(dev->dev) ?: UINT_MAX);
|
2022-06-30 23:07:24 +03:00
|
|
|
ret = virtio_gpu_init(vdev, dev);
|
2018-12-13 14:49:15 +01:00
|
|
|
if (ret)
|
2019-01-08 11:59:30 -03:00
|
|
|
goto err_free;
|
|
|
|
|
|
|
|
ret = drm_dev_register(dev, 0);
|
|
|
|
if (ret)
|
2021-05-17 16:49:13 +08:00
|
|
|
goto err_deinit;
|
2018-12-13 14:49:15 +01:00
|
|
|
|
2024-09-24 09:12:59 +02:00
|
|
|
drm_client_setup(vdev->priv, NULL);
|
|
|
|
|
2018-12-13 14:49:15 +01:00
|
|
|
return 0;
|
2019-01-08 11:59:30 -03:00
|
|
|
|
2021-05-17 16:49:13 +08:00
|
|
|
err_deinit:
|
|
|
|
virtio_gpu_deinit(dev);
|
2019-01-08 11:59:30 -03:00
|
|
|
err_free:
|
|
|
|
drm_dev_put(dev);
|
|
|
|
return ret;
|
2013-09-09 10:02:56 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void virtio_gpu_remove(struct virtio_device *vdev)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = vdev->priv;
|
2018-02-22 21:00:00 -03:00
|
|
|
|
2020-02-11 14:58:04 +01:00
|
|
|
drm_dev_unplug(dev);
|
|
|
|
drm_atomic_helper_shutdown(dev);
|
2019-01-08 11:59:30 -03:00
|
|
|
virtio_gpu_deinit(dev);
|
2019-11-09 15:54:17 +08:00
|
|
|
drm_dev_put(dev);
|
2013-09-09 10:02:56 +10:00
|
|
|
}
|
|
|
|
|
2025-04-10 03:16:26 -04:00
|
|
|
static void virtio_gpu_shutdown(struct virtio_device *vdev)
|
|
|
|
{
|
2025-05-07 10:28:21 +02:00
|
|
|
struct drm_device *dev = vdev->priv;
|
|
|
|
|
|
|
|
/* stop talking to the device */
|
|
|
|
drm_dev_unplug(dev);
|
2025-04-10 03:16:26 -04:00
|
|
|
}
|
|
|
|
|
2013-09-09 10:02:56 +10:00
|
|
|
static void virtio_gpu_config_changed(struct virtio_device *vdev)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = vdev->priv;
|
|
|
|
struct virtio_gpu_device *vgdev = dev->dev_private;
|
|
|
|
|
|
|
|
schedule_work(&vgdev->config_changed_work);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct virtio_device_id id_table[] = {
|
|
|
|
{ VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID },
|
|
|
|
{ 0 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static unsigned int features[] = {
|
2014-10-28 12:48:00 +01:00
|
|
|
#ifdef __LITTLE_ENDIAN
|
|
|
|
/*
|
|
|
|
* Gallium command stream send by virgl is native endian.
|
|
|
|
* Because of that we only support little endian guests on
|
|
|
|
* little endian hosts.
|
|
|
|
*/
|
|
|
|
VIRTIO_GPU_F_VIRGL,
|
|
|
|
#endif
|
2018-10-30 07:32:06 +01:00
|
|
|
VIRTIO_GPU_F_EDID,
|
2020-08-18 16:13:43 +09:00
|
|
|
VIRTIO_GPU_F_RESOURCE_UUID,
|
2020-09-23 17:32:03 -07:00
|
|
|
VIRTIO_GPU_F_RESOURCE_BLOB,
|
2021-09-21 16:20:16 -07:00
|
|
|
VIRTIO_GPU_F_CONTEXT_INIT,
|
2013-09-09 10:02:56 +10:00
|
|
|
};
|
|
|
|
static struct virtio_driver virtio_gpu_driver = {
|
|
|
|
.feature_table = features,
|
|
|
|
.feature_table_size = ARRAY_SIZE(features),
|
|
|
|
.driver.name = KBUILD_MODNAME,
|
|
|
|
.id_table = id_table,
|
|
|
|
.probe = virtio_gpu_probe,
|
|
|
|
.remove = virtio_gpu_remove,
|
2025-04-10 03:16:26 -04:00
|
|
|
.shutdown = virtio_gpu_shutdown,
|
2013-09-09 10:02:56 +10:00
|
|
|
.config_changed = virtio_gpu_config_changed
|
|
|
|
};
|
|
|
|
|
drm/virtio: Lock the VGA resources during initialization
If another driver for a VGA compatible GPU (that is passthrough'd)
locks the VGA resources (by calling vga_get()), then virtio_gpu
driver would encounter the following errors and fail to load during
probe and initialization:
Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected
Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected
virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1
virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22
This issue is only seen if virtio-gpu and the other GPU are on
different PCI buses, which can happen if the user includes an
additional PCIe port and associates the VGA compatible GPU with
it while launching Qemu:
qemu-system-x86_64...
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on
-device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ...
In the above example, the device 03:00.0 is an Intel DG2 card and
this issue is seen when both i915 driver and virtio_gpu driver are
loading (or initializing) concurrently or when i915 is loaded first.
Note that during initalization, i915 driver does the following in
intel_vga_reset_io_mem():
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MIS_R), VGA_MIS_W);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
Although, virtio-gpu might own the VGA resources initially, the
above call (in i915) to vga_get_uninterruptible() would result in
these resources being taken away, which means that virtio-gpu would
not be able to decode VGA anymore. This happens in __vga_tryget()
when it calls
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
where
pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO
flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE
Therefore, to solve this issue, virtio-gpu driver needs to call
vga_get() whenever it needs to reclaim and access VGA resources,
which is during initial probe and setup. After that, a call to
vga_put() would release the lock to allow other VGA compatible
devices to access these shared VGA resources.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Reported-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
2024-12-10 22:43:43 -08:00
|
|
|
static int __init virtio_gpu_driver_init(void)
|
|
|
|
{
|
|
|
|
struct pci_dev *pdev;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
pdev = pci_get_device(PCI_VENDOR_ID_REDHAT_QUMRANET,
|
|
|
|
PCI_DEVICE_ID_VIRTIO_GPU,
|
|
|
|
NULL);
|
2025-01-13 23:57:59 -08:00
|
|
|
if (pdev && pci_is_vga(pdev)) {
|
drm/virtio: Lock the VGA resources during initialization
If another driver for a VGA compatible GPU (that is passthrough'd)
locks the VGA resources (by calling vga_get()), then virtio_gpu
driver would encounter the following errors and fail to load during
probe and initialization:
Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected
Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected
virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1
virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22
This issue is only seen if virtio-gpu and the other GPU are on
different PCI buses, which can happen if the user includes an
additional PCIe port and associates the VGA compatible GPU with
it while launching Qemu:
qemu-system-x86_64...
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on
-device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ...
In the above example, the device 03:00.0 is an Intel DG2 card and
this issue is seen when both i915 driver and virtio_gpu driver are
loading (or initializing) concurrently or when i915 is loaded first.
Note that during initalization, i915 driver does the following in
intel_vga_reset_io_mem():
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MIS_R), VGA_MIS_W);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
Although, virtio-gpu might own the VGA resources initially, the
above call (in i915) to vga_get_uninterruptible() would result in
these resources being taken away, which means that virtio-gpu would
not be able to decode VGA anymore. This happens in __vga_tryget()
when it calls
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
where
pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO
flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE
Therefore, to solve this issue, virtio-gpu driver needs to call
vga_get() whenever it needs to reclaim and access VGA resources,
which is during initial probe and setup. After that, a call to
vga_put() would release the lock to allow other VGA compatible
devices to access these shared VGA resources.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Reported-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
2024-12-10 22:43:43 -08:00
|
|
|
ret = vga_get_interruptible(pdev,
|
|
|
|
VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
|
2025-01-13 23:57:59 -08:00
|
|
|
if (ret) {
|
|
|
|
pci_dev_put(pdev);
|
|
|
|
return ret;
|
|
|
|
}
|
drm/virtio: Lock the VGA resources during initialization
If another driver for a VGA compatible GPU (that is passthrough'd)
locks the VGA resources (by calling vga_get()), then virtio_gpu
driver would encounter the following errors and fail to load during
probe and initialization:
Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected
Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected
virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1
virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22
This issue is only seen if virtio-gpu and the other GPU are on
different PCI buses, which can happen if the user includes an
additional PCIe port and associates the VGA compatible GPU with
it while launching Qemu:
qemu-system-x86_64...
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on
-device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ...
In the above example, the device 03:00.0 is an Intel DG2 card and
this issue is seen when both i915 driver and virtio_gpu driver are
loading (or initializing) concurrently or when i915 is loaded first.
Note that during initalization, i915 driver does the following in
intel_vga_reset_io_mem():
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MIS_R), VGA_MIS_W);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
Although, virtio-gpu might own the VGA resources initially, the
above call (in i915) to vga_get_uninterruptible() would result in
these resources being taken away, which means that virtio-gpu would
not be able to decode VGA anymore. This happens in __vga_tryget()
when it calls
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
where
pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO
flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE
Therefore, to solve this issue, virtio-gpu driver needs to call
vga_get() whenever it needs to reclaim and access VGA resources,
which is during initial probe and setup. After that, a call to
vga_put() would release the lock to allow other VGA compatible
devices to access these shared VGA resources.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Reported-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
2024-12-10 22:43:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = register_virtio_driver(&virtio_gpu_driver);
|
|
|
|
|
2025-01-13 23:57:59 -08:00
|
|
|
if (pdev) {
|
|
|
|
if (pci_is_vga(pdev))
|
|
|
|
vga_put(pdev,
|
|
|
|
VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM);
|
drm/virtio: Lock the VGA resources during initialization
If another driver for a VGA compatible GPU (that is passthrough'd)
locks the VGA resources (by calling vga_get()), then virtio_gpu
driver would encounter the following errors and fail to load during
probe and initialization:
Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected
Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected
virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1
virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22
This issue is only seen if virtio-gpu and the other GPU are on
different PCI buses, which can happen if the user includes an
additional PCIe port and associates the VGA compatible GPU with
it while launching Qemu:
qemu-system-x86_64...
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on
-device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ...
In the above example, the device 03:00.0 is an Intel DG2 card and
this issue is seen when both i915 driver and virtio_gpu driver are
loading (or initializing) concurrently or when i915 is loaded first.
Note that during initalization, i915 driver does the following in
intel_vga_reset_io_mem():
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MIS_R), VGA_MIS_W);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
Although, virtio-gpu might own the VGA resources initially, the
above call (in i915) to vga_get_uninterruptible() would result in
these resources being taken away, which means that virtio-gpu would
not be able to decode VGA anymore. This happens in __vga_tryget()
when it calls
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
where
pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO
flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE
Therefore, to solve this issue, virtio-gpu driver needs to call
vga_get() whenever it needs to reclaim and access VGA resources,
which is during initial probe and setup. After that, a call to
vga_put() would release the lock to allow other VGA compatible
devices to access these shared VGA resources.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Reported-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
2024-12-10 22:43:43 -08:00
|
|
|
|
2025-01-13 23:57:59 -08:00
|
|
|
pci_dev_put(pdev);
|
|
|
|
}
|
drm/virtio: Lock the VGA resources during initialization
If another driver for a VGA compatible GPU (that is passthrough'd)
locks the VGA resources (by calling vga_get()), then virtio_gpu
driver would encounter the following errors and fail to load during
probe and initialization:
Invalid read at addr 0x7200005014, size 1, region '(null)', reason: rejected
Invalid write at addr 0x7200005014, size 1, region '(null)', reason: rejected
virtio_gpu virtio0: virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1
virtio_gpu virtio0: probe with driver virtio_gpu failed with error -22
This issue is only seen if virtio-gpu and the other GPU are on
different PCI buses, which can happen if the user includes an
additional PCIe port and associates the VGA compatible GPU with
it while launching Qemu:
qemu-system-x86_64...
-device virtio-vga,max_outputs=1,xres=1920,yres=1080,blob=true
-device pcie-root-port,id=pcie.1,bus=pcie.0,addr=1c.0,slot=1,chassis=1,multifunction=on
-device vfio-pci,host=03:00.0,bus=pcie.1,addr=00.0 ...
In the above example, the device 03:00.0 is an Intel DG2 card and
this issue is seen when both i915 driver and virtio_gpu driver are
loading (or initializing) concurrently or when i915 is loaded first.
Note that during initalization, i915 driver does the following in
intel_vga_reset_io_mem():
vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
outb(inb(VGA_MIS_R), VGA_MIS_W);
vga_put(pdev, VGA_RSRC_LEGACY_IO);
Although, virtio-gpu might own the VGA resources initially, the
above call (in i915) to vga_get_uninterruptible() would result in
these resources being taken away, which means that virtio-gpu would
not be able to decode VGA anymore. This happens in __vga_tryget()
when it calls
pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
where
pci_bits = PCI_COMMAND_MEMORY | PCI_COMMAND_IO
flags = PCI_VGA_STATE_CHANGE_DECODES | PCI_VGA_STATE_CHANGE_BRIDGE
Therefore, to solve this issue, virtio-gpu driver needs to call
vga_get() whenever it needs to reclaim and access VGA resources,
which is during initial probe and setup. After that, a call to
vga_put() would release the lock to allow other VGA compatible
devices to access these shared VGA resources.
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gurchetan Singh <gurchetansingh@chromium.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Reported-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241211064343.550153-1-vivek.kasireddy@intel.com
Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
2024-12-10 22:43:43 -08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit virtio_gpu_driver_exit(void)
|
|
|
|
{
|
|
|
|
unregister_virtio_driver(&virtio_gpu_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
module_init(virtio_gpu_driver_init);
|
|
|
|
module_exit(virtio_gpu_driver_exit);
|
2013-09-09 10:02:56 +10:00
|
|
|
|
|
|
|
MODULE_DEVICE_TABLE(virtio, id_table);
|
|
|
|
MODULE_DESCRIPTION("Virtio GPU driver");
|
|
|
|
MODULE_LICENSE("GPL and additional rights");
|
|
|
|
MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>");
|
|
|
|
MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
|
|
|
|
MODULE_AUTHOR("Alon Levy");
|
|
|
|
|
2021-11-22 15:22:10 -08:00
|
|
|
DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops);
|
2013-09-09 10:02:56 +10:00
|
|
|
|
2020-11-04 11:04:24 +01:00
|
|
|
static const struct drm_driver driver = {
|
2023-03-02 15:35:06 -08:00
|
|
|
/*
|
|
|
|
* If KMS is disabled DRIVER_MODESET and DRIVER_ATOMIC are masked
|
|
|
|
* out via drm_device::driver_features:
|
|
|
|
*/
|
2023-03-24 02:07:55 +03:00
|
|
|
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC |
|
2023-10-23 09:46:05 +02:00
|
|
|
DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE | DRIVER_CURSOR_HOTSPOT,
|
2014-10-28 12:48:00 +01:00
|
|
|
.open = virtio_gpu_driver_open,
|
|
|
|
.postclose = virtio_gpu_driver_postclose,
|
2013-09-09 10:02:56 +10:00
|
|
|
|
|
|
|
.dumb_create = virtio_gpu_mode_dumb_create,
|
|
|
|
|
2024-09-24 09:12:59 +02:00
|
|
|
DRM_FBDEV_SHMEM_DRIVER_OPS,
|
|
|
|
|
2013-09-09 10:02:56 +10:00
|
|
|
#if defined(CONFIG_DEBUG_FS)
|
|
|
|
.debugfs_init = virtio_gpu_debugfs_init,
|
|
|
|
#endif
|
2020-08-18 16:13:43 +09:00
|
|
|
.gem_prime_import = virtgpu_gem_prime_import,
|
2019-04-24 10:52:20 +10:00
|
|
|
.gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
|
2013-09-09 10:02:56 +10:00
|
|
|
|
2019-08-29 12:32:57 +02:00
|
|
|
.gem_create_object = virtio_gpu_create_object,
|
2013-09-09 10:02:56 +10:00
|
|
|
.fops = &virtio_gpu_driver_fops,
|
|
|
|
|
2014-10-28 12:48:00 +01:00
|
|
|
.ioctls = virtio_gpu_ioctls,
|
|
|
|
.num_ioctls = DRM_VIRTIO_NUM_IOCTLS,
|
|
|
|
|
2013-09-09 10:02:56 +10:00
|
|
|
.name = DRIVER_NAME,
|
|
|
|
.desc = DRIVER_DESC,
|
|
|
|
.major = DRIVER_MAJOR,
|
|
|
|
.minor = DRIVER_MINOR,
|
|
|
|
.patchlevel = DRIVER_PATCHLEVEL,
|
2020-02-11 14:58:04 +01:00
|
|
|
|
|
|
|
.release = virtio_gpu_release,
|
2013-09-09 10:02:56 +10:00
|
|
|
};
|