diff mbox series

[RFC,01/10] virtio: get class_id and pci device id by the virtio id

Message ID 20220105005900.860-2-longpeng2@huawei.com (mailing list archive)
State New, archived
Headers show
Series add generic vDPA device support | expand

Commit Message

Zhijian Li (Fujitsu)" via Jan. 5, 2022, 12:58 a.m. UTC
From: Longpeng <longpeng2@huawei.com>

Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
deivce which is specificed by the "Virtio Device ID".

These helpers will be used to build the generic vDPA device later.

Signed-off-by: Longpeng <longpeng2@huawei.com>
---
 hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
 hw/virtio/virtio-pci.h |  4 ++
 2 files changed, 97 insertions(+)

Comments

Jason Wang Jan. 5, 2022, 4:37 a.m. UTC | #1
On Wed, Jan 5, 2022 at 8:59 AM Longpeng(Mike) <longpeng2@huawei.com> wrote:
>
> From: Longpeng <longpeng2@huawei.com>
>
> Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> deivce which is specificed by the "Virtio Device ID".
>
> These helpers will be used to build the generic vDPA device later.
>
> Signed-off-by: Longpeng <longpeng2@huawei.com>
> ---
>  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
>  hw/virtio/virtio-pci.h |  4 ++
>  2 files changed, 97 insertions(+)
>
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 750aa47ec1..843085c4ea 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -19,6 +19,7 @@
>
>  #include "exec/memop.h"
>  #include "standard-headers/linux/virtio_pci.h"
> +#include "standard-headers/linux/virtio_ids.h"
>  #include "hw/boards.h"
>  #include "hw/virtio/virtio.h"
>  #include "migration/qemu-file-types.h"
> @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
>      return 0;
>  }
>
> +typedef struct VirtIOPCIIDInfo {
> +    uint16_t vdev_id; /* virtio id */
> +    uint16_t pdev_id; /* pci device id */
> +    uint16_t class_id;
> +} VirtIOPCIIDInfo;
> +
> +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> +    {

Any way to get rid of this array? E.g using the algorithm that is used
by the kernel virtio driver.

Thanks

> +        .vdev_id = VIRTIO_ID_NET,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_BLOCK,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> +        .class_id = PCI_CLASS_STORAGE_SCSI,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_CONSOLE,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_SCSI,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> +        .class_id = PCI_CLASS_STORAGE_SCSI,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_9P,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> +        .class_id = PCI_BASE_CLASS_NETWORK,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_VSOCK,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_IOMMU,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_MEM,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_PMEM,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_RNG,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_BALLOON,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +};
> +
> +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> +{
> +    VirtIOPCIIDInfo info = {};
> +    int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> +            info = virtio_pci_id_info[i];
> +            break;
> +        }
> +    }
> +
> +    return info;
> +}
> +
> +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> +{
> +    return virtio_pci_get_id_info(device_id).pdev_id;
> +}
> +
> +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> +{
> +    return virtio_pci_get_id_info(device_id).class_id;
> +}
> +
>  static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
>  {
>      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> @@ -1674,6 +1764,9 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
>           * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
>           */
>          pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus));
> +        if (proxy->pdev_id) {
> +            pci_config_set_device_id(config, proxy->pdev_id);
> +        }
>      } else {
>          /* pure virtio-1.0 */
>          pci_set_word(config + PCI_VENDOR_ID,
> diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> index 2446dcd9ae..06aa59436e 100644
> --- a/hw/virtio/virtio-pci.h
> +++ b/hw/virtio/virtio-pci.h
> @@ -146,6 +146,7 @@ struct VirtIOPCIProxy {
>      bool disable_modern;
>      bool ignore_backend_features;
>      OnOffAuto disable_legacy;
> +    uint16_t pdev_id;
>      uint32_t class_code;
>      uint32_t nvectors;
>      uint32_t dfselect;
> @@ -158,6 +159,9 @@ struct VirtIOPCIProxy {
>      VirtioBusState bus;
>  };
>
> +uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
> +uint16_t virtio_pci_get_class_id(uint16_t device_id);
> +
>  static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
>  {
>      return !proxy->disable_modern;
> --
> 2.23.0
>
Zhijian Li (Fujitsu)" via Jan. 5, 2022, 5:47 a.m. UTC | #2
> -----Original Message-----
> From: Jason Wang [mailto:jasowang@redhat.com]
> Sent: Wednesday, January 5, 2022 12:38 PM
> To: Longpeng (Mike, Cloud Infrastructure Service Product Dept.)
> <longpeng2@huawei.com>
> Cc: Stefan Hajnoczi <stefanha@redhat.com>; mst <mst@redhat.com>; Stefano
> Garzarella <sgarzare@redhat.com>; Cornelia Huck <cohuck@redhat.com>; pbonzini
> <pbonzini@redhat.com>; Gonglei (Arei) <arei.gonglei@huawei.com>; Yechuan
> <yechuan@huawei.com>; Huangzhichao <huangzhichao@huawei.com>; qemu-devel
> <qemu-devel@nongnu.org>
> Subject: Re: [RFC 01/10] virtio: get class_id and pci device id by the virtio
> id
> 
> On Wed, Jan 5, 2022 at 8:59 AM Longpeng(Mike) <longpeng2@huawei.com> wrote:
> >
> > From: Longpeng <longpeng2@huawei.com>
> >
> > Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> > deivce which is specificed by the "Virtio Device ID".
> >
> > These helpers will be used to build the generic vDPA device later.
> >
> > Signed-off-by: Longpeng <longpeng2@huawei.com>
> > ---
> >  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
> >  hw/virtio/virtio-pci.h |  4 ++
> >  2 files changed, 97 insertions(+)
> >
> > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > index 750aa47ec1..843085c4ea 100644
> > --- a/hw/virtio/virtio-pci.c
> > +++ b/hw/virtio/virtio-pci.c
> > @@ -19,6 +19,7 @@
> >
> >  #include "exec/memop.h"
> >  #include "standard-headers/linux/virtio_pci.h"
> > +#include "standard-headers/linux/virtio_ids.h"
> >  #include "hw/boards.h"
> >  #include "hw/virtio/virtio.h"
> >  #include "migration/qemu-file-types.h"
> > @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n,
> QEMUFile *f)
> >      return 0;
> >  }
> >
> > +typedef struct VirtIOPCIIDInfo {
> > +    uint16_t vdev_id; /* virtio id */
> > +    uint16_t pdev_id; /* pci device id */
> > +    uint16_t class_id;
> > +} VirtIOPCIIDInfo;
> > +
> > +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> > +    {
> 
> Any way to get rid of this array? E.g using the algorithm that is used
> by the kernel virtio driver.
> 

For device id, we can use the algorithm if we no need to support
Transitional id. But how to get the class id ?

> Thanks
> 
> > +        .vdev_id = VIRTIO_ID_NET,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> > +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_BLOCK,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_CONSOLE,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_SCSI,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_9P,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> > +        .class_id = PCI_BASE_CLASS_NETWORK,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_VSOCK,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_IOMMU,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_MEM,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_PMEM,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_RNG,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_BALLOON,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +};
> > +
> > +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> > +{
> > +    VirtIOPCIIDInfo info = {};
> > +    int i;
> > +
> > +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> > +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> > +            info = virtio_pci_id_info[i];
> > +            break;
> > +        }
> > +    }
> > +
> > +    return info;
> > +}
> > +
> > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> > +{
> > +    return virtio_pci_get_id_info(device_id).pdev_id;
> > +}
> > +
> > +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> > +{
> > +    return virtio_pci_get_id_info(device_id).class_id;
> > +}
> > +
> >  static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
> >  {
> >      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> > @@ -1674,6 +1764,9 @@ static void virtio_pci_device_plugged(DeviceState *d,
> Error **errp)
> >           * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
> >           */
> >          pci_set_word(config + PCI_SUBSYSTEM_ID,
> virtio_bus_get_vdev_id(bus));
> > +        if (proxy->pdev_id) {
> > +            pci_config_set_device_id(config, proxy->pdev_id);
> > +        }
> >      } else {
> >          /* pure virtio-1.0 */
> >          pci_set_word(config + PCI_VENDOR_ID,
> > diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> > index 2446dcd9ae..06aa59436e 100644
> > --- a/hw/virtio/virtio-pci.h
> > +++ b/hw/virtio/virtio-pci.h
> > @@ -146,6 +146,7 @@ struct VirtIOPCIProxy {
> >      bool disable_modern;
> >      bool ignore_backend_features;
> >      OnOffAuto disable_legacy;
> > +    uint16_t pdev_id;
> >      uint32_t class_code;
> >      uint32_t nvectors;
> >      uint32_t dfselect;
> > @@ -158,6 +159,9 @@ struct VirtIOPCIProxy {
> >      VirtioBusState bus;
> >  };
> >
> > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
> > +uint16_t virtio_pci_get_class_id(uint16_t device_id);
> > +
> >  static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
> >  {
> >      return !proxy->disable_modern;
> > --
> > 2.23.0
> >
Jason Wang Jan. 5, 2022, 6:15 a.m. UTC | #3
On Wed, Jan 5, 2022 at 1:48 PM Longpeng (Mike, Cloud Infrastructure
Service Product Dept.) <longpeng2@huawei.com> wrote:
>
>
>
> > -----Original Message-----
> > From: Jason Wang [mailto:jasowang@redhat.com]
> > Sent: Wednesday, January 5, 2022 12:38 PM
> > To: Longpeng (Mike, Cloud Infrastructure Service Product Dept.)
> > <longpeng2@huawei.com>
> > Cc: Stefan Hajnoczi <stefanha@redhat.com>; mst <mst@redhat.com>; Stefano
> > Garzarella <sgarzare@redhat.com>; Cornelia Huck <cohuck@redhat.com>; pbonzini
> > <pbonzini@redhat.com>; Gonglei (Arei) <arei.gonglei@huawei.com>; Yechuan
> > <yechuan@huawei.com>; Huangzhichao <huangzhichao@huawei.com>; qemu-devel
> > <qemu-devel@nongnu.org>
> > Subject: Re: [RFC 01/10] virtio: get class_id and pci device id by the virtio
> > id
> >
> > On Wed, Jan 5, 2022 at 8:59 AM Longpeng(Mike) <longpeng2@huawei.com> wrote:
> > >
> > > From: Longpeng <longpeng2@huawei.com>
> > >
> > > Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> > > deivce which is specificed by the "Virtio Device ID".
> > >
> > > These helpers will be used to build the generic vDPA device later.
> > >
> > > Signed-off-by: Longpeng <longpeng2@huawei.com>
> > > ---
> > >  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
> > >  hw/virtio/virtio-pci.h |  4 ++
> > >  2 files changed, 97 insertions(+)
> > >
> > > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > > index 750aa47ec1..843085c4ea 100644
> > > --- a/hw/virtio/virtio-pci.c
> > > +++ b/hw/virtio/virtio-pci.c
> > > @@ -19,6 +19,7 @@
> > >
> > >  #include "exec/memop.h"
> > >  #include "standard-headers/linux/virtio_pci.h"
> > > +#include "standard-headers/linux/virtio_ids.h"
> > >  #include "hw/boards.h"
> > >  #include "hw/virtio/virtio.h"
> > >  #include "migration/qemu-file-types.h"
> > > @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n,
> > QEMUFile *f)
> > >      return 0;
> > >  }
> > >
> > > +typedef struct VirtIOPCIIDInfo {
> > > +    uint16_t vdev_id; /* virtio id */
> > > +    uint16_t pdev_id; /* pci device id */
> > > +    uint16_t class_id;
> > > +} VirtIOPCIIDInfo;
> > > +
> > > +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> > > +    {
> >
> > Any way to get rid of this array? E.g using the algorithm that is used
> > by the kernel virtio driver.
> >
>
> For device id, we can use the algorithm if we no need to support
> Transitional id. But how to get the class id ?

Right, I miss this. So the current code should be fine.

Thanks

>
> > Thanks
> >
> > > +        .vdev_id = VIRTIO_ID_NET,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> > > +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_BLOCK,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> > > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_CONSOLE,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> > > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_SCSI,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> > > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_9P,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> > > +        .class_id = PCI_BASE_CLASS_NETWORK,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_VSOCK,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> > > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_IOMMU,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_MEM,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_PMEM,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_RNG,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_BALLOON,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +};
> > > +
> > > +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> > > +{
> > > +    VirtIOPCIIDInfo info = {};
> > > +    int i;
> > > +
> > > +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> > > +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> > > +            info = virtio_pci_id_info[i];
> > > +            break;
> > > +        }
> > > +    }
> > > +
> > > +    return info;
> > > +}
> > > +
> > > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> > > +{
> > > +    return virtio_pci_get_id_info(device_id).pdev_id;
> > > +}
> > > +
> > > +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> > > +{
> > > +    return virtio_pci_get_id_info(device_id).class_id;
> > > +}
> > > +
> > >  static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
> > >  {
> > >      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> > > @@ -1674,6 +1764,9 @@ static void virtio_pci_device_plugged(DeviceState *d,
> > Error **errp)
> > >           * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
> > >           */
> > >          pci_set_word(config + PCI_SUBSYSTEM_ID,
> > virtio_bus_get_vdev_id(bus));
> > > +        if (proxy->pdev_id) {
> > > +            pci_config_set_device_id(config, proxy->pdev_id);
> > > +        }
> > >      } else {
> > >          /* pure virtio-1.0 */
> > >          pci_set_word(config + PCI_VENDOR_ID,
> > > diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> > > index 2446dcd9ae..06aa59436e 100644
> > > --- a/hw/virtio/virtio-pci.h
> > > +++ b/hw/virtio/virtio-pci.h
> > > @@ -146,6 +146,7 @@ struct VirtIOPCIProxy {
> > >      bool disable_modern;
> > >      bool ignore_backend_features;
> > >      OnOffAuto disable_legacy;
> > > +    uint16_t pdev_id;
> > >      uint32_t class_code;
> > >      uint32_t nvectors;
> > >      uint32_t dfselect;
> > > @@ -158,6 +159,9 @@ struct VirtIOPCIProxy {
> > >      VirtioBusState bus;
> > >  };
> > >
> > > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
> > > +uint16_t virtio_pci_get_class_id(uint16_t device_id);
> > > +
> > >  static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
> > >  {
> > >      return !proxy->disable_modern;
> > > --
> > > 2.23.0
> > >
>
Cornelia Huck Jan. 5, 2022, 10:46 a.m. UTC | #4
On Wed, Jan 05 2022, "Longpeng(Mike)" <longpeng2@huawei.com> wrote:

> From: Longpeng <longpeng2@huawei.com>
>
> Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> deivce which is specificed by the "Virtio Device ID".
>
> These helpers will be used to build the generic vDPA device later.
>
> Signed-off-by: Longpeng <longpeng2@huawei.com>
> ---
>  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
>  hw/virtio/virtio-pci.h |  4 ++
>  2 files changed, 97 insertions(+)
>
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 750aa47ec1..843085c4ea 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -19,6 +19,7 @@
>  
>  #include "exec/memop.h"
>  #include "standard-headers/linux/virtio_pci.h"
> +#include "standard-headers/linux/virtio_ids.h"
>  #include "hw/boards.h"
>  #include "hw/virtio/virtio.h"
>  #include "migration/qemu-file-types.h"
> @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
>      return 0;
>  }
>  
> +typedef struct VirtIOPCIIDInfo {
> +    uint16_t vdev_id; /* virtio id */
> +    uint16_t pdev_id; /* pci device id */
> +    uint16_t class_id;
> +} VirtIOPCIIDInfo;
> +
> +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> +    {
> +        .vdev_id = VIRTIO_ID_NET,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_BLOCK,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> +        .class_id = PCI_CLASS_STORAGE_SCSI,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_CONSOLE,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_SCSI,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> +        .class_id = PCI_CLASS_STORAGE_SCSI,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_9P,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> +        .class_id = PCI_BASE_CLASS_NETWORK,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_VSOCK,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_IOMMU,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_MEM,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_PMEM,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_RNG,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_BALLOON,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +};
> +
> +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> +{
> +    VirtIOPCIIDInfo info = {};
> +    int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> +            info = virtio_pci_id_info[i];
> +            break;
> +        }
> +    }
> +
> +    return info;
> +}
> +
> +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> +{
> +    return virtio_pci_get_id_info(device_id).pdev_id;
> +}
> +
> +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> +{
> +    return virtio_pci_get_id_info(device_id).class_id;
> +}

What happens if these functions are called for a device_id that is not
in the array, e.g. if we forgot to add a new id to the array?

Can the array be generated in some way?
Zhijian Li (Fujitsu)" via Jan. 6, 2022, 1:50 a.m. UTC | #5
> -----Original Message-----
> From: Cornelia Huck [mailto:cohuck@redhat.com]
> Sent: Wednesday, January 5, 2022 6:46 PM
> To: Longpeng (Mike, Cloud Infrastructure Service Product Dept.)
> <longpeng2@huawei.com>; stefanha@redhat.com; mst@redhat.com;
> jasowang@redhat.com; sgarzare@redhat.com
> Cc: pbonzini@redhat.com; Gonglei (Arei) <arei.gonglei@huawei.com>; Yechuan
> <yechuan@huawei.com>; Huangzhichao <huangzhichao@huawei.com>;
> qemu-devel@nongnu.org; Longpeng (Mike, Cloud Infrastructure Service Product
> Dept.) <longpeng2@huawei.com>
> Subject: Re: [RFC 01/10] virtio: get class_id and pci device id by the virtio
> id
> 
> On Wed, Jan 05 2022, "Longpeng(Mike)" <longpeng2@huawei.com> wrote:
> 
> > From: Longpeng <longpeng2@huawei.com>
> >
> > Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> > deivce which is specificed by the "Virtio Device ID".
> >
> > These helpers will be used to build the generic vDPA device later.
> >
> > Signed-off-by: Longpeng <longpeng2@huawei.com>
> > ---
> >  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
> >  hw/virtio/virtio-pci.h |  4 ++
> >  2 files changed, 97 insertions(+)
> >
> > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > index 750aa47ec1..843085c4ea 100644
> > --- a/hw/virtio/virtio-pci.c
> > +++ b/hw/virtio/virtio-pci.c
> > @@ -19,6 +19,7 @@
> >
> >  #include "exec/memop.h"
> >  #include "standard-headers/linux/virtio_pci.h"
> > +#include "standard-headers/linux/virtio_ids.h"
> >  #include "hw/boards.h"
> >  #include "hw/virtio/virtio.h"
> >  #include "migration/qemu-file-types.h"
> > @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n,
> QEMUFile *f)
> >      return 0;
> >  }
> >
> > +typedef struct VirtIOPCIIDInfo {
> > +    uint16_t vdev_id; /* virtio id */
> > +    uint16_t pdev_id; /* pci device id */
> > +    uint16_t class_id;
> > +} VirtIOPCIIDInfo;
> > +
> > +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> > +    {
> > +        .vdev_id = VIRTIO_ID_NET,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> > +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_BLOCK,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_CONSOLE,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_SCSI,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_9P,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> > +        .class_id = PCI_BASE_CLASS_NETWORK,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_VSOCK,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_IOMMU,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_MEM,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_PMEM,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_RNG,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_BALLOON,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +};
> > +
> > +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> > +{
> > +    VirtIOPCIIDInfo info = {};
> > +    int i;
> > +
> > +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> > +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> > +            info = virtio_pci_id_info[i];
> > +            break;
> > +        }
> > +    }
> > +
> > +    return info;
> > +}
> > +
> > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> > +{
> > +    return virtio_pci_get_id_info(device_id).pdev_id;
> > +}
> > +
> > +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> > +{
> > +    return virtio_pci_get_id_info(device_id).class_id;
> > +}
> 
> What happens if these functions are called for a device_id that is not
> in the array, e.g. if we forgot to add a new id to the array?
> 

