|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] x86/physdev: Call xsm_unmap_domain_irq earlier
Pull the XSM check up out of unmap_domain_pirq into physdev_map_pirq.
xsm_unmap_domain_irq was seen denying unmap_domain_pirq when called from
complete_domain_destroy as an RCU callback. The source context was an
unexpected, random domain. Since this is a xen-internal operation,
going through the XSM hook is inapproriate.
Move the XSM hook up into physdev_unmap_pirq, which is the
guest-accessible path. This requires moving some of the sanity check
upwards as well since the hook needs the additional data to make its
decision. Since complete_domain_destroy still calls unmap_domain_pirq,
replace the moved runtime checking with assert. Only valid pirqs should
make their way into unmap_domain_pirq from complete_domain_destroy.
This is mostly code movement, but one style change is to pull `irq =
info->arch.irq` out of the if condition.
Label done is now unused and removed.
Signed-off-by: Jason Andryuk <jandryuk@xxxxxxxxx>
---
unmap_domain_pirq is also called in vioapic_hwdom_map_gsi and
vpci_msi_disable. vioapic_hwdom_map_gsi is a cleanup path after going
through map_domain_pirq, and I don't think the vpci code is directly
guest-accessible. So I think those are okay, but I not familiar with
that code. Hence, I am highlighting it.
xen/arch/x86/irq.c | 31 +++++++-----------------------
xen/arch/x86/physdev.c | 43 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 49 insertions(+), 25 deletions(-)
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 285ac399fb..ddd3194fba 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2310,41 +2310,25 @@ int unmap_domain_pirq(struct domain *d, int pirq)
struct pirq *info;
struct msi_desc *msi_desc = NULL;
- if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
- return -EINVAL;
-
+ ASSERT(pirq >= 0);
+ ASSERT(pirq < d->nr_pirqs);
ASSERT(pcidevs_locked());
ASSERT(spin_is_locked(&d->event_lock));
info = pirq_info(d, pirq);
- if ( !info || (irq = info->arch.irq) <= 0 )
- {
- dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n",
- d->domain_id, pirq);
- ret = -EINVAL;
- goto done;
- }
+ ASSERT(info);
+
+ irq = info->arch.irq;
+ ASSERT(irq > 0);
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;
- }
+ ASSERT(msi_desc->msi_attrib.entry_nr == 0);
nr = msi_desc->msi.nvec;
}
- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
- msi_desc ? msi_desc->dev : NULL);
- if ( ret )
- goto done;
-
forced_unbind = pirq_guest_force_unbind(d, info);
if ( forced_unbind )
dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n",
@@ -2405,7 +2389,6 @@ int unmap_domain_pirq(struct domain *d, int pirq)
if (msi_desc)
msi_free_irq(msi_desc);
- done:
return ret;
}
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index 2ddcf44f33..a5ed257dca 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -140,8 +140,11 @@ int physdev_map_pirq(domid_t domid, int type, int *index,
int *pirq_p,
int physdev_unmap_pirq(domid_t domid, int pirq)
{
+ struct msi_desc *msi_desc;
+ struct irq_desc *desc;
+ struct pirq *info;
struct domain *d;
- int ret = 0;
+ int irq, ret = 0;
d = rcu_lock_domain_by_any_id(domid);
if ( d == NULL )
@@ -162,9 +165,47 @@ int physdev_unmap_pirq(domid_t domid, int pirq)
goto free_domain;
}
+ if ( (pirq < 0) || (pirq >= d->nr_pirqs) ) {
+ ret = -EINVAL;
+ goto free_domain;
+ }
+
pcidevs_lock();
spin_lock(&d->event_lock);
+
+ info = pirq_info(d, pirq);
+ irq = info ? info->arch.irq : 0;
+ if ( !info || irq <= 0 )
+ {
+ dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n",
+ d->domain_id, pirq);
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+ 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 unlock;
+ }
+ }
+
+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
+ msi_desc ? msi_desc->dev : NULL);
+ if ( ret )
+ goto unlock;
+
ret = unmap_domain_pirq(d, pirq);
+
+ unlock:
+
spin_unlock(&d->event_lock);
pcidevs_unlock();
--
2.35.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |