From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>,
xiantao.zhang@intel.com, xen-devel <xen-devel@lists.xen.org>
Subject: Re: [PATCH resend 2/3] x86: enable multi-vector MSI
Date: Tue, 16 Jul 2013 12:36:38 +0100 [thread overview]
Message-ID: <51E53046.1040809@citrix.com> (raw)
In-Reply-To: <51E5392502000078000E54AE@nat28.tlf.novell.com>
[-- Attachment #1.1: Type: text/plain, Size: 24573 bytes --]
On 16/07/13 11:14, Jan Beulich wrote:
> This implies
> - extending the public interface to have a way to request a block of
> MSIs
> - allocating a block of contiguous pIRQ-s for the target domain (but
> note that the Xen IRQs allocated have no need of being contiguous)
> - repeating certain operations for all involved IRQs
> - fixing multi_msi_enable()
> - adjusting the mask bit accesses for maskable MSIs
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>
> --- a/xen/arch/x86/irq.c
> +++ b/xen/arch/x86/irq.c
> @@ -1863,6 +1863,25 @@ int get_free_pirq(struct domain *d, int
> return -ENOSPC;
> }
>
> +int get_free_pirqs(struct domain *d, unsigned int nr)
> +{
> + unsigned int i, found = 0;
> +
> + ASSERT(spin_is_locked(&d->event_lock));
> +
> + for ( i = d->nr_pirqs - 1; i >= nr_irqs_gsi; --i )
> + if ( is_free_pirq(d, pirq_info(d, i)) )
> + {
> + pirq_get_info(d, i);
> + if ( ++found == nr )
> + return i;
> + }
> + else
> + found = 0;
> +
> + return -ENOSPC;
> +}
> +
Is there any reason why this loop is backwards? Unless I am mistaken,
guests can choose their own pirqs when binding them, reducing the
likelyhood that the top of the available space will be free.
> int map_domain_pirq(
> struct domain *d, int pirq, int irq, int type, void *data)
> {
> @@ -1918,11 +1937,12 @@ int map_domain_pirq(
>
> desc = irq_to_desc(irq);
>
> - if ( type == MAP_PIRQ_TYPE_MSI )
> + if ( type == MAP_PIRQ_TYPE_MSI || type == MAP_PIRQ_TYPE_MULTI_MSI )
> {
> struct msi_info *msi = (struct msi_info *)data;
> struct msi_desc *msi_desc;
> struct pci_dev *pdev;
> + unsigned int nr = 0;
>
> ASSERT(spin_is_locked(&pcidevs_lock));
>
> @@ -1933,7 +1953,14 @@ int map_domain_pirq(
> pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
> ret = pci_enable_msi(msi, &msi_desc);
> if ( ret )
> + {
> + if ( ret > 0 )
> + {
> + msi->entry_nr = ret;
> + ret = -ENFILE;
> + }
> goto done;
> + }
>
> spin_lock_irqsave(&desc->lock, flags);
>
> @@ -1947,25 +1974,73 @@ int map_domain_pirq(
> goto done;
> }
>
> - ret = setup_msi_irq(desc, msi_desc);
> - if ( ret )
> + while ( !(ret = setup_msi_irq(desc, msi_desc + nr)) )
> {
> + if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV &&
> + !desc->arch.used_vectors )
> + {
> + desc->arch.used_vectors = &pdev->arch.used_vectors;
> + if ( desc->arch.vector != IRQ_VECTOR_UNASSIGNED )
> + {
> + int vector = desc->arch.vector;
> +
> + ASSERT(!test_bit(vector, desc->arch.used_vectors));
> + set_bit(vector, desc->arch.used_vectors);
> + }
> + }
> + if ( type == MAP_PIRQ_TYPE_MSI ||
> + msi_desc->msi_attrib.type != PCI_CAP_ID_MSI ||
> + ++nr == msi->entry_nr )
> + break;
> +
> + set_domain_irq_pirq(d, irq, info);
> spin_unlock_irqrestore(&desc->lock, flags);
> - pci_disable_msi(msi_desc);
> - goto done;
> +
> + info = NULL;
> + irq = create_irq(NUMA_NO_NODE);
> + ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
> + : irq;
> + if ( ret )
> + break;
> + msi_desc[nr].irq = irq;
> +
> + if ( irq_permit_access(d, irq) != 0 )
> + printk(XENLOG_G_WARNING
> + "dom%d: could not permit access to IRQ%d (pirq %d)\n",
> + d->domain_id, irq, pirq);
> +
> + desc = irq_to_desc(irq);
> + spin_lock_irqsave(&desc->lock, flags);
> +
> + if ( desc->handler != &no_irq_type )
> + {
> + dprintk(XENLOG_G_ERR, "dom%d: irq %d (pirq %u) in use (%s)\n",
> + d->domain_id, irq, pirq + nr, desc->handler->typename);
> + ret = -EBUSY;
> + break;
> + }
> }
>
> - if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV
> - && !desc->arch.used_vectors )
> + if ( ret )
> {
> - desc->arch.used_vectors = &pdev->arch.used_vectors;
> - if ( desc->arch.vector != IRQ_VECTOR_UNASSIGNED )
> + spin_unlock_irqrestore(&desc->lock, flags);
> + while ( nr-- )
> {
> - int vector = desc->arch.vector;
> - ASSERT(!test_bit(vector, desc->arch.used_vectors));
> -
> - set_bit(vector, desc->arch.used_vectors);
> + if ( irq >= 0 )
> + {
> + if ( irq_deny_access(d, irq) )
> + printk(XENLOG_G_ERR
> + "dom%d: could not revoke access to IRQ%d (pirq %d)\n",
> + d->domain_id, irq, pirq);
> + destroy_irq(irq);
> + }
> + if ( info )
> + cleanup_domain_irq_pirq(d, irq, info);
> + info = pirq_info(d, pirq + nr);
> + irq = info->arch.irq;
> }
> + pci_disable_msi(msi_desc);
> + goto done;
> }
>
> set_domain_irq_pirq(d, irq, info);
> @@ -1996,7 +2071,8 @@ int unmap_domain_pirq(struct domain *d,
> {
> unsigned long flags;
> struct irq_desc *desc;
> - int irq, ret = 0;
> + int irq, ret = 0, rc;
> + unsigned int i, nr = 1;
> bool_t forced_unbind;
> struct pirq *info;
> struct msi_desc *msi_desc = NULL;
> @@ -2018,6 +2094,18 @@ int unmap_domain_pirq(struct domain *d,
>
> desc = irq_to_desc(irq);
> msi_desc = desc->msi_desc;
> + if ( msi_desc && msi_desc->msi_attrib.type == PCI_CAP_ID_MSI )
> + {
> + if ( msi_desc->msi_attrib.entry_nr )
> + {
> + printk(XENLOG_G_ERR
> + "dom%d: trying to unmap secondary MSI pirq %d\n",
> + d->domain_id, pirq);
> + ret = -EBUSY;
> + goto done;
> + }
> + nr = msi_desc->msi.nvec;
> + }
>
> ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
> if ( ret )
> @@ -2033,37 +2121,83 @@ int unmap_domain_pirq(struct domain *d,
>
> spin_lock_irqsave(&desc->lock, flags);
>
> - BUG_ON(irq != domain_pirq_to_irq(d, pirq));
> -
> - if ( !forced_unbind )
> - clear_domain_irq_pirq(d, irq, info);
> - else
> + for ( i = 0; ; )
> {
> - info->arch.irq = -irq;
> - radix_tree_replace_slot(
> - radix_tree_lookup_slot(&d->arch.irq_pirq, irq),
> - radix_tree_int_to_ptr(-pirq));
> + BUG_ON(irq != domain_pirq_to_irq(d, pirq + i));
> +
> + if ( !forced_unbind )
> + clear_domain_irq_pirq(d, irq, info);
> + else
> + {
> + info->arch.irq = -irq;
> + radix_tree_replace_slot(
> + radix_tree_lookup_slot(&d->arch.irq_pirq, irq),
> + radix_tree_int_to_ptr(-pirq));
> + }
> +
> + if ( msi_desc )
> + {
> + desc->handler = &no_irq_type;
> + desc->msi_desc = NULL;
> + }
> +
> + if ( ++i == nr )
> + break;
> +
> + spin_unlock_irqrestore(&desc->lock, flags);
> +
> + if ( !forced_unbind )
> + cleanup_domain_irq_pirq(d, irq, info);
> +
> + rc = irq_deny_access(d, irq);
> + if ( rc )
> + {
> + printk(XENLOG_G_ERR
> + "dom%d: could not deny access to IRQ%d (pirq %d)\n",
> + d->domain_id, irq, pirq + i);
> + ret = rc;
> + }
> +
> + do {
> + info = pirq_info(d, pirq + i);
> + if ( info && (irq = info->arch.irq) > 0 )
> + break;
> + printk(XENLOG_G_ERR "dom%d: MSI pirq %d not mapped\n",
> + d->domain_id, pirq + i);
> + } while ( ++i < nr );
> +
> + if ( i == nr )
> + {
> + desc = NULL;
> + break;
> + }
> +
> + desc = irq_to_desc(irq);
> + BUG_ON(desc->msi_desc != msi_desc + i);
> +
> + spin_lock_irqsave(&desc->lock, flags);
> }
>
> - if ( msi_desc )
> + if ( desc )
> {
> - desc->handler = &no_irq_type;
> - desc->msi_desc = NULL;
> + spin_unlock_irqrestore(&desc->lock, flags);
> +
> + if ( !forced_unbind )
> + cleanup_domain_irq_pirq(d, irq, info);
> +
> + rc = irq_deny_access(d, irq);
> + if ( rc )
> + {
> + printk(XENLOG_G_ERR
> + "dom%d: could not deny access to IRQ%d (pirq %d)\n",
> + d->domain_id, irq, pirq + nr - 1);
> + ret = rc;
> + }
> }
>
> - spin_unlock_irqrestore(&desc->lock, flags);
> if (msi_desc)
> msi_free_irq(msi_desc);
>
> - if ( !forced_unbind )
> - cleanup_domain_irq_pirq(d, irq, info);
> -
> - ret = irq_deny_access(d, irq);
> - if ( ret )
> - printk(XENLOG_G_ERR
> - "dom%d: could not deny access to IRQ%d (pirq %d)\n",
> - d->domain_id, irq, pirq);
> -
> done:
> return ret;
> }
> --- a/xen/arch/x86/msi.c
> +++ b/xen/arch/x86/msi.c
> @@ -236,6 +236,11 @@ static int write_msi_msg(struct msi_desc
> u8 bus = dev->bus;
> u8 slot = PCI_SLOT(dev->devfn);
> u8 func = PCI_FUNC(dev->devfn);
> + int nr = entry->msi_attrib.entry_nr;
> +
> + ASSERT((msg->data & (entry[-nr].msi.nvec - 1)) == nr);
> + if ( nr )
> + return 0;
>
> pci_conf_write32(seg, bus, slot, func, msi_lower_address_reg(pos),
> msg->address_lo);
> @@ -359,8 +364,8 @@ static void msi_set_mask_bit(struct irq_
> u8 func = PCI_FUNC(entry->dev->devfn);
>
> mask_bits = pci_conf_read32(seg, bus, slot, func, entry->msi.mpos);
> - mask_bits &= ~(1);
> - mask_bits |= flag;
> + mask_bits &= ~((u32)1 << entry->msi_attrib.entry_nr);
> + mask_bits |= (u32)flag << entry->msi_attrib.entry_nr;
> pci_conf_write32(seg, bus, slot, func, entry->msi.mpos, mask_bits);
> }
> break;
> @@ -384,10 +389,11 @@ static int msi_get_mask_bit(const struct
> case PCI_CAP_ID_MSI:
> if (!entry->dev || !entry->msi_attrib.maskbit)
> break;
> - return pci_conf_read32(entry->dev->seg, entry->dev->bus,
> - PCI_SLOT(entry->dev->devfn),
> - PCI_FUNC(entry->dev->devfn),
> - entry->msi.mpos) & 1;
> + return (pci_conf_read32(entry->dev->seg, entry->dev->bus,
> + PCI_SLOT(entry->dev->devfn),
> + PCI_FUNC(entry->dev->devfn),
> + entry->msi.mpos) >>
> + entry->msi_attrib.entry_nr) & 1;
> case PCI_CAP_ID_MSIX:
> return readl(entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) & 1;
> }
> @@ -453,17 +459,20 @@ static hw_irq_controller pci_msi_nonmask
> .set_affinity = set_msi_affinity
> };
>
> -static struct msi_desc* alloc_msi_entry(void)
> +static struct msi_desc *alloc_msi_entry(unsigned int nr)
> {
> struct msi_desc *entry;
>
> - entry = xmalloc(struct msi_desc);
> + entry = xmalloc_array(struct msi_desc, nr);
> if ( !entry )
> return NULL;
>
> INIT_LIST_HEAD(&entry->list);
> - entry->dev = NULL;
> - entry->remap_index = -1;
> + while ( nr-- )
> + {
> + entry[nr].dev = NULL;
> + entry[nr].remap_index = -1;
> + }
>
> return entry;
> }
> @@ -488,17 +497,24 @@ int __setup_msi_irq(struct irq_desc *des
>
> int msi_free_irq(struct msi_desc *entry)
> {
> - destroy_irq(entry->irq);
> + unsigned int nr = entry->msi.nvec;
> +
> if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
> {
> unsigned long start;
> start = (unsigned long)entry->mask_base & ~(PAGE_SIZE - 1);
> msix_put_fixmap(entry->dev, virt_to_fix(start));
> + nr = 1;
> }
>
> - /* Free the unused IRTE if intr remap enabled */
> - if ( iommu_intremap )
> - iommu_update_ire_from_msi(entry, NULL);
> + while ( nr-- )
> + {
> + destroy_irq(entry[nr].irq);
> +
> + /* Free the unused IRTE if intr remap enabled */
> + if ( iommu_intremap )
> + iommu_update_ire_from_msi(entry + nr, NULL);
> + }
>
> list_del(&entry->list);
> xfree(entry);
> @@ -531,11 +547,12 @@ static struct msi_desc *find_msi_entry(s
> **/
> static int msi_capability_init(struct pci_dev *dev,
> int irq,
> - struct msi_desc **desc)
> + struct msi_desc **desc,
> + unsigned int nvec)
> {
> struct msi_desc *entry;
> int pos;
> - unsigned int maxvec, mpos;
> + unsigned int i, maxvec, mpos;
> u16 control, seg = dev->seg;
> u8 bus = dev->bus;
> u8 slot = PCI_SLOT(dev->devfn);
> @@ -545,27 +562,34 @@ static int msi_capability_init(struct pc
> pos = pci_find_cap_offset(seg, bus, slot, func, PCI_CAP_ID_MSI);
> control = pci_conf_read16(seg, bus, slot, func, msi_control_reg(pos));
> maxvec = multi_msi_capable(control);
> + if ( nvec > maxvec )
> + return maxvec;
> control &= ~PCI_MSI_FLAGS_QSIZE;
> + multi_msi_enable(control, nvec);
>
> /* MSI Entry Initialization */
> msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
>
> - entry = alloc_msi_entry();
> + entry = alloc_msi_entry(nvec);
> if ( !entry )
> return -ENOMEM;
>
> - entry->msi_attrib.type = PCI_CAP_ID_MSI;
> - entry->msi_attrib.is_64 = is_64bit_address(control);
> - entry->msi_attrib.entry_nr = 0;
> - entry->msi_attrib.maskbit = is_mask_bit_support(control);
> - entry->msi_attrib.masked = 1;
> - entry->msi_attrib.pos = pos;
> mpos = msi_mask_bits_reg(pos, is_64bit_address(control));
> - entry->msi.nvec = 1;
> + for ( i = 0; i < nvec; ++i )
> + {
> + entry[i].msi_attrib.type = PCI_CAP_ID_MSI;
> + entry[i].msi_attrib.is_64 = is_64bit_address(control);
> + entry[i].msi_attrib.entry_nr = i;
> + entry[i].msi_attrib.maskbit = is_mask_bit_support(control);
> + entry[i].msi_attrib.masked = 1;
> + entry[i].msi_attrib.pos = pos;
> + if ( entry[i].msi_attrib.maskbit )
> + entry[i].msi.mpos = mpos;
> + entry[i].msi.nvec = 0;
> + entry[i].dev = dev;
> + }
> + entry->msi.nvec = nvec;
> entry->irq = irq;
> - if ( is_mask_bit_support(control) )
> - entry->msi.mpos = mpos;
> - entry->dev = dev;
> if ( entry->msi_attrib.maskbit )
> {
> u32 maskbits;
> @@ -693,7 +717,7 @@ static int msix_capability_init(struct p
>
> if ( desc )
> {
> - entry = alloc_msi_entry();
> + entry = alloc_msi_entry(1);
> if ( !entry )
> return -ENOMEM;
> ASSERT(msi);
> @@ -851,7 +875,6 @@ static int msix_capability_init(struct p
>
> static int __pci_enable_msi(struct msi_info *msi, struct msi_desc **desc)
> {
> - int status;
> struct pci_dev *pdev;
> struct msi_desc *old_desc;
>
> @@ -880,8 +903,7 @@ static int __pci_enable_msi(struct msi_i
> pci_disable_msi(old_desc);
> }
>
> - status = msi_capability_init(pdev, msi->irq, desc);
> - return status;
> + return msi_capability_init(pdev, msi->irq, desc, msi->entry_nr);
> }
>
> static void __pci_disable_msi(struct msi_desc *entry)
> @@ -1101,6 +1123,8 @@ int pci_restore_msi_state(struct pci_dev
>
> list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list )
> {
> + unsigned int i = 0, nr = 1;
> +
> irq = entry->irq;
> desc = &irq_desc[irq];
>
> @@ -1110,30 +1134,58 @@ int pci_restore_msi_state(struct pci_dev
>
> if (desc->msi_desc != entry)
> {
> + bogus:
> dprintk(XENLOG_ERR,
> - "Restore MSI for dev %04x:%02x:%02x:%x not set before?\n",
> + "Restore MSI for %04x:%02x:%02x:%u entry %u not set?\n",
> pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
> - PCI_FUNC(pdev->devfn));
> + PCI_FUNC(pdev->devfn), i);
> spin_unlock_irqrestore(&desc->lock, flags);
> return -EINVAL;
> }
>
> if ( entry->msi_attrib.type == PCI_CAP_ID_MSI )
> + {
> msi_set_enable(pdev, 0);
> + nr = entry->msi.nvec;
> + }
> else if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
> msix_set_enable(pdev, 0);
>
> msg = entry->msg;
> write_msi_msg(entry, &msg);
>
> - msi_set_mask_bit(desc, entry->msi_attrib.masked);
> + for ( i = 0; ; )
> + {
> + msi_set_mask_bit(desc, entry[i].msi_attrib.masked);
> + spin_unlock_irqrestore(&desc->lock, flags);
> +
> + if ( !--nr )
> + break;
> +
> + desc = &irq_desc[entry[++i].irq];
> + spin_lock_irqsave(&desc->lock, flags);
> + if ( desc->msi_desc != entry + i )
> + goto bogus;
> + }
> +
> + spin_unlock_irqrestore(&desc->lock, flags);
>
> if ( entry->msi_attrib.type == PCI_CAP_ID_MSI )
> + {
> + unsigned int cpos = msi_control_reg(entry->msi_attrib.pos);
> + u16 control = pci_conf_read16(pdev->seg, pdev->bus,
> + PCI_SLOT(pdev->devfn),
> + PCI_FUNC(pdev->devfn), cpos);
> +
> + control &= ~PCI_MSI_FLAGS_QSIZE;
> + multi_msi_enable(control, entry->msi.nvec);
> + pci_conf_write16(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
> + PCI_FUNC(pdev->devfn), cpos, control);
> +
> msi_set_enable(pdev, 1);
> + }
> else if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
> msix_set_enable(pdev, 1);
> -
> - spin_unlock_irqrestore(&desc->lock, flags);
> }
>
> return 0;
> --- a/xen/arch/x86/physdev.c
> +++ b/xen/arch/x86/physdev.c
> @@ -140,8 +140,11 @@ int physdev_map_pirq(domid_t domid, int
> break;
>
> case MAP_PIRQ_TYPE_MSI:
> + if ( !msi->table_base )
> + msi->entry_nr = 1;
> irq = *index;
> if ( irq == -1 )
> + case MAP_PIRQ_TYPE_MULTI_MSI:
> irq = create_irq(NUMA_NO_NODE);
>
> if ( irq < nr_irqs_gsi || irq >= nr_irqs )
> @@ -179,6 +182,30 @@ int physdev_map_pirq(domid_t domid, int
> goto done;
> }
> }
> + else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
> + {
> + if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
> + ret = -EDOM;
> + else if ( msi->entry_nr != 1 && !iommu_intremap )
> + ret = -EOPNOTSUPP;
> + else
> + {
> + while ( msi->entry_nr & (msi->entry_nr - 1) )
> + msi->entry_nr += msi->entry_nr & -msi->entry_nr;
> + pirq = get_free_pirqs(d, msi->entry_nr);
> + if ( pirq < 0 )
> + {
> + while ( (msi->entry_nr >>= 1) > 1 )
> + if ( get_free_pirqs(d, msi->entry_nr) > 0 )
> + break;
> + dprintk(XENLOG_G_ERR, "dom%d: no block of %d free pirqs\n",
> + d->domain_id, msi->entry_nr << 1);
> + ret = pirq;
> + }
> + }
> + if ( ret < 0 )
> + goto done;
> + }
> else
> {
> pirq = get_free_pirq(d, type);
> @@ -210,8 +237,15 @@ int physdev_map_pirq(domid_t domid, int
> done:
> spin_unlock(&d->event_lock);
> spin_unlock(&pcidevs_lock);
> - if ( (ret != 0) && (type == MAP_PIRQ_TYPE_MSI) && (*index == -1) )
> - destroy_irq(irq);
> + if ( ret != 0 )
> + switch ( type )
> + {
> + case MAP_PIRQ_TYPE_MSI:
> + if ( *index == -1 )
> + case MAP_PIRQ_TYPE_MULTI_MSI:
> + destroy_irq(irq);
> + break;
> + }
Do we not need to create and destroy entry_nr irqs in this function, or
is a multi-vector-msi now considered as just as single irq ?
I ask because this appears to lack the "repeating certain operations for
all involved IRQs" described in the comment.
~Andrew
> free_domain:
> rcu_unlock_domain(d);
> return ret;
> @@ -390,14 +424,22 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
> if ( copy_from_guest(&map, arg, 1) != 0 )
> break;
>
> - if ( map.type == MAP_PIRQ_TYPE_MSI_SEG )
> + switch ( map.type )
> {
> + case MAP_PIRQ_TYPE_MSI_SEG:
> map.type = MAP_PIRQ_TYPE_MSI;
> msi.seg = map.bus >> 16;
> - }
> - else
> - {
> + break;
> +
> + case MAP_PIRQ_TYPE_MULTI_MSI:
> + if ( map.table_base )
> + return -EINVAL;
> + msi.seg = map.bus >> 16;
> + break;
> +
> + default:
> msi.seg = 0;
> + break;
> }
> msi.bus = map.bus;
> msi.devfn = map.devfn;
> @@ -406,6 +448,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
> ret = physdev_map_pirq(map.domid, map.type, &map.index, &map.pirq,
> &msi);
>
> + if ( map.type == MAP_PIRQ_TYPE_MULTI_MSI )
> + map.entry_nr = msi.entry_nr;
> if ( __copy_to_guest(arg, &map, 1) )
> ret = -EFAULT;
> break;
> --- a/xen/include/asm-x86/irq.h
> +++ b/xen/include/asm-x86/irq.h
> @@ -141,6 +141,7 @@ int map_domain_pirq(struct domain *d, in
> void *data);
> int unmap_domain_pirq(struct domain *d, int pirq);
> int get_free_pirq(struct domain *d, int type);
> +int get_free_pirqs(struct domain *, unsigned int nr);
> void free_domain_pirqs(struct domain *d);
> int map_domain_emuirq_pirq(struct domain *d, int pirq, int irq);
> int unmap_domain_pirq_emuirq(struct domain *d, int pirq);
> --- a/xen/include/asm-x86/msi.h
> +++ b/xen/include/asm-x86/msi.h
> @@ -148,7 +148,7 @@ int msi_free_irq(struct msi_desc *entry)
> #define multi_msi_capable(control) \
> (1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1))
> #define multi_msi_enable(control, num) \
> - control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE);
> + control |= (((fls(num) - 1) << 4) & PCI_MSI_FLAGS_QSIZE);
> #define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT))
> #define is_mask_bit_support(control) (!!(control & PCI_MSI_FLAGS_MASKBIT))
> #define msi_enable(control, num) multi_msi_enable(control, num); \
> --- a/xen/include/public/physdev.h
> +++ b/xen/include/public/physdev.h
> @@ -151,21 +151,22 @@ DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
> #define MAP_PIRQ_TYPE_GSI 0x1
> #define MAP_PIRQ_TYPE_UNKNOWN 0x2
> #define MAP_PIRQ_TYPE_MSI_SEG 0x3
> +#define MAP_PIRQ_TYPE_MULTI_MSI 0x4
>
> #define PHYSDEVOP_map_pirq 13
> struct physdev_map_pirq {
> domid_t domid;
> /* IN */
> int type;
> - /* IN */
> + /* IN (ignored for ..._MULTI_MSI) */
> int index;
> /* IN or OUT */
> int pirq;
> - /* IN - high 16 bits hold segment for MAP_PIRQ_TYPE_MSI_SEG */
> + /* IN - high 16 bits hold segment for ..._MSI_SEG and ..._MULTI_MSI */
> int bus;
> /* IN */
> int devfn;
> - /* IN */
> + /* IN (also OUT for ..._MULTI_MSI) */
> int entry_nr;
> /* IN */
> uint64_t table_base;
>
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
[-- Attachment #1.2: Type: text/html, Size: 25128 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2013-07-16 11:36 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-16 10:00 [PATCH resend 0/3] x86/IOMMU: multi-vector MSI Jan Beulich
2013-07-16 10:13 ` [PATCH resend 1/3] VT-d: enable for " Jan Beulich
2013-07-16 11:15 ` Andrew Cooper
2013-07-16 11:32 ` Jan Beulich
2013-07-17 9:50 ` Andrew Cooper
2013-07-18 10:48 ` Zhang, Xiantao
2013-07-16 10:14 ` [PATCH resend 2/3] x86: enable " Jan Beulich
2013-07-16 11:36 ` Andrew Cooper [this message]
2013-07-16 11:48 ` Jan Beulich
2013-07-17 10:02 ` Andrew Cooper
2013-08-05 13:11 ` Ping: " Jan Beulich
2013-08-08 9:02 ` Keir Fraser
2013-07-16 10:15 ` [PATCH resend 3/3] pciif: add multi-vector-MSI command Jan Beulich
2013-07-16 11:19 ` Andrew Cooper
2013-07-16 11:35 ` Jan Beulich
2013-07-17 9:02 ` Andrew Cooper
2013-08-05 13:12 ` Ping: " Jan Beulich
2013-08-08 9:02 ` Keir Fraser
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51E53046.1040809@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=JBeulich@suse.com \
--cc=keir@xen.org \
--cc=xen-devel@lists.xen.org \
--cc=xiantao.zhang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.