From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v4 4/6] x86/MSI-X: access MSI-X table only after having enabled MSI-X Date: Mon, 22 Jun 2015 15:50:07 +0100 Message-ID: <55883CBF0200007800087A2C@mail.emea.novell.com> References: <558839ED02000078000879FE@mail.emea.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part1A2ECA8F.1__=" Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Z7338-0000h0-Dx for xen-devel@lists.xenproject.org; Mon, 22 Jun 2015 14:50:14 +0000 In-Reply-To: <558839ED02000078000879FE@mail.emea.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel Cc: Andrew Cooper , Keir Fraser List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part1A2ECA8F.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline As done in Linux by f598282f51 ("PCI: Fix the NIU MSI-X problem in a better way") and its broken predecessor, make sure we don't access the MSI-X table without having enabled MSI-X first, using the mask-all flag instead to prevent interrupts from occurring. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -144,6 +144,17 @@ static bool_t memory_decoded(const struc PCI_COMMAND_MEMORY); } =20 +static bool_t msix_memory_decoded(const struct pci_dev *dev, unsigned int = pos) +{ + u16 control =3D pci_conf_read16(dev->seg, dev->bus, PCI_SLOT(dev->devf= n), + PCI_FUNC(dev->devfn), msix_control_reg(p= os)); + + if ( !(control & PCI_MSIX_FLAGS_ENABLE) ) + return 0; + + return memory_decoded(dev); +} + /* * MSI message composition */ @@ -222,7 +233,8 @@ static bool_t read_msi_msg(struct msi_de { void __iomem *base =3D entry->mask_base; =20 - if ( unlikely(!memory_decoded(entry->dev)) ) + if ( unlikely(!msix_memory_decoded(entry->dev, + entry->msi_attrib.pos)) ) return 0; msg->address_lo =3D readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET)= ; msg->address_hi =3D readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET)= ; @@ -287,7 +299,8 @@ static int write_msi_msg(struct msi_desc { void __iomem *base =3D entry->mask_base; =20 - if ( unlikely(!memory_decoded(entry->dev)) ) + if ( unlikely(!msix_memory_decoded(entry->dev, + entry->msi_attrib.pos)) ) return -ENXIO; writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); @@ -381,9 +394,9 @@ static bool_t msi_set_mask_bit(struct ir { struct msi_desc *entry =3D desc->msi_desc; struct pci_dev *pdev; - u16 seg; + u16 seg, control; u8 bus, slot, func; - bool_t flag =3D host || guest; + bool_t flag =3D host || guest, maskall; =20 ASSERT(spin_is_locked(&desc->lock)); BUG_ON(!entry || !entry->dev); @@ -406,36 +419,45 @@ static bool_t msi_set_mask_bit(struct ir } break; case PCI_CAP_ID_MSIX: + maskall =3D pdev->msix->host_maskall; + control =3D pci_conf_read16(seg, bus, slot, func, + msix_control_reg(entry->msi_attrib.pos))= ; + if ( unlikely(!(control & PCI_MSIX_FLAGS_ENABLE)) ) + { + pdev->msix->host_maskall =3D 1; + pci_conf_write16(seg, bus, slot, func, + msix_control_reg(entry->msi_attrib.pos), + control | (PCI_MSIX_FLAGS_ENABLE | + PCI_MSIX_FLAGS_MASKALL)); + } if ( likely(memory_decoded(pdev)) ) { writel(flag, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFF= SET); readl(entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); - break; + if ( likely(control & PCI_MSIX_FLAGS_ENABLE) ) + break; + flag =3D 1; } - if ( flag ) + else if ( flag && !(control & PCI_MSIX_FLAGS_MASKALL) ) { - u16 control; domid_t domid =3D pdev->domain->domain_id; =20 - pdev->msix->host_maskall =3D 1; - control =3D pci_conf_read16(seg, bus, slot, func, - msix_control_reg(entry->msi_attrib.p= os)); - if ( control & PCI_MSIX_FLAGS_MASKALL ) - break; - pci_conf_write16(seg, bus, slot, func, - msix_control_reg(entry->msi_attrib.pos), - control | PCI_MSIX_FLAGS_MASKALL); + maskall =3D 1; if ( pdev->msix->warned !=3D domid ) { pdev->msix->warned =3D domid; printk(XENLOG_G_WARNING - "cannot mask IRQ %d: masked MSI-X on Dom%d's = %04x:%02x:%02x.%u\n", + "cannot mask IRQ %d: masking MSI-X on Dom%d's = %04x:%02x:%02x.%u\n", desc->irq, domid, pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); } - break; } - /* fall through */ + pdev->msix->host_maskall =3D maskall; + if ( maskall || pdev->msix->guest_maskall ) + control |=3D PCI_MSIX_FLAGS_MASKALL; + pci_conf_write16(seg, bus, slot, func, + msix_control_reg(entry->msi_attrib.pos), = control); + return flag; default: return 0; } @@ -461,7 +483,8 @@ static int msi_get_mask_bit(const struct entry->msi.mpos) >> entry->msi_attrib.entry_nr) & 1; case PCI_CAP_ID_MSIX: - if ( unlikely(!memory_decoded(entry->dev)) ) + if ( unlikely(!msix_memory_decoded(entry->dev, + entry->msi_attrib.pos)) ) break; return readl(entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)= & 1; } @@ -567,9 +590,31 @@ static struct msi_desc *alloc_msi_entry( =20 int setup_msi_irq(struct irq_desc *desc, struct msi_desc *msidesc) { - return __setup_msi_irq(desc, msidesc, - msi_maskable_irq(msidesc) ? &pci_msi_maskable - : &pci_msi_nonmaskabl= e); + const struct pci_dev *pdev =3D msidesc->dev; + unsigned int cpos =3D msix_control_reg(msidesc->msi_attrib.pos); + u16 control =3D ~0; + int rc; + + if ( msidesc->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX ) + { + control =3D pci_conf_read16(pdev->seg, pdev->bus, PCI_SLOT(pdev->d= evfn), + PCI_FUNC(pdev->devfn), cpos); + if ( !(control & PCI_MSIX_FLAGS_ENABLE) ) + pci_conf_write16(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), cpos, + control | (PCI_MSIX_FLAGS_ENABLE | + PCI_MSIX_FLAGS_MASKALL)); + } + + rc =3D __setup_msi_irq(desc, msidesc, + msi_maskable_irq(msidesc) ? &pci_msi_maskable + : &pci_msi_nonmaskable)= ; + + if ( !(control & PCI_MSIX_FLAGS_ENABLE) ) + pci_conf_write16(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), cpos, control); + + return rc; } =20 int __setup_msi_irq(struct irq_desc *desc, struct msi_desc *msidesc, @@ -806,20 +851,38 @@ static int msix_capability_init(struct p u8 bus =3D dev->bus; u8 slot =3D PCI_SLOT(dev->devfn); u8 func =3D PCI_FUNC(dev->devfn); + bool_t maskall =3D msix->host_maskall; =20 ASSERT(spin_is_locked(&pcidevs_lock)); =20 control =3D pci_conf_read16(seg, bus, slot, func, msix_control_reg(pos= )); - msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */ + /* + * Ensure MSI-X interrupts are masked during setup. Some devices = require + * MSI-X to be enabled before we can touch the MSI-X registers. We = need + * to mask all the vectors to prevent interrupts coming in before = they're + * fully set up. + */ + msix->host_maskall =3D 1; + pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), + control | (PCI_MSIX_FLAGS_ENABLE | + PCI_MSIX_FLAGS_MASKALL)); =20 if ( unlikely(!memory_decoded(dev)) ) + { + pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), + control & ~PCI_MSIX_FLAGS_ENABLE); return -ENXIO; + } =20 if ( desc ) { entry =3D alloc_msi_entry(1); if ( !entry ) + { + pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), + control & ~PCI_MSIX_FLAGS_ENABLE); return -ENOMEM; + } ASSERT(msi); } =20 @@ -850,6 +913,8 @@ static int msix_capability_init(struct p { if ( !msi || !msi->table_base ) { + pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), + control & ~PCI_MSIX_FLAGS_ENABLE); xfree(entry); return -ENXIO; } @@ -892,6 +957,8 @@ static int msix_capability_init(struct p =20 if ( idx < 0 ) { + pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), + control & ~PCI_MSIX_FLAGS_ENABLE); xfree(entry); return idx; } @@ -918,7 +985,7 @@ static int msix_capability_init(struct p =20 if ( !msix->used_entries ) { - msix->host_maskall =3D 0; + maskall =3D 0; if ( !msix->guest_maskall ) control &=3D ~PCI_MSIX_FLAGS_MASKALL; else @@ -954,8 +1021,8 @@ static int msix_capability_init(struct p ++msix->used_entries; =20 /* Restore MSI-X enabled bits */ - pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), - control & ~PCI_MSIX_FLAGS_MASKALL); + msix->host_maskall =3D maskall; + pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), = control); =20 return 0; } @@ -1095,8 +1162,15 @@ static void __pci_disable_msix(struct ms PCI_CAP_ID_MSIX); u16 control =3D pci_conf_read16(seg, bus, slot, func, msix_control_reg(entry->msi_attrib.pos))= ; + bool_t maskall =3D dev->msix->host_maskall; =20 - msix_set_enable(dev, 0); + if ( unlikely(!(control & PCI_MSIX_FLAGS_ENABLE)) ) + { + dev->msix->host_maskall =3D 1; + pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), + control | (PCI_MSIX_FLAGS_ENABLE | + PCI_MSIX_FLAGS_MASKALL)); + } =20 BUG_ON(list_empty(&dev->msi_list)); =20 @@ -1108,8 +1182,11 @@ static void __pci_disable_msix(struct ms "cannot disable IRQ %d: masking MSI-X on %04x:%02x:%02x.%u\= n", entry->irq, dev->seg, dev->bus, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); - control |=3D PCI_MSIX_FLAGS_MASKALL; + maskall =3D 1; } + dev->msix->host_maskall =3D maskall; + if ( maskall || dev->msix->guest_maskall ) + control |=3D PCI_MSIX_FLAGS_MASKALL; pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), = control); =20 _pci_cleanup_msix(dev->msix); @@ -1260,6 +1337,8 @@ int pci_restore_msi_state(struct pci_dev list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list ) { unsigned int i =3D 0, nr =3D 1; + u16 control =3D 0; + u8 slot =3D PCI_SLOT(pdev->devfn), func =3D PCI_FUNC(pdev->devfn);= =20 irq =3D entry->irq; desc =3D &irq_desc[irq]; @@ -1286,10 +1365,18 @@ int pci_restore_msi_state(struct pci_dev } else if ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX ) { - msix_set_enable(pdev, 0); + control =3D pci_conf_read16(pdev->seg, pdev->bus, slot, func, + msix_control_reg(entry->msi_attrib.p= os)); + pci_conf_write16(pdev->seg, pdev->bus, slot, func, + msix_control_reg(entry->msi_attrib.pos), + control | (PCI_MSIX_FLAGS_ENABLE | + PCI_MSIX_FLAGS_MASKALL)); if ( unlikely(!memory_decoded(pdev)) ) { spin_unlock_irqrestore(&desc->lock, flags); + pci_conf_write16(pdev->seg, pdev->bus, slot, func, + msix_control_reg(entry->msi_attrib.pos), + control & ~PCI_MSIX_FLAGS_ENABLE); return -ENXIO; } } @@ -1319,11 +1406,9 @@ int pci_restore_msi_state(struct pci_dev if ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSI ) { unsigned int cpos =3D msi_control_reg(entry->msi_attrib.pos); - u16 control =3D pci_conf_read16(pdev->seg, pdev->bus, - PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), cpos); =20 - control &=3D ~PCI_MSI_FLAGS_QSIZE; + control =3D pci_conf_read16(pdev->seg, pdev->bus, slot, func, = cpos) & + ~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); @@ -1331,7 +1416,9 @@ int pci_restore_msi_state(struct pci_dev msi_set_enable(pdev, 1); } else if ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX ) - msix_set_enable(pdev, 1); + pci_conf_write16(pdev->seg, pdev->bus, slot, func, + msix_control_reg(entry->msi_attrib.pos), + control | PCI_MSIX_FLAGS_ENABLE); } =20 return 0; --=__Part1A2ECA8F.1__= Content-Type: text/plain; name="x86-MSI-X-enable.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-MSI-X-enable.patch" x86/MSI-X: access MSI-X table only after having enabled MSI-X=0A=0AAs done = in Linux by f598282f51 ("PCI: Fix the NIU MSI-X problem in a=0Abetter = way") and its broken predecessor, make sure we don't access the=0AMSI-X = table without having enabled MSI-X first, using the mask-all flag=0Ainstead= to prevent interrupts from occurring.=0A=0ASigned-off-by: Jan Beulich = =0AReviewed-by: Andrew Cooper =0A=0A--- a/xen/arch/x86/msi.c=0A+++ b/xen/arch/x86/msi.c=0A@@ -144,6 = +144,17 @@ static bool_t memory_decoded(const struc=0A = PCI_COMMAND_MEMORY);=0A }=0A =0A+static bool_t msix_memory_decoded(const = struct pci_dev *dev, unsigned int pos)=0A+{=0A+ u16 control =3D = pci_conf_read16(dev->seg, dev->bus, PCI_SLOT(dev->devfn),=0A+ = PCI_FUNC(dev->devfn), msix_control_reg(pos));=0A+=0A+ = if ( !(control & PCI_MSIX_FLAGS_ENABLE) )=0A+ return 0;=0A+=0A+ = return memory_decoded(dev);=0A+}=0A+=0A /*=0A * MSI message composition= =0A */=0A@@ -222,7 +233,8 @@ static bool_t read_msi_msg(struct msi_de=0A = {=0A void __iomem *base =3D entry->mask_base;=0A =0A- if = ( unlikely(!memory_decoded(entry->dev)) )=0A+ if ( unlikely(!msix_me= mory_decoded(entry->dev,=0A+ = entry->msi_attrib.pos)) )=0A return 0;=0A msg->address_= lo =3D readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);=0A = msg->address_hi =3D readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);=0A@@ = -287,7 +299,8 @@ static int write_msi_msg(struct msi_desc=0A {=0A = void __iomem *base =3D entry->mask_base;=0A =0A- if ( unlikely(!m= emory_decoded(entry->dev)) )=0A+ if ( unlikely(!msix_memory_decoded(= entry->dev,=0A+ entry->msi_attrib= .pos)) )=0A return -ENXIO;=0A writel(msg->address_lo,= =0A base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);=0A@@ -381,9 = +394,9 @@ static bool_t msi_set_mask_bit(struct ir=0A {=0A struct = msi_desc *entry =3D desc->msi_desc;=0A struct pci_dev *pdev;=0A- = u16 seg;=0A+ u16 seg, control;=0A u8 bus, slot, func;=0A- bool_t = flag =3D host || guest;=0A+ bool_t flag =3D host || guest, maskall;=0A = =0A ASSERT(spin_is_locked(&desc->lock));=0A BUG_ON(!entry || = !entry->dev);=0A@@ -406,36 +419,45 @@ static bool_t msi_set_mask_bit(struct= ir=0A }=0A break;=0A case PCI_CAP_ID_MSIX:=0A+ = maskall =3D pdev->msix->host_maskall;=0A+ control =3D pci_conf_read1= 6(seg, bus, slot, func,=0A+ msix_control_r= eg(entry->msi_attrib.pos));=0A+ if ( unlikely(!(control & PCI_MSIX_F= LAGS_ENABLE)) )=0A+ {=0A+ pdev->msix->host_maskall =3D = 1;=0A+ pci_conf_write16(seg, bus, slot, func,=0A+ = msix_control_reg(entry->msi_attrib.pos),=0A+ = control | (PCI_MSIX_FLAGS_ENABLE |=0A+ = PCI_MSIX_FLAGS_MASKALL));=0A+ }=0A if ( = likely(memory_decoded(pdev)) )=0A {=0A writel(flag, = entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);=0A = readl(entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);=0A- = break;=0A+ if ( likely(control & PCI_MSIX_FLAGS_ENABLE) )=0A+ = break;=0A+ flag =3D 1;=0A }=0A- if = ( flag )=0A+ else if ( flag && !(control & PCI_MSIX_FLAGS_MASKALL) = )=0A {=0A- u16 control;=0A domid_t domid = =3D pdev->domain->domain_id;=0A =0A- pdev->msix->host_maskall = =3D 1;=0A- control =3D pci_conf_read16(seg, bus, slot, = func,=0A- msix_control_reg(entry->msi_= attrib.pos));=0A- if ( control & PCI_MSIX_FLAGS_MASKALL )=0A- = break;=0A- pci_conf_write16(seg, bus, slot, = func,=0A- msix_control_reg(entry->msi_attrib.po= s),=0A- control | PCI_MSIX_FLAGS_MASKALL);=0A+ = maskall =3D 1;=0A if ( pdev->msix->warned !=3D = domid )=0A {=0A pdev->msix->warned =3D = domid;=0A printk(XENLOG_G_WARNING=0A- = "cannot mask IRQ %d: masked MSI-X on Dom%d's %04x:%02x:%02x.%u\n",=0A+ = "cannot mask IRQ %d: masking MSI-X on Dom%d's %04x:%02x:= %02x.%u\n",=0A desc->irq, domid, pdev->seg, = pdev->bus,=0A PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->= devfn));=0A }=0A- break;=0A }=0A- /* = fall through */=0A+ pdev->msix->host_maskall =3D maskall;=0A+ = if ( maskall || pdev->msix->guest_maskall )=0A+ control |=3D = PCI_MSIX_FLAGS_MASKALL;=0A+ pci_conf_write16(seg, bus, slot, = func,=0A+ msix_control_reg(entry->msi_attrib.pos), = control);=0A+ return flag;=0A default:=0A return 0;=0A = }=0A@@ -461,7 +483,8 @@ static int msi_get_mask_bit(const struct=0A = entry->msi.mpos) >>=0A = entry->msi_attrib.entry_nr) & 1;=0A case PCI_CAP_ID_MSIX:=0A- = if ( unlikely(!memory_decoded(entry->dev)) )=0A+ if ( unlikely(!msix= _memory_decoded(entry->dev,=0A+ = entry->msi_attrib.pos)) )=0A break;=0A return = readl(entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) & 1;=0A = }=0A@@ -567,9 +590,31 @@ static struct msi_desc *alloc_msi_entry(=0A =0A = int setup_msi_irq(struct irq_desc *desc, struct msi_desc *msidesc)=0A = {=0A- return __setup_msi_irq(desc, msidesc,=0A- = msi_maskable_irq(msidesc) ? &pci_msi_maskable=0A- = : &pci_msi_nonmaskable);=0A+ const struct = pci_dev *pdev =3D msidesc->dev;=0A+ unsigned int cpos =3D msix_control_r= eg(msidesc->msi_attrib.pos);=0A+ u16 control =3D ~0;=0A+ int = rc;=0A+=0A+ if ( msidesc->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX )=0A+ = {=0A+ control =3D pci_conf_read16(pdev->seg, pdev->bus, PCI_SLOT(p= dev->devfn),=0A+ PCI_FUNC(pdev->devfn), = cpos);=0A+ if ( !(control & PCI_MSIX_FLAGS_ENABLE) )=0A+ = pci_conf_write16(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),=0A+ = PCI_FUNC(pdev->devfn), cpos,=0A+ = control | (PCI_MSIX_FLAGS_ENABLE |=0A+ = PCI_MSIX_FLAGS_MASKALL));=0A+ }=0A+=0A+ rc =3D __setup_msi_ir= q(desc, msidesc,=0A+ msi_maskable_irq(msidesc) ? = &pci_msi_maskable=0A+ : = &pci_msi_nonmaskable);=0A+=0A+ if ( !(control & PCI_MSIX_FLAGS_ENABLE) = )=0A+ pci_conf_write16(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),= =0A+ PCI_FUNC(pdev->devfn), cpos, control);=0A+=0A+= return rc;=0A }=0A =0A int __setup_msi_irq(struct irq_desc *desc, = struct msi_desc *msidesc,=0A@@ -806,20 +851,38 @@ static int msix_capabilit= y_init(struct p=0A u8 bus =3D dev->bus;=0A u8 slot =3D PCI_SLOT(dev= ->devfn);=0A u8 func =3D PCI_FUNC(dev->devfn);=0A+ bool_t maskall = =3D msix->host_maskall;=0A =0A ASSERT(spin_is_locked(&pcidevs_lock));= =0A =0A control =3D pci_conf_read16(seg, bus, slot, func, msix_control_= reg(pos));=0A- msix_set_enable(dev, 0);/* Ensure msix is disabled as I = set it up */=0A+ /*=0A+ * Ensure MSI-X interrupts are masked during = setup. Some devices require=0A+ * MSI-X to be enabled before we can = touch the MSI-X registers. We need=0A+ * to mask all the vectors to = prevent interrupts coming in before they're=0A+ * fully set up.=0A+ = */=0A+ msix->host_maskall =3D 1;=0A+ pci_conf_write16(seg, bus, = slot, func, msix_control_reg(pos),=0A+ control | = (PCI_MSIX_FLAGS_ENABLE |=0A+ PCI_MSIX_FLAGS_= MASKALL));=0A =0A if ( unlikely(!memory_decoded(dev)) )=0A+ {=0A+ = pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos),=0A+ = control & ~PCI_MSIX_FLAGS_ENABLE);=0A return = -ENXIO;=0A+ }=0A =0A if ( desc )=0A {=0A entry =3D = alloc_msi_entry(1);=0A if ( !entry )=0A+ {=0A+ = pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos),=0A+ = control & ~PCI_MSIX_FLAGS_ENABLE);=0A = return -ENOMEM;=0A+ }=0A ASSERT(msi);=0A }=0A =0A@@ = -850,6 +913,8 @@ static int msix_capability_init(struct p=0A {=0A = if ( !msi || !msi->table_base )=0A {=0A+ pci_conf_wri= te16(seg, bus, slot, func, msix_control_reg(pos),=0A+ = control & ~PCI_MSIX_FLAGS_ENABLE);=0A xfree(entry);=0A = return -ENXIO;=0A }=0A@@ -892,6 +957,8 @@ static int = msix_capability_init(struct p=0A =0A if ( idx < 0 )=0A = {=0A+ pci_conf_write16(seg, bus, slot, func, msix_control_reg(po= s),=0A+ control & ~PCI_MSIX_FLAGS_ENABLE);=0A = xfree(entry);=0A return idx;=0A }=0A@@ = -918,7 +985,7 @@ static int msix_capability_init(struct p=0A =0A if ( = !msix->used_entries )=0A {=0A- msix->host_maskall =3D 0;=0A+ = maskall =3D 0;=0A if ( !msix->guest_maskall )=0A = control &=3D ~PCI_MSIX_FLAGS_MASKALL;=0A else=0A@@ -954,8 +1021,8 = @@ static int msix_capability_init(struct p=0A ++msix->used_entries;=0A= =0A /* Restore MSI-X enabled bits */=0A- pci_conf_write16(seg, = bus, slot, func, msix_control_reg(pos),=0A- control & = ~PCI_MSIX_FLAGS_MASKALL);=0A+ msix->host_maskall =3D maskall;=0A+ = pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), control);=0A = =0A return 0;=0A }=0A@@ -1095,8 +1162,15 @@ static void __pci_disable_m= six(struct ms=0A PCI_CAP_ID_MSIX= );=0A u16 control =3D pci_conf_read16(seg, bus, slot, func,=0A = msix_control_reg(entry->msi_attrib.pos));=0A+ = bool_t maskall =3D dev->msix->host_maskall;=0A =0A- msix_set_enable(dev,= 0);=0A+ if ( unlikely(!(control & PCI_MSIX_FLAGS_ENABLE)) )=0A+ = {=0A+ dev->msix->host_maskall =3D 1;=0A+ pci_conf_write16(seg= , bus, slot, func, msix_control_reg(pos),=0A+ = control | (PCI_MSIX_FLAGS_ENABLE |=0A+ = PCI_MSIX_FLAGS_MASKALL));=0A+ }=0A =0A BUG_ON(list_empty(&dev->msi_l= ist));=0A =0A@@ -1108,8 +1182,11 @@ static void __pci_disable_msix(struct = ms=0A "cannot disable IRQ %d: masking MSI-X on %04x:%02x:%02= x.%u\n",=0A entry->irq, dev->seg, dev->bus,=0A = PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));=0A- control |=3D = PCI_MSIX_FLAGS_MASKALL;=0A+ maskall =3D 1;=0A }=0A+ = dev->msix->host_maskall =3D maskall;=0A+ if ( maskall || dev->msix->gues= t_maskall )=0A+ control |=3D PCI_MSIX_FLAGS_MASKALL;=0A = pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), control);=0A = =0A _pci_cleanup_msix(dev->msix);=0A@@ -1260,6 +1337,8 @@ int = pci_restore_msi_state(struct pci_dev=0A list_for_each_entry_safe( = entry, tmp, &pdev->msi_list, list )=0A {=0A unsigned int i =3D = 0, nr =3D 1;=0A+ u16 control =3D 0;=0A+ u8 slot =3D = PCI_SLOT(pdev->devfn), func =3D PCI_FUNC(pdev->devfn);=0A =0A irq = =3D entry->irq;=0A desc =3D &irq_desc[irq];=0A@@ -1286,10 +1365,18 = @@ int pci_restore_msi_state(struct pci_dev=0A }=0A else = if ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX )=0A {=0A- = msix_set_enable(pdev, 0);=0A+ control =3D pci_conf_read16(= pdev->seg, pdev->bus, slot, func,=0A+ = msix_control_reg(entry->msi_attrib.pos));=0A+ pci_conf_write16(p= dev->seg, pdev->bus, slot, func,=0A+ msix_contr= ol_reg(entry->msi_attrib.pos),=0A+ control | = (PCI_MSIX_FLAGS_ENABLE |=0A+ = PCI_MSIX_FLAGS_MASKALL));=0A if ( unlikely(!memory_decoded(pdev= )) )=0A {=0A spin_unlock_irqrestore(&desc->lock= , flags);=0A+ pci_conf_write16(pdev->seg, pdev->bus, slot, = func,=0A+ msix_control_reg(entry->msi_attri= b.pos),=0A+ control & ~PCI_MSIX_FLAGS_ENABL= E);=0A return -ENXIO;=0A }=0A }=0A@@ = -1319,11 +1406,9 @@ int pci_restore_msi_state(struct pci_dev=0A if = ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSI )=0A {=0A = unsigned int cpos =3D msi_control_reg(entry->msi_attrib.pos);=0A- = u16 control =3D pci_conf_read16(pdev->seg, pdev->bus,=0A- = PCI_SLOT(pdev->devfn),=0A- = PCI_FUNC(pdev->devfn), cpos);=0A =0A- = control &=3D ~PCI_MSI_FLAGS_QSIZE;=0A+ control =3D pci_conf_read= 16(pdev->seg, pdev->bus, slot, func, cpos) &=0A+ = ~PCI_MSI_FLAGS_QSIZE;=0A multi_msi_enable(control, entry->msi.n= vec);=0A pci_conf_write16(pdev->seg, pdev->bus, PCI_SLOT(pdev->= devfn),=0A PCI_FUNC(pdev->devfn), cpos, = control);=0A@@ -1331,7 +1416,9 @@ int pci_restore_msi_state(struct = pci_dev=0A msi_set_enable(pdev, 1);=0A }=0A = else if ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX )=0A- = msix_set_enable(pdev, 1);=0A+ pci_conf_write16(pdev->seg, = pdev->bus, slot, func,=0A+ msix_control_reg(ent= ry->msi_attrib.pos),=0A+ control | PCI_MSIX_FLA= GS_ENABLE);=0A }=0A =0A return 0;=0A --=__Part1A2ECA8F.1__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --=__Part1A2ECA8F.1__=--