It would return pdev_id=0 or class_id=0 as a result, the virtio device
with pdev_id=0 is undefined and class_id=0 is also treated as undefined
(PCI_CLASS_NOT_DEFINED), so the caller should check the returned value.

> Can the array be generated in some way?

For PCI Device ID:
  - If we need to support Transitional VIRTIO devices, there's no algorithm
    can map a VIRTIO ID to a PCI Device ID.
  - If we only need to support 1.0+ VIRTIO devices, then we can calculate the
    PCI Device ID based on the VIRTIO ID.

For Class ID, seems no way :(
Zhijian Li (Fujitsu)" via Jan. 10, 2022, 3:03 a.m. UTC | #6
> -----Original Message-----
> From: Jason Wang [mailto:jasowang@redhat.com]
> Sent: Wednesday, January 5, 2022 2:15 PM
> To: Longpeng (Mike, Cloud Infrastructure Service Product Dept.)
> <longpeng2@huawei.com>
> Cc: Stefan Hajnoczi <stefanha@redhat.com>; mst <mst@redhat.com>; Stefano
> Garzarella <sgarzare@redhat.com>; Cornelia Huck <cohuck@redhat.com>; pbonzini
> <pbonzini@redhat.com>; Gonglei (Arei) <arei.gonglei@huawei.com>; Yechuan
> <yechuan@huawei.com>; Huangzhichao <huangzhichao@huawei.com>; qemu-devel
> <qemu-devel@nongnu.org>
> Subject: Re: [RFC 01/10] virtio: get class_id and pci device id by the virtio
> id
> 
> On Wed, Jan 5, 2022 at 1:48 PM Longpeng (Mike, Cloud Infrastructure
> Service Product Dept.) <longpeng2@huawei.com> wrote:
> >
> >
> >
> > > -----Original Message-----
> > > From: Jason Wang [mailto:jasowang@redhat.com]
> > > Sent: Wednesday, January 5, 2022 12:38 PM
> > > To: Longpeng (Mike, Cloud Infrastructure Service Product Dept.)
> > > <longpeng2@huawei.com>
> > > Cc: Stefan Hajnoczi <stefanha@redhat.com>; mst <mst@redhat.com>; Stefano
> > > Garzarella <sgarzare@redhat.com>; Cornelia Huck <cohuck@redhat.com>;
> pbonzini
> > > <pbonzini@redhat.com>; Gonglei (Arei) <arei.gonglei@huawei.com>; Yechuan
> > > <yechuan@huawei.com>; Huangzhichao <huangzhichao@huawei.com>; qemu-devel
> > > <qemu-devel@nongnu.org>
> > > Subject: Re: [RFC 01/10] virtio: get class_id and pci device id by the virtio
> > > id
> > >
> > > On Wed, Jan 5, 2022 at 8:59 AM Longpeng(Mike) <longpeng2@huawei.com> wrote:
> > > >
> > > > From: Longpeng <longpeng2@huawei.com>
> > > >
> > > > Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> > > > deivce which is specificed by the "Virtio Device ID".
> > > >
> > > > These helpers will be used to build the generic vDPA device later.
> > > >
> > > > Signed-off-by: Longpeng <longpeng2@huawei.com>
> > > > ---
> > > >  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
> > > >  hw/virtio/virtio-pci.h |  4 ++
> > > >  2 files changed, 97 insertions(+)
> > > >
> > > > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > > > index 750aa47ec1..843085c4ea 100644
> > > > --- a/hw/virtio/virtio-pci.c
> > > > +++ b/hw/virtio/virtio-pci.c
> > > > @@ -19,6 +19,7 @@
> > > >
> > > >  #include "exec/memop.h"
> > > >  #include "standard-headers/linux/virtio_pci.h"
> > > > +#include "standard-headers/linux/virtio_ids.h"
> > > >  #include "hw/boards.h"
> > > >  #include "hw/virtio/virtio.h"
> > > >  #include "migration/qemu-file-types.h"
> > > > @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int
> n,
> > > QEMUFile *f)
> > > >      return 0;
> > > >  }
> > > >
> > > > +typedef struct VirtIOPCIIDInfo {
> > > > +    uint16_t vdev_id; /* virtio id */
> > > > +    uint16_t pdev_id; /* pci device id */
> > > > +    uint16_t class_id;
> > > > +} VirtIOPCIIDInfo;
> > > > +
> > > > +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> > > > +    {
> > >
> > > Any way to get rid of this array? E.g using the algorithm that is used
> > > by the kernel virtio driver.
> > >
> >
> > For device id, we can use the algorithm if we no need to support
> > Transitional id. But how to get the class id ?
> 
> Right, I miss this. So the current code should be fine.
> 

Maybe the following way would be better? It can save about 40 lines.

#define VIRTIO_PCI_ID_INFO(name, class)   \
    {VIRTIO_ID_##name, PCI_DEVICE_ID_VIRTIO_##name, class}

static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
    VIRTIO_PCI_ID_INFO(NET,     PCI_CLASS_NETWORK_ETHERNET),
    VIRTIO_PCI_ID_INFO(BLOCK,   PCI_CLASS_STORAGE_SCSI),
    VIRTIO_PCI_ID_INFO(SCSI,    PCI_CLASS_STORAGE_SCSI),
    VIRTIO_PCI_ID_INFO(CONSOLE, PCI_CLASS_COMMUNICATION_OTHER),
    VIRTIO_PCI_ID_INFO(VSOCK,   PCI_CLASS_COMMUNICATION_OTHER),
    VIRTIO_PCI_ID_INFO(IOMMU,   PCI_CLASS_OTHERS),
    VIRTIO_PCI_ID_INFO(MEM,     PCI_CLASS_OTHERS),
    VIRTIO_PCI_ID_INFO(PMEM,    PCI_CLASS_OTHERS),
    VIRTIO_PCI_ID_INFO(RNG,     PCI_CLASS_OTHERS),
    VIRTIO_PCI_ID_INFO(BALLOON, PCI_CLASS_OTHERS),
    VIRTIO_PCI_ID_INFO(9P,      PCI_BASE_CLASS_NETWORK),
};


> Thanks
> 
> >
> > > Thanks
> > >
> > > > +        .vdev_id = VIRTIO_ID_NET,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> > > > +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_BLOCK,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> > > > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_CONSOLE,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> > > > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_SCSI,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> > > > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_9P,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> > > > +        .class_id = PCI_BASE_CLASS_NETWORK,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_VSOCK,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> > > > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_IOMMU,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> > > > +        .class_id = PCI_CLASS_OTHERS,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_MEM,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> > > > +        .class_id = PCI_CLASS_OTHERS,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_PMEM,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> > > > +        .class_id = PCI_CLASS_OTHERS,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_RNG,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> > > > +        .class_id = PCI_CLASS_OTHERS,
> > > > +    },
> > > > +    {
> > > > +        .vdev_id = VIRTIO_ID_BALLOON,
> > > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> > > > +        .class_id = PCI_CLASS_OTHERS,
> > > > +    },
> > > > +};
> > > > +
> > > > +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> > > > +{
> > > > +    VirtIOPCIIDInfo info = {};
> > > > +    int i;
> > > > +
> > > > +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> > > > +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> > > > +            info = virtio_pci_id_info[i];
> > > > +            break;
> > > > +        }
> > > > +    }
> > > > +
> > > > +    return info;
> > > > +}
> > > > +
> > > > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> > > > +{
> > > > +    return virtio_pci_get_id_info(device_id).pdev_id;
> > > > +}
> > > > +
> > > > +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> > > > +{
> > > > +    return virtio_pci_get_id_info(device_id).class_id;
> > > > +}
> > > > +
> > > >  static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
> > > >  {
> > > >      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> > > > @@ -1674,6 +1764,9 @@ static void virtio_pci_device_plugged(DeviceState
> *d,
> > > Error **errp)
> > > >           * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
> > > >           */
> > > >          pci_set_word(config + PCI_SUBSYSTEM_ID,
> > > virtio_bus_get_vdev_id(bus));
> > > > +        if (proxy->pdev_id) {
> > > > +            pci_config_set_device_id(config, proxy->pdev_id);
> > > > +        }
> > > >      } else {
> > > >          /* pure virtio-1.0 */
> > > >          pci_set_word(config + PCI_VENDOR_ID,
> > > > diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> > > > index 2446dcd9ae..06aa59436e 100644
> > > > --- a/hw/virtio/virtio-pci.h
> > > > +++ b/hw/virtio/virtio-pci.h
> > > > @@ -146,6 +146,7 @@ struct VirtIOPCIProxy {
> > > >      bool disable_modern;
> > > >      bool ignore_backend_features;
> > > >      OnOffAuto disable_legacy;
> > > > +    uint16_t pdev_id;
> > > >      uint32_t class_code;
> > > >      uint32_t nvectors;
> > > >      uint32_t dfselect;
> > > > @@ -158,6 +159,9 @@ struct VirtIOPCIProxy {
> > > >      VirtioBusState bus;
> > > >  };
> > > >
> > > > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
> > > > +uint16_t virtio_pci_get_class_id(uint16_t device_id);
> > > > +
> > > >  static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
> > > >  {
> > > >      return !proxy->disable_modern;
> > > > --
> > > > 2.23.0
> > > >
> >
Michael S. Tsirkin Jan. 10, 2022, 5:43 a.m. UTC | #7
On Wed, Jan 05, 2022 at 08:58:51AM +0800, Longpeng(Mike) wrote:
> From: Longpeng <longpeng2@huawei.com>
> 
> Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> deivce which is specificed by the "Virtio Device ID".

ton of typos here.

> These helpers will be used to build the generic vDPA device later.
> 
> Signed-off-by: Longpeng <longpeng2@huawei.com>
> ---
>  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
>  hw/virtio/virtio-pci.h |  4 ++
>  2 files changed, 97 insertions(+)
> 
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 750aa47ec1..843085c4ea 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -19,6 +19,7 @@
>  
>  #include "exec/memop.h"
>  #include "standard-headers/linux/virtio_pci.h"
> +#include "standard-headers/linux/virtio_ids.h"
>  #include "hw/boards.h"
>  #include "hw/virtio/virtio.h"
>  #include "migration/qemu-file-types.h"
> @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
>      return 0;
>  }
>  
> +typedef struct VirtIOPCIIDInfo {
> +    uint16_t vdev_id; /* virtio id */
> +    uint16_t pdev_id; /* pci device id */
> +    uint16_t class_id;
> +} VirtIOPCIIDInfo;


if this is transitional as comment says make it explicit
in the names and comments.

> +
> +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> +    {
> +        .vdev_id = VIRTIO_ID_NET,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_BLOCK,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> +        .class_id = PCI_CLASS_STORAGE_SCSI,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_CONSOLE,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_SCSI,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> +        .class_id = PCI_CLASS_STORAGE_SCSI,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_9P,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> +        .class_id = PCI_BASE_CLASS_NETWORK,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_VSOCK,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_IOMMU,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_MEM,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_PMEM,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_RNG,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +    {
> +        .vdev_id = VIRTIO_ID_BALLOON,
> +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> +        .class_id = PCI_CLASS_OTHERS,
> +    },
> +};
> +


this is the list from the spec:


So this is the list from the spec:

0x1000 network card
0x1001 block device
0x1002 memory ballooning (traditional)
0x1003 console
0x1004 SCSI host
0x1005 entropy source
0x1009 9P transport


I'd drop all the rest, use the algorithm for non transitional.
And when class is other I'd just not include it in the array,
make this the default.



> +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> +{
> +    VirtIOPCIIDInfo info = {};
> +    int i;
> +
> +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> +            info = virtio_pci_id_info[i];
> +            break;
> +        }
> +    }
> +
> +    return info;
> +}
> +
> +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> +{
> +    return virtio_pci_get_id_info(device_id).pdev_id;
> +}
> +
> +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> +{
> +    return virtio_pci_get_id_info(device_id).class_id;
> +}
> +
>  static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
>  {
>      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> @@ -1674,6 +1764,9 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
>           * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
>           */
>          pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus));
> +        if (proxy->pdev_id) {
> +            pci_config_set_device_id(config, proxy->pdev_id);
> +        }
>      } else {
>          /* pure virtio-1.0 */
>          pci_set_word(config + PCI_VENDOR_ID,
> diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> index 2446dcd9ae..06aa59436e 100644
> --- a/hw/virtio/virtio-pci.h
> +++ b/hw/virtio/virtio-pci.h
> @@ -146,6 +146,7 @@ struct VirtIOPCIProxy {
>      bool disable_modern;
>      bool ignore_backend_features;
>      OnOffAuto disable_legacy;
> +    uint16_t pdev_id;
>      uint32_t class_code;
>      uint32_t nvectors;
>      uint32_t dfselect;
> @@ -158,6 +159,9 @@ struct VirtIOPCIProxy {
>      VirtioBusState bus;
>  };
>  
> +uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
> +uint16_t virtio_pci_get_class_id(uint16_t device_id);
> +
>  static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
>  {
>      return !proxy->disable_modern;
> -- 
> 2.23.0
Zhijian Li (Fujitsu)" via Jan. 10, 2022, 6:27 a.m. UTC | #8
> -----Original Message-----
> From: Michael S. Tsirkin [mailto:mst@redhat.com]
> Sent: Monday, January 10, 2022 1:43 PM
> To: Longpeng (Mike, Cloud Infrastructure Service Product Dept.)
> <longpeng2@huawei.com>
> Cc: stefanha@redhat.com; jasowang@redhat.com; sgarzare@redhat.com;
> cohuck@redhat.com; pbonzini@redhat.com; Gonglei (Arei)
> <arei.gonglei@huawei.com>; Yechuan <yechuan@huawei.com>; Huangzhichao
> <huangzhichao@huawei.com>; qemu-devel@nongnu.org
> Subject: Re: [RFC 01/10] virtio: get class_id and pci device id by the virtio
> id
> 
> On Wed, Jan 05, 2022 at 08:58:51AM +0800, Longpeng(Mike) wrote:
> > From: Longpeng <longpeng2@huawei.com>
> >
> > Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> > deivce which is specificed by the "Virtio Device ID".
> 
> ton of typos here.
> 

Will fix all in the V2.

> > These helpers will be used to build the generic vDPA device later.
> >
> > Signed-off-by: Longpeng <longpeng2@huawei.com>
> > ---
> >  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
> >  hw/virtio/virtio-pci.h |  4 ++
> >  2 files changed, 97 insertions(+)
> >
> > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > index 750aa47ec1..843085c4ea 100644
> > --- a/hw/virtio/virtio-pci.c
> > +++ b/hw/virtio/virtio-pci.c
> > @@ -19,6 +19,7 @@
> >
> >  #include "exec/memop.h"
> >  #include "standard-headers/linux/virtio_pci.h"
> > +#include "standard-headers/linux/virtio_ids.h"
> >  #include "hw/boards.h"
> >  #include "hw/virtio/virtio.h"
> >  #include "migration/qemu-file-types.h"
> > @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n,
> QEMUFile *f)
> >      return 0;
> >  }
> >
> > +typedef struct VirtIOPCIIDInfo {
> > +    uint16_t vdev_id; /* virtio id */
> > +    uint16_t pdev_id; /* pci device id */
> > +    uint16_t class_id;
> > +} VirtIOPCIIDInfo;
> 
> 
> if this is transitional as comment says make it explicit
> in the names and comments.
> 

OK.

> > +
> > +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> > +    {
> > +        .vdev_id = VIRTIO_ID_NET,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> > +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_BLOCK,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_CONSOLE,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_SCSI,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_9P,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> > +        .class_id = PCI_BASE_CLASS_NETWORK,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_VSOCK,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_IOMMU,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_MEM,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_PMEM,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_RNG,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +    {
> > +        .vdev_id = VIRTIO_ID_BALLOON,
> > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> > +        .class_id = PCI_CLASS_OTHERS,
> > +    },
> > +};
> > +
> 
> 
> this is the list from the spec:
> 
> 
> So this is the list from the spec:
> 
> 0x1000 network card
> 0x1001 block device
> 0x1002 memory ballooning (traditional)
> 0x1003 console
> 0x1004 SCSI host
> 0x1005 entropy source
> 0x1009 9P transport
> 

Why the following device IDs are introduced? They are non
transitional devices.

#define PCI_DEVICE_ID_VIRTIO_VSOCK       0x1012
#define PCI_DEVICE_ID_VIRTIO_PMEM        0x1013
#define PCI_DEVICE_ID_VIRTIO_IOMMU       0x1014
#define PCI_DEVICE_ID_VIRTIO_MEM         0x1015

> 
> I'd drop all the rest, use the algorithm for non transitional.
> And when class is other I'd just not include it in the array,
> make this the default.
> 
> 
> 
> > +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> > +{
> > +    VirtIOPCIIDInfo info = {};
> > +    int i;
> > +
> > +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> > +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> > +            info = virtio_pci_id_info[i];
> > +            break;
> > +        }
> > +    }
> > +
> > +    return info;
> > +}
> > +
> > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> > +{
> > +    return virtio_pci_get_id_info(device_id).pdev_id;
> > +}
> > +
> > +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> > +{
> > +    return virtio_pci_get_id_info(device_id).class_id;
> > +}
> > +
> >  static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
> >  {
> >      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> > @@ -1674,6 +1764,9 @@ static void virtio_pci_device_plugged(DeviceState *d,
> Error **errp)
> >           * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
> >           */
> >          pci_set_word(config + PCI_SUBSYSTEM_ID,
> virtio_bus_get_vdev_id(bus));
> > +        if (proxy->pdev_id) {
> > +            pci_config_set_device_id(config, proxy->pdev_id);
> > +        }
> >      } else {
> >          /* pure virtio-1.0 */
> >          pci_set_word(config + PCI_VENDOR_ID,
> > diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> > index 2446dcd9ae..06aa59436e 100644
> > --- a/hw/virtio/virtio-pci.h
> > +++ b/hw/virtio/virtio-pci.h
> > @@ -146,6 +146,7 @@ struct VirtIOPCIProxy {
> >      bool disable_modern;
> >      bool ignore_backend_features;
> >      OnOffAuto disable_legacy;
> > +    uint16_t pdev_id;
> >      uint32_t class_code;
> >      uint32_t nvectors;
> >      uint32_t dfselect;
> > @@ -158,6 +159,9 @@ struct VirtIOPCIProxy {
> >      VirtioBusState bus;
> >  };
> >
> > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
> > +uint16_t virtio_pci_get_class_id(uint16_t device_id);
> > +
> >  static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
> >  {
> >      return !proxy->disable_modern;
> > --
> > 2.23.0
Michael S. Tsirkin Jan. 10, 2022, 7:14 a.m. UTC | #9
On Mon, Jan 10, 2022 at 06:27:05AM +0000, Longpeng (Mike, Cloud Infrastructure Service Product Dept.) wrote:
> 
> 
> > -----Original Message-----
> > From: Michael S. Tsirkin [mailto:mst@redhat.com]
> > Sent: Monday, January 10, 2022 1:43 PM
> > To: Longpeng (Mike, Cloud Infrastructure Service Product Dept.)
> > <longpeng2@huawei.com>
> > Cc: stefanha@redhat.com; jasowang@redhat.com; sgarzare@redhat.com;
> > cohuck@redhat.com; pbonzini@redhat.com; Gonglei (Arei)
> > <arei.gonglei@huawei.com>; Yechuan <yechuan@huawei.com>; Huangzhichao
> > <huangzhichao@huawei.com>; qemu-devel@nongnu.org
> > Subject: Re: [RFC 01/10] virtio: get class_id and pci device id by the virtio
> > id
> > 
> > On Wed, Jan 05, 2022 at 08:58:51AM +0800, Longpeng(Mike) wrote:
> > > From: Longpeng <longpeng2@huawei.com>
> > >
> > > Add helpers to get the "Transitional PCI Device ID" and "class_id" of the
> > > deivce which is specificed by the "Virtio Device ID".
> > 
> > ton of typos here.
> > 
> 
> Will fix all in the V2.
> 
> > > These helpers will be used to build the generic vDPA device later.
> > >
> > > Signed-off-by: Longpeng <longpeng2@huawei.com>
> > > ---
> > >  hw/virtio/virtio-pci.c | 93 ++++++++++++++++++++++++++++++++++++++++++
> > >  hw/virtio/virtio-pci.h |  4 ++
> > >  2 files changed, 97 insertions(+)
> > >
> > > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > > index 750aa47ec1..843085c4ea 100644
> > > --- a/hw/virtio/virtio-pci.c
> > > +++ b/hw/virtio/virtio-pci.c
> > > @@ -19,6 +19,7 @@
> > >
> > >  #include "exec/memop.h"
> > >  #include "standard-headers/linux/virtio_pci.h"
> > > +#include "standard-headers/linux/virtio_ids.h"
> > >  #include "hw/boards.h"
> > >  #include "hw/virtio/virtio.h"
> > >  #include "migration/qemu-file-types.h"
> > > @@ -213,6 +214,95 @@ static int virtio_pci_load_queue(DeviceState *d, int n,
> > QEMUFile *f)
> > >      return 0;
> > >  }
> > >
> > > +typedef struct VirtIOPCIIDInfo {
> > > +    uint16_t vdev_id; /* virtio id */
> > > +    uint16_t pdev_id; /* pci device id */
> > > +    uint16_t class_id;
> > > +} VirtIOPCIIDInfo;
> > 
> > 
> > if this is transitional as comment says make it explicit
> > in the names and comments.
> > 
> 
> OK.
> 
> > > +
> > > +static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_NET,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
> > > +        .class_id = PCI_CLASS_NETWORK_ETHERNET,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_BLOCK,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
> > > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_CONSOLE,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
> > > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_SCSI,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
> > > +        .class_id = PCI_CLASS_STORAGE_SCSI,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_9P,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
> > > +        .class_id = PCI_BASE_CLASS_NETWORK,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_VSOCK,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
> > > +        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_IOMMU,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_MEM,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_PMEM,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_RNG,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +    {
> > > +        .vdev_id = VIRTIO_ID_BALLOON,
> > > +        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
> > > +        .class_id = PCI_CLASS_OTHERS,
> > > +    },
> > > +};
> > > +
> > 
> > 
> > this is the list from the spec:
> > 
> > 
> > So this is the list from the spec:
> > 
> > 0x1000 network card
> > 0x1001 block device
> > 0x1002 memory ballooning (traditional)
> > 0x1003 console
> > 0x1004 SCSI host
> > 0x1005 entropy source
> > 0x1009 9P transport
> > 
> 
> Why the following device IDs are introduced? They are non
> transitional devices.
> 
> #define PCI_DEVICE_ID_VIRTIO_VSOCK       0x1012
> #define PCI_DEVICE_ID_VIRTIO_PMEM        0x1013
> #define PCI_DEVICE_ID_VIRTIO_IOMMU       0x1014
> #define PCI_DEVICE_ID_VIRTIO_MEM         0x1015

Just a single place to put these things.
E.g. vsock id is used in more than 1 place.

> > 
> > I'd drop all the rest, use the algorithm for non transitional.
> > And when class is other I'd just not include it in the array,
> > make this the default.
> > 
> > 
> > 
> > > +static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
> > > +{
> > > +    VirtIOPCIIDInfo info = {};
> > > +    int i;
> > > +
> > > +    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
> > > +        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
> > > +            info = virtio_pci_id_info[i];
> > > +            break;
> > > +        }
> > > +    }
> > > +
> > > +    return info;
> > > +}
> > > +
> > > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
> > > +{
> > > +    return virtio_pci_get_id_info(device_id).pdev_id;
> > > +}
> > > +
> > > +uint16_t virtio_pci_get_class_id(uint16_t device_id)
> > > +{
> > > +    return virtio_pci_get_id_info(device_id).class_id;
> > > +}
> > > +
> > >  static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
> > >  {
> > >      VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> > > @@ -1674,6 +1764,9 @@ static void virtio_pci_device_plugged(DeviceState *d,
> > Error **errp)
> > >           * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
> > >           */
> > >          pci_set_word(config + PCI_SUBSYSTEM_ID,
> > virtio_bus_get_vdev_id(bus));
> > > +        if (proxy->pdev_id) {
> > > +            pci_config_set_device_id(config, proxy->pdev_id);
> > > +        }
> > >      } else {
> > >          /* pure virtio-1.0 */
> > >          pci_set_word(config + PCI_VENDOR_ID,
> > > diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
> > > index 2446dcd9ae..06aa59436e 100644
> > > --- a/hw/virtio/virtio-pci.h
> > > +++ b/hw/virtio/virtio-pci.h
> > > @@ -146,6 +146,7 @@ struct VirtIOPCIProxy {
> > >      bool disable_modern;
> > >      bool ignore_backend_features;
> > >      OnOffAuto disable_legacy;
> > > +    uint16_t pdev_id;
> > >      uint32_t class_code;
> > >      uint32_t nvectors;
> > >      uint32_t dfselect;
> > > @@ -158,6 +159,9 @@ struct VirtIOPCIProxy {
> > >      VirtioBusState bus;
> > >  };
> > >
> > > +uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
> > > +uint16_t virtio_pci_get_class_id(uint16_t device_id);
> > > +
> > >  static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
> > >  {
> > >      return !proxy->disable_modern;
> > > --
> > > 2.23.0
diff mbox series

Patch

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 750aa47ec1..843085c4ea 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -19,6 +19,7 @@ 
 
 #include "exec/memop.h"
 #include "standard-headers/linux/virtio_pci.h"
+#include "standard-headers/linux/virtio_ids.h"
 #include "hw/boards.h"
 #include "hw/virtio/virtio.h"
 #include "migration/qemu-file-types.h"
@@ -213,6 +214,95 @@  static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f)
     return 0;
 }
 
+typedef struct VirtIOPCIIDInfo {
+    uint16_t vdev_id; /* virtio id */
+    uint16_t pdev_id; /* pci device id */
+    uint16_t class_id;
+} VirtIOPCIIDInfo;
+
+static const VirtIOPCIIDInfo virtio_pci_id_info[] = {
+    {
+        .vdev_id = VIRTIO_ID_NET,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_NET,
+        .class_id = PCI_CLASS_NETWORK_ETHERNET,
+    },
+    {
+        .vdev_id = VIRTIO_ID_BLOCK,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_BLOCK,
+        .class_id = PCI_CLASS_STORAGE_SCSI,
+    },
+    {
+        .vdev_id = VIRTIO_ID_CONSOLE,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_CONSOLE,
+        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
+    },
+    {
+        .vdev_id = VIRTIO_ID_SCSI,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_SCSI,
+        .class_id = PCI_CLASS_STORAGE_SCSI,
+    },
+    {
+        .vdev_id = VIRTIO_ID_9P,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_9P,
+        .class_id = PCI_BASE_CLASS_NETWORK,
+    },
+    {
+        .vdev_id = VIRTIO_ID_VSOCK,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_VSOCK,
+        .class_id = PCI_CLASS_COMMUNICATION_OTHER,
+    },
+    {
+        .vdev_id = VIRTIO_ID_IOMMU,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_IOMMU,
+        .class_id = PCI_CLASS_OTHERS,
+    },
+    {
+        .vdev_id = VIRTIO_ID_MEM,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_MEM,
+        .class_id = PCI_CLASS_OTHERS,
+    },
+    {
+        .vdev_id = VIRTIO_ID_PMEM,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_PMEM,
+        .class_id = PCI_CLASS_OTHERS,
+    },
+    {
+        .vdev_id = VIRTIO_ID_RNG,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_RNG,
+        .class_id = PCI_CLASS_OTHERS,
+    },
+    {
+        .vdev_id = VIRTIO_ID_BALLOON,
+        .pdev_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
+        .class_id = PCI_CLASS_OTHERS,
+    },
+};
+
+static VirtIOPCIIDInfo virtio_pci_get_id_info(uint16_t vdev_id)
+{
+    VirtIOPCIIDInfo info = {};
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(virtio_pci_id_info); i++) {
+        if (virtio_pci_id_info[i].vdev_id == vdev_id) {
+            info = virtio_pci_id_info[i];
+            break;
+        }
+    }
+
+    return info;
+}
+
+uint16_t virtio_pci_get_pci_devid(uint16_t device_id)
+{
+    return virtio_pci_get_id_info(device_id).pdev_id;
+}
+
+uint16_t virtio_pci_get_class_id(uint16_t device_id)
+{
+    return virtio_pci_get_id_info(device_id).class_id;
+}
+
 static bool virtio_pci_ioeventfd_enabled(DeviceState *d)
 {
     VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
@@ -1674,6 +1764,9 @@  static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
          * is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
          */
         pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus));
+        if (proxy->pdev_id) {
+            pci_config_set_device_id(config, proxy->pdev_id);
+        }
     } else {
         /* pure virtio-1.0 */
         pci_set_word(config + PCI_VENDOR_ID,
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 2446dcd9ae..06aa59436e 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -146,6 +146,7 @@  struct VirtIOPCIProxy {
     bool disable_modern;
     bool ignore_backend_features;
     OnOffAuto disable_legacy;
+    uint16_t pdev_id;
     uint32_t class_code;
     uint32_t nvectors;
     uint32_t dfselect;
@@ -158,6 +159,9 @@  struct VirtIOPCIProxy {
     VirtioBusState bus;
 };
 
+uint16_t virtio_pci_get_pci_devid(uint16_t device_id);
+uint16_t virtio_pci_get_class_id(uint16_t device_id);
+
 static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
 {
     return !proxy->disable_modern;