|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v5 05/11] x86/passthrough: Extract PT_IRQ_TYPE_MSI body into pt_irq_bind_msi()
Move the PT_IRQ_TYPE_MSI case of pt_irq_create_bind() into a new static
helper pt_irq_bind_msi(d, machine_irq, gvec, gflags, gtable, unmasked).
The helper calls pt_irq_dpci_setup() itself, so pt_irq_create_bind() now
invokes the setup helper separately in the PCI / MSI_TRANSLATE case and
the 'default' case no longer needs to drop d->event_lock.
To keep this step "just" a code move, the extracted body is left at its
original (switch/case) indentation inside a compound block. The next
commit re-indents it. References to pt_irq_bind->u.msi.* are replaced by
the corresponding parameters, and the two pt_irq_destroy_bind() error
paths build a local xen_domctl_bind_pt_irq instead. No functional
change.
Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
---
Changes in v5:
- New patch: this is the first half of v4's single "Extract
PT_IRQ_TYPE_MSI body" patch, now split into "extract as-is, keeping
the switch/case indentation inside a bare block" plus a re-indent
(next patch), so each step reviews cleanly.
- machine_irq / gflags parameters are now unsigned int.
- The redundant nr_pirqs bound check inside the helper was dropped.
- The "!!" on the unmasked argument was removed.
- pt_irq_dpci_setup() is now called per-case.
- The "default" case no longer double-unlocks d->event_lock.
- The two pt_irq_destroy_bind() error paths build a local
xen_domctl_bind_pt_irq.
- Comment capitalisation fixed.
Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
---
xen/drivers/passthrough/x86/hvm.c | 81 +++++++++++++++++++++----------
1 file changed, 55 insertions(+), 26 deletions(-)
diff --git a/xen/drivers/passthrough/x86/hvm.c
b/xen/drivers/passthrough/x86/hvm.c
index 7fcd3cc046..ed368a7fdb 100644
--- a/xen/drivers/passthrough/x86/hvm.c
+++ b/xen/drivers/passthrough/x86/hvm.c
@@ -287,40 +287,33 @@ static int pt_irq_dpci_setup(struct domain *d, unsigned
int pirq,
return 0;
}
-int pt_irq_create_bind(
- struct domain *d, const struct xen_domctl_bind_pt_irq *pt_irq_bind)
+static int pt_irq_bind_msi(struct domain *d, unsigned int machine_irq,
+ uint8_t gvec, unsigned int gflags, uint64_t gtable,
+ bool unmasked)
{
struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
struct pirq *info;
- int rc, pirq = pt_irq_bind->machine_irq;
-
- if ( pirq < 0 || pirq >= d->nr_pirqs )
- return -EINVAL;
+ int rc;
- rc = pt_irq_dpci_setup(d, pirq, &hvm_irq_dpci, &pirq_dpci, &info);
+ rc = pt_irq_dpci_setup(d, machine_irq, &hvm_irq_dpci, &pirq_dpci, &info);
if ( rc )
return rc;
- switch ( pt_irq_bind->irq_type )
- {
- case PT_IRQ_TYPE_MSI:
{
uint8_t dest, delivery_mode;
bool dest_mode;
int dest_vcpu_id;
const struct vcpu *vcpu;
- uint32_t gflags = pt_irq_bind->u.msi.gflags &
- ~XEN_DOMCTL_VMSI_X86_UNMASKED;
if ( !(pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
{
pirq_dpci->flags = HVM_IRQ_DPCI_MAPPED | HVM_IRQ_DPCI_MACH_MSI |
HVM_IRQ_DPCI_GUEST_MSI;
- pirq_dpci->gmsi.gvec = pt_irq_bind->u.msi.gvec;
+ pirq_dpci->gmsi.gvec = gvec;
pirq_dpci->gmsi.gflags = gflags;
/*
- * 'pt_irq_create_bind' can be called after 'pt_irq_destroy_bind'.
+ * 'pt_irq_bind_msi' can be called after 'pt_irq_destroy_bind'.
* The 'pirq_cleanup_check' which would free the structure is only
* called if the event channel for the PIRQ is active. However
* OS-es that use event channels usually bind PIRQs to eventds
@@ -328,14 +321,14 @@ int pt_irq_create_bind(
* result that we re-use the 'dpci' structure. This can be
* reproduced with unloading and loading the driver for a device.
*
- * As such on every 'pt_irq_create_bind' call we MUST set it.
+ * As such on every 'pt_irq_bind_msi' call we MUST set it.
*/
pirq_dpci->dom = d;
- /* bind after hvm_irq_dpci is setup to avoid race with irq
handler*/
+ /* Bind after hvm_irq_dpci is setup to avoid race with irq
handler. */
rc = pirq_guest_bind(d->vcpu[0], info, 0);
- if ( rc == 0 && pt_irq_bind->u.msi.gtable )
+ if ( rc == 0 && gtable )
{
- rc = msixtbl_pt_register(d, info, pt_irq_bind->u.msi.gtable);
+ rc = msixtbl_pt_register(d, info, gtable);
if ( unlikely(rc) )
{
pirq_guest_unbind(d, info);
@@ -371,13 +364,13 @@ int pt_irq_create_bind(
}
/* If pirq is already mapped as vmsi, update guest data/addr. */
- if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
+ if ( pirq_dpci->gmsi.gvec != gvec ||
pirq_dpci->gmsi.gflags != gflags )
{
/* Directly clear pending EOIs before enabling new MSI info. */
pirq_guest_eoi(info);
- pirq_dpci->gmsi.gvec = pt_irq_bind->u.msi.gvec;
+ pirq_dpci->gmsi.gvec = gvec;
pirq_dpci->gmsi.gflags = gflags;
}
}
@@ -408,23 +401,31 @@ int pt_irq_create_bind(
/* Use interrupt posting if it is supported. */
if ( iommu_intpost )
{
- rc = hvm_pi_update_irte(vcpu, info, pirq_dpci->gmsi.gvec);
+ struct xen_domctl_bind_pt_irq pt_irq_bind = {
+ .machine_irq = machine_irq,
+ .irq_type = PT_IRQ_TYPE_MSI,
+ };
+ rc = hvm_pi_update_irte(vcpu, info, pirq_dpci->gmsi.gvec);
if ( rc )
{
- pt_irq_destroy_bind(d, pt_irq_bind);
+ pt_irq_destroy_bind(d, &pt_irq_bind);
return rc;
}
}
- if ( pt_irq_bind->u.msi.gflags & XEN_DOMCTL_VMSI_X86_UNMASKED )
+ if ( unmasked )
{
+ struct xen_domctl_bind_pt_irq pt_irq_bind = {
+ .machine_irq = machine_irq,
+ .irq_type = PT_IRQ_TYPE_MSI,
+ };
unsigned long flags;
struct irq_desc *desc = pirq_spin_lock_irq_desc(info, &flags);
if ( !desc )
{
- pt_irq_destroy_bind(d, pt_irq_bind);
+ pt_irq_destroy_bind(d, &pt_irq_bind);
return -EINVAL;
}
@@ -432,15 +433,44 @@ int pt_irq_create_bind(
spin_unlock_irqrestore(&desc->lock, flags);
}
- break;
+ return 0;
+ }
+}
+
+int pt_irq_create_bind(
+ struct domain *d, const struct xen_domctl_bind_pt_irq *pt_irq_bind)
+{
+ int pirq = pt_irq_bind->machine_irq;
+
+ if ( pirq < 0 || pirq >= d->nr_pirqs )
+ return -EINVAL;
+
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_MSI:
+ {
+ unsigned int gflags = pt_irq_bind->u.msi.gflags;
+
+ return pt_irq_bind_msi(d, pirq, pt_irq_bind->u.msi.gvec,
+ gflags & ~XEN_DOMCTL_VMSI_X86_UNMASKED,
+ pt_irq_bind->u.msi.gtable,
+ gflags & XEN_DOMCTL_VMSI_X86_UNMASKED);
}
case PT_IRQ_TYPE_PCI:
case PT_IRQ_TYPE_MSI_TRANSLATE:
{
+ struct hvm_irq_dpci *hvm_irq_dpci;
+ struct hvm_pirq_dpci *pirq_dpci;
+ struct pirq *info;
struct dev_intx_gsi_link *digl = NULL;
struct hvm_girq_dpci_mapping *girq = NULL;
unsigned int guest_gsi;
+ int rc;
+
+ rc = pt_irq_dpci_setup(d, pirq, &hvm_irq_dpci, &pirq_dpci, &info);
+ if ( rc )
+ return rc;
/*
* Mapping GSIs for the hardware domain is different than doing it for
@@ -589,7 +619,6 @@ int pt_irq_create_bind(
}
default:
- write_unlock(&d->event_lock);
return -EOPNOTSUPP;
}
--
2.53.0
--
Julian Vetter | Vates Hypervisor & Kernel Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |