On Tue, 22 Apr 2025 00:31:03 +0800
Tomita Moeko <tomitamo...@gmail.com> wrote:

> There is currently no straightforward way to distinguish if a Intel
> graphics device is IGD or discrete GPU. However, only IGD devices expose
> OpRegion. Use the presence of VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION
> to identify IGD devices.
> 
> Signed-off-by: Tomita Moeko <tomitamo...@gmail.com>
> ---
>  hw/vfio/igd.c | 26 ++++++++++++++++++--------
>  1 file changed, 18 insertions(+), 8 deletions(-)
> 
> diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
> index 36316e50ea..7a7c7735c1 100644
> --- a/hw/vfio/igd.c
> +++ b/hw/vfio/igd.c
> @@ -479,6 +479,7 @@ void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int 
> nr)
>  
>  static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
>  {
> +    g_autofree struct vfio_region_info *opregion = NULL;
>      int ret, gen;
>      uint64_t gms_size;
>      uint64_t *bdsm_size;
> @@ -486,16 +487,20 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice 
> *vdev, Error **errp)
>      bool legacy_mode_enabled = false;
>      Error *err = NULL;
>  
> -    /*
> -     * This must be an Intel VGA device at address 00:02.0 for us to even
> -     * consider enabling legacy mode.  The vBIOS has dependencies on the
> -     * PCI bus address.
> -     */
>      if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
>          !vfio_is_vga(vdev)) {
>          return true;
>      }
>  
> +    /* IGD device always comes with OpRegion */
> +    ret = vfio_device_get_region_info_type(&vdev->vbasedev,
> +                    VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
> +                    VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion);
> +    if (ret) {
> +        return true;
> +    }
> +    info_report("OpRegion detected on Intel display %x.", vdev->device_id);
> +
>      /*
>       * IGD is not a standard, they like to change their specs often.  We
>       * only attempt to support back to SandBridge and we hope that newer
> @@ -570,9 +575,14 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice 
> *vdev, Error **errp)
>      }
>  
>      /* Setup OpRegion access */
> -    if ((vdev->features & VFIO_FEATURE_ENABLE_IGD_OPREGION) &&
> -        !vfio_pci_igd_setup_opregion(vdev, errp)) {
> -        goto error;
> +    if ((vdev->features & VFIO_FEATURE_ENABLE_IGD_OPREGION)) {
> +        if (vdev->pdev.qdev.hotplugged) {
> +            error_setg(errp, "OpRegion is not supported on hotplugged 
> device");
> +            goto error;
> +        }
> +        if (!vfio_pci_igd_opregion_init(vdev, opregion, errp)) {
> +            goto error;
> +        }
>      }
>  
>      /* Setup LPC bridge / Host bridge PCI IDs */

I think this still needs some refactoring work.  The setup function
currently does:
 a) test hotplugged
 b) get opregion
 c) call init

We implemented b) above and therefore do a) and c) here, duplicating
them from the setup function.  It would be valid to test a) as we're
getting the opregion, so wouldn't it make sense to turn setup into a
function that does a) and b), returning an opregion, called by both
this path and GVT-g path, and each would call the init function
themselves?  The latter is already implemented in the next patch, but
a) and b) are still duplicated in GVT-g specific code.  Thanks,

Alex


Reply via email to