From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v4 3/6] x86/MSI-X: be more careful during teardown Date: Mon, 22 Jun 2015 15:49:16 +0100 Message-ID: <55883C8C0200007800087A28@mail.emea.novell.com> References: <558839ED02000078000879FE@mail.emea.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartE9DD397C.1__=" Return-path: Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Z732I-0000YF-44 for xen-devel@lists.xenproject.org; Mon, 22 Jun 2015 14:49:22 +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. --=__PartE9DD397C.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline When a device gets detached from a guest, pciback will clear its command register, thus disabling both memory and I/O decoding. The disabled memory decoding, however, has an effect on the MSI-X table accesses the hypervisor does: These won't have the intended effect anymore. Even worse, for PCIe devices (but not SR-IOV virtual functions) such accesses may (will?) be treated as Unsupported Requests, causing respective errors to be surfaced, potentially in the form of NMIs that may be fatal to the hypervisor or Dom0 is different ways. Hence rather than carrying out these accesses, we should avoid them where we can, and use alternative (e.g. PCI config space based) mechanisms to achieve at least the same effect. At this time it continues to be unclear whether this is fixing an actual bug or is rather just working around bogus (but apparently common) system behavior. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- Backporting note (largely to myself): Depends on (not yet backported to 4.4 and earlier) commit 061eebe0e "x86/MSI: drop workaround for insecure Dom0 kernels" (due to re-use of struct arch_msix's warned field). --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -217,9 +217,9 @@ void destroy_irq(unsigned int irq) } =20 spin_lock_irqsave(&desc->lock, flags); - desc->status |=3D IRQ_DISABLED; desc->status &=3D ~IRQ_GUEST; desc->handler->shutdown(desc); + desc->status |=3D IRQ_DISABLED; action =3D desc->action; desc->action =3D NULL; desc->msi_desc =3D NULL; @@ -995,8 +995,8 @@ void __init release_irq(unsigned int irq spin_lock_irqsave(&desc->lock,flags); action =3D desc->action; desc->action =3D NULL; - desc->status |=3D IRQ_DISABLED; desc->handler->shutdown(desc); + desc->status |=3D IRQ_DISABLED; spin_unlock_irqrestore(&desc->lock,flags); =20 /* Wait to make sure it's not being used on another CPU */ @@ -1732,8 +1732,8 @@ static irq_guest_action_t *__pirq_guest_ BUG_ON(action->in_flight !=3D 0); =20 /* Disabling IRQ before releasing the desc_lock avoids an IRQ storm. = */ - desc->status |=3D IRQ_DISABLED; desc->handler->disable(desc); + desc->status |=3D IRQ_DISABLED; =20 /* * Mark any remaining pending EOIs as ready to flush. --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -123,6 +123,27 @@ static void msix_put_fixmap(struct arch_ spin_unlock(&msix->table_lock); } =20 +static bool_t memory_decoded(const struct pci_dev *dev) +{ + u8 bus, slot, func; + + if ( !dev->info.is_virtfn ) + { + bus =3D dev->bus; + slot =3D PCI_SLOT(dev->devfn); + func =3D PCI_FUNC(dev->devfn); + } + else + { + bus =3D dev->info.physfn.bus; + slot =3D PCI_SLOT(dev->info.physfn.devfn); + func =3D PCI_FUNC(dev->info.physfn.devfn); + } + + return !!(pci_conf_read16(dev->seg, bus, slot, func, PCI_COMMAND) & + PCI_COMMAND_MEMORY); +} + /* * MSI message composition */ @@ -166,7 +187,7 @@ void msi_compose_msg(unsigned vector, co } } =20 -static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) +static bool_t read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) { switch ( entry->msi_attrib.type ) { @@ -201,6 +222,8 @@ static void read_msi_msg(struct msi_desc { void __iomem *base =3D entry->mask_base; =20 + if ( unlikely(!memory_decoded(entry->dev)) ) + 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)= ; msg->data =3D readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); @@ -212,6 +235,8 @@ static void read_msi_msg(struct msi_desc =20 if ( iommu_intremap ) iommu_read_msi_from_ire(entry, msg); + + return 1; } =20 static int write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) @@ -262,6 +287,8 @@ static int write_msi_msg(struct msi_desc { void __iomem *base =3D entry->mask_base; =20 + if ( unlikely(!memory_decoded(entry->dev)) ) + return -ENXIO; writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); writel(msg->address_hi, @@ -289,7 +316,8 @@ void set_msi_affinity(struct irq_desc *d ASSERT(spin_is_locked(&desc->lock)); =20 memset(&msg, 0, sizeof(msg)); - read_msi_msg(msi_desc, &msg); + if ( !read_msi_msg(msi_desc, &msg) ) + return; =20 msg.data &=3D ~MSI_DATA_VECTOR_MASK; msg.data |=3D MSI_DATA_VECTOR(desc->arch.vector); @@ -349,23 +377,27 @@ int msi_maskable_irq(const struct msi_de || entry->msi_attrib.maskbit; } =20 -static void msi_set_mask_bit(struct irq_desc *desc, bool_t host, bool_t = guest) +static bool_t msi_set_mask_bit(struct irq_desc *desc, bool_t host, bool_t = guest) { struct msi_desc *entry =3D desc->msi_desc; + struct pci_dev *pdev; + u16 seg; + u8 bus, slot, func; bool_t flag =3D host || guest; =20 ASSERT(spin_is_locked(&desc->lock)); BUG_ON(!entry || !entry->dev); + pdev =3D entry->dev; + seg =3D pdev->seg; + bus =3D pdev->bus; + slot =3D PCI_SLOT(pdev->devfn); + func =3D PCI_FUNC(pdev->devfn); switch ( entry->msi_attrib.type ) { case PCI_CAP_ID_MSI: if ( entry->msi_attrib.maskbit ) { u32 mask_bits; - u16 seg =3D entry->dev->seg; - u8 bus =3D entry->dev->bus; - u8 slot =3D PCI_SLOT(entry->dev->devfn); - u8 func =3D PCI_FUNC(entry->dev->devfn); =20 mask_bits =3D pci_conf_read32(seg, bus, slot, func, entry->msi= .mpos); mask_bits &=3D ~((u32)1 << entry->msi_attrib.entry_nr); @@ -374,25 +406,54 @@ static void msi_set_mask_bit(struct irq_ } break; case PCI_CAP_ID_MSIX: - { - int offset =3D PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; - writel(flag, entry->mask_base + offset); - readl(entry->mask_base + offset); - break; - } + 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 ( flag ) + { + u16 control; + domid_t domid =3D pdev->domain->domain_id; + + 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); + 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", + desc->irq, domid, pdev->seg, pdev->bus, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + } + break; + } + /* fall through */ default: - BUG(); - break; + return 0; } entry->msi_attrib.host_masked =3D host; entry->msi_attrib.guest_masked =3D guest; + + return 1; } =20 static int msi_get_mask_bit(const struct msi_desc *entry) { - switch (entry->msi_attrib.type) { + if ( !entry->dev ) + return -1; + + switch ( entry->msi_attrib.type ) + { case PCI_CAP_ID_MSI: - if (!entry->dev || !entry->msi_attrib.maskbit) + if ( !entry->msi_attrib.maskbit ) break; return (pci_conf_read32(entry->dev->seg, entry->dev->bus, PCI_SLOT(entry->dev->devfn), @@ -400,6 +461,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)) ) + break; return readl(entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET)= & 1; } return -1; @@ -407,12 +470,16 @@ static int msi_get_mask_bit(const struct =20 void mask_msi_irq(struct irq_desc *desc) { - msi_set_mask_bit(desc, 1, desc->msi_desc->msi_attrib.guest_masked); + if ( unlikely(!msi_set_mask_bit(desc, 1, + desc->msi_desc->msi_attrib.guest_maske= d)) ) + BUG_ON(!(desc->status & IRQ_DISABLED)); } =20 void unmask_msi_irq(struct irq_desc *desc) { - msi_set_mask_bit(desc, 0, desc->msi_desc->msi_attrib.guest_masked); + if ( unlikely(!msi_set_mask_bit(desc, 0, + desc->msi_desc->msi_attrib.guest_maske= d)) ) + WARN(); } =20 void guest_mask_msi_irq(struct irq_desc *desc, bool_t mask) @@ -425,13 +492,15 @@ static unsigned int startup_msi_irq(stru bool_t guest_masked =3D (desc->status & IRQ_GUEST) && is_hvm_domain(desc->msi_desc->dev->domain); =20 - msi_set_mask_bit(desc, 0, guest_masked); + if ( unlikely(!msi_set_mask_bit(desc, 0, guest_masked)) ) + WARN(); return 0; } =20 static void shutdown_msi_irq(struct irq_desc *desc) { - msi_set_mask_bit(desc, 1, 1); + if ( unlikely(!msi_set_mask_bit(desc, 1, 1)) ) + BUG_ON(!(desc->status & IRQ_DISABLED)); } =20 void ack_nonmaskable_msi_irq(struct irq_desc *desc) @@ -743,6 +812,9 @@ static int msix_capability_init(struct p 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 */ =20 + if ( unlikely(!memory_decoded(dev)) ) + return -ENXIO; + if ( desc ) { entry =3D alloc_msi_entry(1); @@ -882,7 +954,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_conf_write16(seg, bus, slot, func, msix_control_reg(pos), + control & ~PCI_MSIX_FLAGS_MASKALL); =20 return 0; } @@ -1027,8 +1100,16 @@ static void __pci_disable_msix(struct ms =20 BUG_ON(list_empty(&dev->msi_list)); =20 - writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); - + if ( likely(memory_decoded(dev)) ) + writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); + else if ( !(control & PCI_MSIX_FLAGS_MASKALL) ) + { + printk(XENLOG_WARNING + "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; + } pci_conf_write16(seg, bus, slot, func, msix_control_reg(pos), = control); =20 _pci_cleanup_msix(dev->msix); @@ -1204,15 +1285,24 @@ int pci_restore_msi_state(struct pci_dev nr =3D entry->msi.nvec; } else if ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX ) + { msix_set_enable(pdev, 0); + if ( unlikely(!memory_decoded(pdev)) ) + { + spin_unlock_irqrestore(&desc->lock, flags); + return -ENXIO; + } + } =20 msg =3D entry->msg; write_msi_msg(entry, &msg); =20 for ( i =3D 0; ; ) { - msi_set_mask_bit(desc, entry[i].msi_attrib.host_masked, - entry[i].msi_attrib.guest_masked); + if ( unlikely(!msi_set_mask_bit(desc, + entry[i].msi_attrib.host_maske= d, + entry[i].msi_attrib.guest_mask= ed)) ) + BUG(); =20 if ( !--nr ) break; --=__PartE9DD397C.1__= Content-Type: text/plain; name="x86-MSI-X-teardown.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-MSI-X-teardown.patch" x86/MSI-X: be more careful during teardown=0A=0AWhen a device gets = detached from a guest, pciback will clear its=0Acommand register, thus = disabling both memory and I/O decoding. The=0Adisabled memory decoding, = however, has an effect on the MSI-X table=0Aaccesses the hypervisor does: = These won't have the intended effect=0Aanymore. Even worse, for PCIe = devices (but not SR-IOV virtual=0Afunctions) such accesses may (will?) be = treated as Unsupported=0ARequests, causing respective errors to be = surfaced, potentially in the=0Aform of NMIs that may be fatal to the = hypervisor or Dom0 is different=0Aways. Hence rather than carrying out = these accesses, we should avoid=0Athem where we can, and use alternative = (e.g. PCI config space based)=0Amechanisms to achieve at least the same = effect.=0A=0AAt this time it continues to be unclear whether this is = fixing an=0Aactual bug or is rather just working around bogus (but = apparently=0Acommon) system behavior.=0A=0ASigned-off-by: Jan Beulich = =0AReviewed-by: Andrew Cooper =0A---=0ABackporting note (largely to myself):=0A Depends on (not yet = backported to 4.4 and earlier) commit 061eebe0e=0A "x86/MSI: drop = workaround for insecure Dom0 kernels" (due to re-use=0A of struct = arch_msix's warned field).=0A=0A--- a/xen/arch/x86/irq.c=0A+++ b/xen/arch/x= 86/irq.c=0A@@ -217,9 +217,9 @@ void destroy_irq(unsigned int irq)=0A = }=0A =0A spin_lock_irqsave(&desc->lock, flags);=0A- desc->status = |=3D IRQ_DISABLED;=0A desc->status &=3D ~IRQ_GUEST;=0A desc->handl= er->shutdown(desc);=0A+ desc->status |=3D IRQ_DISABLED;=0A action = =3D desc->action;=0A desc->action =3D NULL;=0A desc->msi_desc =3D = NULL;=0A@@ -995,8 +995,8 @@ void __init release_irq(unsigned int irq=0A = spin_lock_irqsave(&desc->lock,flags);=0A action =3D desc->action;=0A = desc->action =3D NULL;=0A- desc->status |=3D IRQ_DISABLED;=0A = desc->handler->shutdown(desc);=0A+ desc->status |=3D IRQ_DISABLED;=0A = spin_unlock_irqrestore(&desc->lock,flags);=0A =0A /* Wait to make = sure it's not being used on another CPU */=0A@@ -1732,8 +1732,8 @@ static = irq_guest_action_t *__pirq_guest_=0A BUG_ON(action->in_flight !=3D = 0);=0A =0A /* Disabling IRQ before releasing the desc_lock avoids an = IRQ storm. */=0A- desc->status |=3D IRQ_DISABLED;=0A desc->handler->= disable(desc);=0A+ desc->status |=3D IRQ_DISABLED;=0A =0A /*=0A = * Mark any remaining pending EOIs as ready to flush.=0A--- a/xen/arch/x86/= msi.c=0A+++ b/xen/arch/x86/msi.c=0A@@ -123,6 +123,27 @@ static void = msix_put_fixmap(struct arch_=0A spin_unlock(&msix->table_lock);=0A = }=0A =0A+static bool_t memory_decoded(const struct pci_dev *dev)=0A+{=0A+ = u8 bus, slot, func;=0A+=0A+ if ( !dev->info.is_virtfn )=0A+ {=0A+ = bus =3D dev->bus;=0A+ slot =3D PCI_SLOT(dev->devfn);=0A+ = func =3D PCI_FUNC(dev->devfn);=0A+ }=0A+ else=0A+ {=0A+ = bus =3D dev->info.physfn.bus;=0A+ slot =3D PCI_SLOT(dev->info.physfn= .devfn);=0A+ func =3D PCI_FUNC(dev->info.physfn.devfn);=0A+ = }=0A+=0A+ return !!(pci_conf_read16(dev->seg, bus, slot, func, = PCI_COMMAND) &=0A+ PCI_COMMAND_MEMORY);=0A+}=0A+=0A /*=0A * = MSI message composition=0A */=0A@@ -166,7 +187,7 @@ void msi_compose_msg(u= nsigned vector, co=0A }=0A }=0A =0A-static void read_msi_msg(struct = msi_desc *entry, struct msi_msg *msg)=0A+static bool_t read_msi_msg(struct = msi_desc *entry, struct msi_msg *msg)=0A {=0A switch ( entry->msi_attri= b.type )=0A {=0A@@ -201,6 +222,8 @@ static void read_msi_msg(struct = msi_desc=0A {=0A void __iomem *base =3D entry->mask_base;=0A = =0A+ if ( unlikely(!memory_decoded(entry->dev)) )=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_UP= PER_ADDR_OFFSET);=0A msg->data =3D readl(base + PCI_MSIX_ENTRY_DATA= _OFFSET);=0A@@ -212,6 +235,8 @@ static void read_msi_msg(struct msi_desc=0A= =0A if ( iommu_intremap )=0A iommu_read_msi_from_ire(entry, = msg);=0A+=0A+ return 1;=0A }=0A =0A static int write_msi_msg(struct = msi_desc *entry, struct msi_msg *msg)=0A@@ -262,6 +287,8 @@ static int = write_msi_msg(struct msi_desc=0A {=0A void __iomem *base =3D = entry->mask_base;=0A =0A+ if ( unlikely(!memory_decoded(entry->dev))= )=0A+ return -ENXIO;=0A writel(msg->address_lo,=0A = base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);=0A writel(msg-= >address_hi,=0A@@ -289,7 +316,8 @@ void set_msi_affinity(struct irq_desc = *d=0A ASSERT(spin_is_locked(&desc->lock));=0A =0A memset(&msg, 0, = sizeof(msg));=0A- read_msi_msg(msi_desc, &msg);=0A+ if ( !read_msi_ms= g(msi_desc, &msg) )=0A+ return;=0A =0A msg.data &=3D ~MSI_DATA_V= ECTOR_MASK;=0A msg.data |=3D MSI_DATA_VECTOR(desc->arch.vector);=0A@@ = -349,23 +377,27 @@ int msi_maskable_irq(const struct msi_de=0A = || entry->msi_attrib.maskbit;=0A }=0A =0A-static void msi_set_mask_bit(stru= ct irq_desc *desc, bool_t host, bool_t guest)=0A+static bool_t msi_set_mask= _bit(struct irq_desc *desc, bool_t host, bool_t guest)=0A {=0A struct = msi_desc *entry =3D desc->msi_desc;=0A+ struct pci_dev *pdev;=0A+ = u16 seg;=0A+ u8 bus, slot, func;=0A bool_t flag =3D host || = guest;=0A =0A ASSERT(spin_is_locked(&desc->lock));=0A BUG_ON(!entry= || !entry->dev);=0A+ pdev =3D entry->dev;=0A+ seg =3D pdev->seg;=0A+= bus =3D pdev->bus;=0A+ slot =3D PCI_SLOT(pdev->devfn);=0A+ func = =3D PCI_FUNC(pdev->devfn);=0A switch ( entry->msi_attrib.type )=0A = {=0A case PCI_CAP_ID_MSI:=0A if ( entry->msi_attrib.maskbit = )=0A {=0A u32 mask_bits;=0A- u16 seg =3D = entry->dev->seg;=0A- u8 bus =3D entry->dev->bus;=0A- = u8 slot =3D PCI_SLOT(entry->dev->devfn);=0A- u8 func =3D = PCI_FUNC(entry->dev->devfn);=0A =0A mask_bits =3D pci_conf_read= 32(seg, bus, slot, func, entry->msi.mpos);=0A mask_bits &=3D = ~((u32)1 << entry->msi_attrib.entry_nr);=0A@@ -374,25 +406,54 @@ static = void msi_set_mask_bit(struct irq_=0A }=0A break;=0A = case PCI_CAP_ID_MSIX:=0A- {=0A- int offset =3D PCI_MSIX_ENTRY_VEC= TOR_CTRL_OFFSET;=0A- writel(flag, entry->mask_base + offset);=0A- = readl(entry->mask_base + offset);=0A- break;=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+ }=0A+ if ( flag )=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.pos),=0A+ = control | PCI_MSIX_FLAGS_MASKALL);=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+ = desc->irq, domid, pdev->seg, pdev->bus,=0A+ = PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));=0A+ = }=0A+ break;=0A+ }=0A+ /* fall through */=0A = default:=0A- BUG();=0A- break;=0A+ return 0;=0A = }=0A entry->msi_attrib.host_masked =3D host;=0A entry->msi_attrib.g= uest_masked =3D guest;=0A+=0A+ return 1;=0A }=0A =0A static int = msi_get_mask_bit(const struct msi_desc *entry)=0A {=0A- switch = (entry->msi_attrib.type) {=0A+ if ( !entry->dev )=0A+ return = -1;=0A+=0A+ switch ( entry->msi_attrib.type )=0A+ {=0A case = PCI_CAP_ID_MSI:=0A- if (!entry->dev || !entry->msi_attrib.maskbit)= =0A+ if ( !entry->msi_attrib.maskbit )=0A break;=0A = return (pci_conf_read32(entry->dev->seg, entry->dev->bus,=0A = PCI_SLOT(entry->dev->devfn),=0A@@ -400,6 +461,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(en= try->dev)) )=0A+ break;=0A return readl(entry->mask_base= + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) & 1;=0A }=0A return -1;=0A@@ = -407,12 +470,16 @@ static int msi_get_mask_bit(const struct=0A =0A void = mask_msi_irq(struct irq_desc *desc)=0A {=0A- msi_set_mask_bit(desc, 1, = desc->msi_desc->msi_attrib.guest_masked);=0A+ if ( unlikely(!msi_set_mas= k_bit(desc, 1,=0A+ desc->msi_desc->msi_a= ttrib.guest_masked)) )=0A+ BUG_ON(!(desc->status & IRQ_DISABLED));= =0A }=0A =0A void unmask_msi_irq(struct irq_desc *desc)=0A {=0A- = msi_set_mask_bit(desc, 0, desc->msi_desc->msi_attrib.guest_masked);=0A+ = if ( unlikely(!msi_set_mask_bit(desc, 0,=0A+ = desc->msi_desc->msi_attrib.guest_masked)) )=0A+ WARN();=0A = }=0A =0A void guest_mask_msi_irq(struct irq_desc *desc, bool_t mask)=0A@@ = -425,13 +492,15 @@ static unsigned int startup_msi_irq(stru=0A bool_t = guest_masked =3D (desc->status & IRQ_GUEST) &&=0A = is_hvm_domain(desc->msi_desc->dev->domain);=0A =0A- msi_set_mask_bit(de= sc, 0, guest_masked);=0A+ if ( unlikely(!msi_set_mask_bit(desc, 0, = guest_masked)) )=0A+ WARN();=0A return 0;=0A }=0A =0A static = void shutdown_msi_irq(struct irq_desc *desc)=0A {=0A- msi_set_mask_bit(d= esc, 1, 1);=0A+ if ( unlikely(!msi_set_mask_bit(desc, 1, 1)) )=0A+ = BUG_ON(!(desc->status & IRQ_DISABLED));=0A }=0A =0A void ack_nonmaskable_= msi_irq(struct irq_desc *desc)=0A@@ -743,6 +812,9 @@ static int msix_capabi= lity_init(struct p=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+ if ( unlikely(!memory_decoded= (dev)) )=0A+ return -ENXIO;=0A+=0A if ( desc )=0A {=0A = entry =3D alloc_msi_entry(1);=0A@@ -882,7 +954,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), control);=0A+ pci_conf_write16(seg, bus, = slot, func, msix_control_reg(pos),=0A+ control & = ~PCI_MSIX_FLAGS_MASKALL);=0A =0A return 0;=0A }=0A@@ -1027,8 +1100,16 = @@ static void __pci_disable_msix(struct ms=0A =0A BUG_ON(list_empty(&d= ev->msi_list));=0A =0A- writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECT= OR_CTRL_OFFSET);=0A-=0A+ if ( likely(memory_decoded(dev)) )=0A+ = writel(1, entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);=0A+ = else if ( !(control & PCI_MSIX_FLAGS_MASKALL) )=0A+ {=0A+ = printk(XENLOG_WARNING=0A+ "cannot disable IRQ %d: masking = MSI-X on %04x:%02x:%02x.%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+ }=0A pci_conf_writ= e16(seg, bus, slot, func, msix_control_reg(pos), control);=0A =0A = _pci_cleanup_msix(dev->msix);=0A@@ -1204,15 +1285,24 @@ int pci_restore_msi= _state(struct pci_dev=0A nr =3D entry->msi.nvec;=0A = }=0A else if ( entry->msi_attrib.type =3D=3D PCI_CAP_ID_MSIX )=0A+ = {=0A msix_set_enable(pdev, 0);=0A+ if ( = unlikely(!memory_decoded(pdev)) )=0A+ {=0A+ = spin_unlock_irqrestore(&desc->lock, flags);=0A+ return = -ENXIO;=0A+ }=0A+ }=0A =0A msg =3D entry->msg;=0A= write_msi_msg(entry, &msg);=0A =0A for ( i =3D 0; ; )=0A = {=0A- msi_set_mask_bit(desc, entry[i].msi_attrib.host_mas= ked,=0A- entry[i].msi_attrib.guest_masked);=0A+= if ( unlikely(!msi_set_mask_bit(desc,=0A+ = entry[i].msi_attrib.host_masked,=0A+ = entry[i].msi_attrib.guest_masked)) )=0A+ = BUG();=0A =0A if ( !--nr )=0A break;=0A --=__PartE9DD397C.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 --=__PartE9DD397C.1__=--