[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [V5 1/6] hw/msi: Allow platform devices to use explicit
From: |
Michael S. Tsirkin |
Subject: |
Re: [Qemu-devel] [V5 1/6] hw/msi: Allow platform devices to use explicit SID |
Date: |
Mon, 10 Oct 2016 01:11:53 +0300 |
On Tue, Sep 20, 2016 at 08:40:41PM +0300, David Kiarie wrote:
> When using IOMMU platform devices like IOAPIC are required to make
> interrupt remapping requests using explicit SID. We associate an MSI
> route with a requester ID and a PCI device if present which ensures
> that platform devices can call IOMMU interrupt remapping code with
> explicit SID. This also ensures compatility with the original code
> which mainly dealt with PCI devices.
>
> Signed-off-by: David Kiarie <address@hidden>
Paolo, could you please ack the kvm changes?
Thanks!
> ---
> hw/i386/intel_iommu.c | 3 +++
> hw/i386/kvm/pci-assign.c | 12 ++++++++----
> hw/intc/ioapic.c | 33 ++++++++++++++++++++++++++-------
> hw/misc/ivshmem.c | 6 ++++--
> hw/vfio/pci.c | 6 ++++--
> hw/virtio/virtio-pci.c | 7 +++++--
> include/hw/i386/ioapic_internal.h | 1 +
> include/hw/i386/x86-iommu.h | 1 +
> include/sysemu/kvm.h | 25 ++++++++++++++-----------
> kvm-all.c | 11 +++++++----
> kvm-stub.c | 5 +++--
> target-arm/kvm.c | 3 ++-
> target-i386/kvm.c | 15 +++++++++------
> target-mips/kvm.c | 3 ++-
> target-ppc/kvm.c | 3 ++-
> target-s390x/kvm.c | 3 ++-
> 16 files changed, 93 insertions(+), 44 deletions(-)
>
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index d6e02c8..496d836 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -2466,6 +2466,9 @@ static void vtd_realize(DeviceState *dev, Error **errp)
> vtd_init(s);
> sysbus_mmio_map(SYS_BUS_DEVICE(s), 0, Q35_HOST_BRIDGE_IOMMU_ADDR);
> pci_setup_iommu(bus, vtd_host_dma_iommu, dev);
> + /* IOMMU expected IOAPIC SID */
> + x86_iommu->ioapic_bdf = PCI_BUILD_BDF(Q35_PSEUDO_DEVFN_IOAPIC,
> + Q35_PSEUDO_DEVFN_IOAPIC);
> /* Pseudo address space under root PCI bus. */
> pcms->ioapic_as = vtd_host_dma_iommu(bus, s, Q35_PSEUDO_DEVFN_IOAPIC);
>
> diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
> index 8238fbc..3f26be1 100644
> --- a/hw/i386/kvm/pci-assign.c
> +++ b/hw/i386/kvm/pci-assign.c
> @@ -976,7 +976,8 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev)
> if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) {
> int virq;
>
> - virq = kvm_irqchip_add_msi_route(kvm_state, 0, pci_dev);
> + virq = kvm_irqchip_add_msi_route(kvm_state, 0, pci_dev,
> + pci_requester_id(pci_dev));
> if (virq < 0) {
> perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route");
> return;
> @@ -1014,7 +1015,8 @@ static void assigned_dev_update_msi_msg(PCIDevice
> *pci_dev)
> }
>
> kvm_irqchip_update_msi_route(kvm_state, assigned_dev->msi_virq[0],
> - msi_get_message(pci_dev, 0), pci_dev);
> + msi_get_message(pci_dev, 0), pci_dev,
> + pci_requester_id(pci_dev));
> kvm_irqchip_commit_routes(kvm_state);
> }
>
> @@ -1078,7 +1080,8 @@ static int assigned_dev_update_msix_mmio(PCIDevice
> *pci_dev)
> continue;
> }
>
> - r = kvm_irqchip_add_msi_route(kvm_state, i, pci_dev);
> + r = kvm_irqchip_add_msi_route(kvm_state, i, pci_dev,
> + pci_requester_id(pci_dev));
> if (r < 0) {
> return r;
> }
> @@ -1599,7 +1602,8 @@ static void assigned_dev_msix_mmio_write(void *opaque,
> hwaddr addr,
>
> ret = kvm_irqchip_update_msi_route(kvm_state,
> adev->msi_virq[i], msg,
> - pdev);
> + pdev,
> + pci_requester_id(pdev));
> if (ret) {
> error_report("Error updating irq routing entry (%d)",
> ret);
> }
> diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
> index 31791b0..fa2b745 100644
> --- a/hw/intc/ioapic.c
> +++ b/hw/intc/ioapic.c
> @@ -95,9 +95,17 @@ static void ioapic_entry_parse(uint64_t entry, struct
> ioapic_entry_info *info)
> (info->delivery_mode << MSI_DATA_DELIVERY_MODE_SHIFT);
> }
>
> -static void ioapic_service(IOAPICCommonState *s)
> +static void ioapic_as_write(IOAPICCommonState *s, uint32_t data, uint64_t
> addr)
> {
> AddressSpace *ioapic_as = PC_MACHINE(qdev_get_machine())->ioapic_as;
> + MemTxAttrs attrs;
> +
> + attrs.requester_id = s->devid;
> + address_space_stl_le(ioapic_as, addr, data, attrs, NULL);
> +}
> +
> +static void ioapic_service(IOAPICCommonState *s)
> +{
> struct ioapic_entry_info info;
> uint8_t i;
> uint32_t mask;
> @@ -141,7 +149,7 @@ static void ioapic_service(IOAPICCommonState *s)
> * the IOAPIC message into a MSI one, and its
> * address space will decide whether we need a
> * translation. */
> - stl_le_phys(ioapic_as, info.addr, info.data);
> + ioapic_as_write(s, info.data, info.addr);
> }
> }
> }
> @@ -197,7 +205,7 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s)
> ioapic_entry_parse(s->ioredtbl[i], &info);
> msg.address = info.addr;
> msg.data = info.data;
> - kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
> + kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL, s->devid);
> }
> kvm_irqchip_commit_routes(kvm_state);
> }
> @@ -379,18 +387,30 @@ static const MemoryRegionOps ioapic_io_ops = {
>
> static void ioapic_machine_done_notify(Notifier *notifier, void *data)
> {
> -#ifdef CONFIG_KVM
> + X86IOMMUState *iommu = x86_iommu_get_default();
> IOAPICCommonState *s = container_of(notifier, IOAPICCommonState,
> machine_done);
> -
> + /* kernel_irqchip=off */
> + if (iommu) {
> + s->devid = iommu->ioapic_bdf;
> + }
> +#ifdef CONFIG_KVM
> if (kvm_irqchip_is_split()) {
> - X86IOMMUState *iommu = x86_iommu_get_default();
> + MSIMessage msg = {0, 0};
> + int i;
> +
> if (iommu) {
> /* Register this IOAPIC with IOMMU IEC notifier, so that
> * when there are IR invalidates, we can be notified to
> * update kernel IR cache. */
> x86_iommu_iec_register_notifier(iommu, ioapic_iec_notifier, s);
> + /* update IOAPIC routes to the right SID */
> + for (i = 0; i < IOAPIC_NUM_PINS; i++) {
> + kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL,
> s->devid);
> + }
> + kvm_irqchip_commit_routes(kvm_state);
> }
> +
> }
> #endif
> }
> @@ -407,7 +427,6 @@ static void ioapic_realize(DeviceState *dev, Error **errp)
>
> memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s,
> "ioapic", 0x1000);
> -
> qdev_init_gpio_in(dev, ioapic_set_irq, IOAPIC_NUM_PINS);
>
> ioapics[ioapic_no] = s;
> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
> index f803dfd..64995bf 100644
> --- a/hw/misc/ivshmem.c
> +++ b/hw/misc/ivshmem.c
> @@ -318,7 +318,8 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned
> vector,
>
> IVSHMEM_DPRINTF("vector unmask %p %d\n", dev, vector);
>
> - ret = kvm_irqchip_update_msi_route(kvm_state, v->virq, msg, dev);
> + ret = kvm_irqchip_update_msi_route(kvm_state, v->virq, msg, dev,
> + pci_requester_id(dev));
> if (ret < 0) {
> return ret;
> }
> @@ -447,7 +448,8 @@ static void ivshmem_add_kvm_msi_virq(IVShmemState *s, int
> vector,
> IVSHMEM_DPRINTF("ivshmem_add_kvm_msi_virq vector:%d\n", vector);
> assert(!s->msi_vectors[vector].pdev);
>
> - ret = kvm_irqchip_add_msi_route(kvm_state, vector, pdev);
> + ret = kvm_irqchip_add_msi_route(kvm_state, vector, pdev,
> + pci_requester_id(pdev));
> if (ret < 0) {
> error_setg(errp, "kvm_irqchip_add_msi_route failed");
> return;
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index a5a620a..1ab083a 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -429,7 +429,8 @@ static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev,
> VFIOMSIVector *vector,
> return;
> }
>
> - virq = kvm_irqchip_add_msi_route(kvm_state, vector_n, &vdev->pdev);
> + virq = kvm_irqchip_add_msi_route(kvm_state, vector_n, &vdev->pdev,
> + pci_requester_id(&vdev->pdev));
> if (virq < 0) {
> event_notifier_cleanup(&vector->kvm_interrupt);
> return;
> @@ -457,7 +458,8 @@ static void vfio_remove_kvm_msi_virq(VFIOMSIVector
> *vector)
> static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg,
> PCIDevice *pdev)
> {
> - kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg, pdev);
> + kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg, pdev,
> + pci_requester_id(pdev));
> kvm_irqchip_commit_routes(kvm_state);
> }
>
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 2d60a00..6108f5b 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -711,7 +711,8 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy
> *proxy,
> int ret;
>
> if (irqfd->users == 0) {
> - ret = kvm_irqchip_add_msi_route(kvm_state, vector, &proxy->pci_dev);
> + ret = kvm_irqchip_add_msi_route(kvm_state, vector, &proxy->pci_dev,
> + pci_requester_id(&proxy->pci_dev));
> if (ret < 0) {
> return ret;
> }
> @@ -839,12 +840,14 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy
> *proxy,
> EventNotifier *n = virtio_queue_get_guest_notifier(vq);
> VirtIOIRQFD *irqfd;
> int ret = 0;
> + uint16_t requester_id = pci_requester_id(&proxy->pci_dev);
>
> if (proxy->vector_irqfd) {
> irqfd = &proxy->vector_irqfd[vector];
> if (irqfd->msg.data != msg.data || irqfd->msg.address !=
> msg.address) {
> ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg,
> - &proxy->pci_dev);
> + &proxy->pci_dev,
> + requester_id);
> if (ret < 0) {
> return ret;
> }
> diff --git a/include/hw/i386/ioapic_internal.h
> b/include/hw/i386/ioapic_internal.h
> index a11d86d..d68a24f 100644
> --- a/include/hw/i386/ioapic_internal.h
> +++ b/include/hw/i386/ioapic_internal.h
> @@ -103,6 +103,7 @@ typedef struct IOAPICCommonClass {
> struct IOAPICCommonState {
> SysBusDevice busdev;
> MemoryRegion io_memory;
> + uint16_t devid;
> uint8_t id;
> uint8_t ioregsel;
> uint32_t irr;
> diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h
> index 0c89d98..5d05865 100644
> --- a/include/hw/i386/x86-iommu.h
> +++ b/include/hw/i386/x86-iommu.h
> @@ -72,6 +72,7 @@ typedef struct IEC_Notifier IEC_Notifier;
>
> struct X86IOMMUState {
> SysBusDevice busdev;
> + uint16_t ioapic_bdf; /* expected IOAPIC SID */
> bool intr_supported; /* Whether vIOMMU supports IR */
> IommuType type; /* IOMMU type - AMD/Intel */
> QLIST_HEAD(, IEC_Notifier) iec_notifiers; /* IEC notify list */
> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> index 3e17ba7..2348456 100644
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -354,7 +354,8 @@ int kvm_arch_on_sigbus(int code, void *addr);
> void kvm_arch_init_irq_routing(KVMState *s);
>
> int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
> - uint64_t address, uint32_t data, PCIDevice
> *dev);
> + uint64_t address, uint32_t data,
> + uint16_t requester_id);
>
> /* Notify arch about newly added MSI routes */
> int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
> @@ -477,18 +478,20 @@ static inline void cpu_synchronize_post_init(CPUState
> *cpu)
>
> /**
> * kvm_irqchip_add_msi_route - Add MSI route for specific vector
> - * @s: KVM state
> - * @vector: which vector to add. This can be either MSI/MSIX
> - * vector. The function will automatically detect whether
> - * MSI/MSIX is enabled, and fetch corresponding MSI
> - * message.
> - * @dev: Owner PCI device to add the route. If @dev is specified
> - * as @NULL, an empty MSI message will be inited.
> - * @return: virq (>=0) when success, errno (<0) when failed.
> + * @s: KVM state
> + * @vector: which vector to add. This can be either MSI/MSIX
> + * vector. The function will automatically detect whether
> + * MSI/MSIX is enabled, and fetch corresponding MSI
> + * message.
> + * @dev: Owner PCI device to add the route. If @dev is specified
> + * as @NULL, an empty MSI message will be inited.
> + * @requester_id: SID when calling IOMMU code
> + * @return: virq (>=0) when success, errno (<0) when failed.
> */
> -int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev);
> +int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev,
> + uint16_t requester_id);
> int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
> - PCIDevice *dev);
> + PCIDevice *dev, uint16_t requester_id);
> void kvm_irqchip_commit_routes(KVMState *s);
> void kvm_irqchip_release_virq(KVMState *s, int virq);
>
> diff --git a/kvm-all.c b/kvm-all.c
> index 8a4382e..f9b2ff7 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -1246,7 +1246,8 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
> return kvm_set_irq(s, route->kroute.gsi, 1);
> }
>
> -int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
> +int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev,
> + uint16_t requester_id)
> {
> struct kvm_irq_routing_entry kroute = {};
> int virq;
> @@ -1275,7 +1276,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector,
> PCIDevice *dev)
> kroute.u.msi.address_lo = (uint32_t)msg.address;
> kroute.u.msi.address_hi = msg.address >> 32;
> kroute.u.msi.data = le32_to_cpu(msg.data);
> - if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data, dev)) {
> + if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data,
> + requester_id)) {
> kvm_irqchip_release_virq(s, virq);
> return -EINVAL;
> }
> @@ -1290,7 +1292,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector,
> PCIDevice *dev)
> }
>
> int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
> - PCIDevice *dev)
> + PCIDevice *dev, uint16_t requester_id)
> {
> struct kvm_irq_routing_entry kroute = {};
>
> @@ -1308,7 +1310,8 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq,
> MSIMessage msg,
> kroute.u.msi.address_lo = (uint32_t)msg.address;
> kroute.u.msi.address_hi = msg.address >> 32;
> kroute.u.msi.data = le32_to_cpu(msg.data);
> - if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data, dev)) {
> + if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data,
> + requester_id)) {
> return -EINVAL;
> }
>
> diff --git a/kvm-stub.c b/kvm-stub.c
> index 3227127..5f0bee5 100644
> --- a/kvm-stub.c
> +++ b/kvm-stub.c
> @@ -112,7 +112,8 @@ int kvm_on_sigbus(int code, void *addr)
> }
>
> #ifndef CONFIG_USER_ONLY
> -int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
> +int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev,
> + uint16_t requester_id)
> {
> return -ENOSYS;
> }
> @@ -126,7 +127,7 @@ void kvm_irqchip_release_virq(KVMState *s, int virq)
> }
>
> int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
> - PCIDevice *dev)
> + PCIDevice *dev, uint16_t requester_id)
> {
> return -ENOSYS;
> }
> diff --git a/target-arm/kvm.c b/target-arm/kvm.c
> index dbe393c..a221e68 100644
> --- a/target-arm/kvm.c
> +++ b/target-arm/kvm.c
> @@ -617,7 +617,8 @@ int kvm_arm_vgic_probe(void)
> }
>
> int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
> - uint64_t address, uint32_t data, PCIDevice *dev)
> + uint64_t address, uint32_t data,
> + uint16_t requester_id)
> {
> return 0;
> }
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index f1ad805..2e223e0 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -3226,7 +3226,7 @@ void kvm_arch_init_irq_routing(KVMState *s)
> /* If the ioapic is in QEMU and the lapics are in KVM, reserve
> MSI routes for signaling interrupts to the local apics. */
> for (i = 0; i < IOAPIC_NUM_PINS; i++) {
> - if (kvm_irqchip_add_msi_route(s, 0, NULL) < 0) {
> + if (kvm_irqchip_add_msi_route(s, 0, NULL, 0) < 0) {
> error_report("Could not enable split IRQ mode.");
> exit(1);
> }
> @@ -3394,7 +3394,8 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t
> dev_id)
> }
>
> int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
> - uint64_t address, uint32_t data, PCIDevice *dev)
> + uint64_t address, uint32_t data,
> + uint16_t requester_id)
> {
> X86IOMMUState *iommu = x86_iommu_get_default();
>
> @@ -3408,9 +3409,8 @@ int kvm_arch_fixup_msi_route(struct
> kvm_irq_routing_entry *route,
> src.address |= route->u.msi.address_lo;
> src.data = route->u.msi.data;
>
> - ret = class->int_remap(iommu, &src, &dst, dev ? \
> - pci_requester_id(dev) : \
> - X86_IOMMU_SID_INVALID);
> + ret = class->int_remap(iommu, &src, &dst, requester_id);
> +
> if (ret) {
> trace_kvm_x86_fixup_msi_error(route->gsi);
> return 1;
> @@ -3428,6 +3428,7 @@ typedef struct MSIRouteEntry MSIRouteEntry;
>
> struct MSIRouteEntry {
> PCIDevice *dev; /* Device pointer */
> + uint16_t requester_id; /* Requesting SID */
> int vector; /* MSI/MSIX vector index */
> int virq; /* Virtual IRQ index */
> QLIST_ENTRY(MSIRouteEntry) list;
> @@ -3448,7 +3449,8 @@ static void kvm_update_msi_routes_all(void *private,
> bool global,
> cnt++;
> msg = pci_get_msi_message(entry->dev, entry->vector);
> kvm_irqchip_update_msi_route(kvm_state, entry->virq,
> - msg, entry->dev);
> + msg, entry->dev,
> + entry->requester_id);
> }
> kvm_irqchip_commit_routes(kvm_state);
> trace_kvm_x86_update_msi_routes(cnt);
> @@ -3469,6 +3471,7 @@ int kvm_arch_add_msi_route_post(struct
> kvm_irq_routing_entry *route,
>
> entry = g_new0(MSIRouteEntry, 1);
> entry->dev = dev;
> + entry->requester_id = pci_requester_id(dev);
> entry->vector = vector;
> entry->virq = route->gsi;
> QLIST_INSERT_HEAD(&msi_route_list, entry, list);
> diff --git a/target-mips/kvm.c b/target-mips/kvm.c
> index dcf5fbb..dbb5e59 100644
> --- a/target-mips/kvm.c
> +++ b/target-mips/kvm.c
> @@ -1038,7 +1038,8 @@ int kvm_arch_get_registers(CPUState *cs)
> }
>
> int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
> - uint64_t address, uint32_t data, PCIDevice *dev)
> + uint64_t address, uint32_t data,
> + uint16_t requester_id)
> {
> return 0;
> }
> diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
> index dcb68b9..49d313a 100644
> --- a/target-ppc/kvm.c
> +++ b/target-ppc/kvm.c
> @@ -2620,7 +2620,8 @@ error_out:
> }
>
> int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
> - uint64_t address, uint32_t data, PCIDevice *dev)
> + uint64_t address, uint32_t data,
> + uint16_t requester_id)
> {
> return 0;
> }
> diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
> index 4b847a3..93aeee4 100644
> --- a/target-s390x/kvm.c
> +++ b/target-s390x/kvm.c
> @@ -2282,7 +2282,8 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
> }
>
> int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
> - uint64_t address, uint32_t data, PCIDevice *dev)
> + uint64_t address, uint32_t data,
> + uint16_t requester_id)
> {
> S390PCIBusDevice *pbdev;
> uint32_t idx = data >> ZPCI_MSI_VEC_BITS;
> --
> 2.1.4
- Re: [Qemu-devel] [V5 1/6] hw/msi: Allow platform devices to use explicit SID,
Michael S. Tsirkin <=