* [PATCH 0/3] XSA-96 follow-ups
@ 2014-06-03 13:52 Jan Beulich
2014-06-03 13:58 ` [PATCH 1/3] x86/HVM: properly propagate errors from HVMOP_inject_msi Jan Beulich
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Jan Beulich @ 2014-06-03 13:52 UTC (permalink / raw)
To: xen-devel; +Cc: Keir Fraser
1: x86/HVM: properly propagate errors from HVMOP_inject_msi
2: x86/HVM: make vmsi_deliver() return proper error values
3: pt-irq fixes and improvements
Signed-off-by: Jan Beulich <jbeulich@suse.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/3] x86/HVM: properly propagate errors from HVMOP_inject_msi
2014-06-03 13:52 [PATCH 0/3] XSA-96 follow-ups Jan Beulich
@ 2014-06-03 13:58 ` Jan Beulich
2014-06-03 14:05 ` Andrew Cooper
2014-06-03 13:59 ` [PATCH 2/3] x86/HVM: make vmsi_deliver() return proper error values Jan Beulich
2014-06-03 14:00 ` [PATCH 3/3] pt-irq fixes and improvements Jan Beulich
2 siblings, 1 reply; 12+ messages in thread
From: Jan Beulich @ 2014-06-03 13:58 UTC (permalink / raw)
To: xen-devel; +Cc: Keir Fraser, Stefano Stabellini
[-- Attachment #1: Type: text/plain, Size: 2677 bytes --]
There are a number of ways this operation can go wrong, all of which
got ignored so far.
In the context of this I wonder whether map_domain_emuirq_pirq()
returning 0 in the "already mapped" case is really intended to be that
way (this is why the subsequent NULL check here can't be an ASSERT()).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -5096,7 +5096,7 @@ static int hvmop_inject_msi(
if ( rc )
goto out;
- hvm_inject_msi(d, op.addr, op.data);
+ rc = hvm_inject_msi(d, op.addr, op.data);
out:
rcu_unlock_domain(d);
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -270,7 +270,7 @@ void hvm_set_pci_link_route(struct domai
d->domain_id, link, old_isa_irq, isa_irq);
}
-void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
+int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
{
uint32_t tmp = (uint32_t) addr;
uint8_t dest = (tmp & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
@@ -292,20 +292,28 @@ void hvm_inject_msi(struct domain *d, ui
/* if it is the first time, allocate the pirq */
if ( !info || info->arch.hvm.emuirq == IRQ_UNBOUND )
{
+ int rc;
+
spin_lock(&d->event_lock);
- map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
+ rc = map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
spin_unlock(&d->event_lock);
+ if ( rc )
+ return rc;
info = pirq_info(d, pirq);
if ( !info )
- return;
- } else if (info->arch.hvm.emuirq != IRQ_MSI_EMU)
- return;
+ return -EBUSY;
+ }
+ else if ( info->arch.hvm.emuirq != IRQ_MSI_EMU )
+ return -EINVAL;
send_guest_pirq(d, info);
- return;
+ return 0;
}
+ return -ERANGE;
}
vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
+
+ return 0;
}
void hvm_set_callback_via(struct domain *d, uint64_t via)
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -123,7 +123,7 @@ void hvm_isa_irq_deassert(
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
-void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
+int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
[-- Attachment #2: x86-HVM-inject-MSI-retval.patch --]
[-- Type: text/plain, Size: 2731 bytes --]
x86/HVM: properly propagate errors from HVMOP_inject_msi
There are a number of ways this operation can go wrong, all of which
got ignored so far.
In the context of this I wonder whether map_domain_emuirq_pirq()
returning 0 in the "already mapped" case is really intended to be that
way (this is why the subsequent NULL check here can't be an ASSERT()).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -5096,7 +5096,7 @@ static int hvmop_inject_msi(
if ( rc )
goto out;
- hvm_inject_msi(d, op.addr, op.data);
+ rc = hvm_inject_msi(d, op.addr, op.data);
out:
rcu_unlock_domain(d);
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -270,7 +270,7 @@ void hvm_set_pci_link_route(struct domai
d->domain_id, link, old_isa_irq, isa_irq);
}
-void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
+int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
{
uint32_t tmp = (uint32_t) addr;
uint8_t dest = (tmp & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
@@ -292,20 +292,28 @@ void hvm_inject_msi(struct domain *d, ui
/* if it is the first time, allocate the pirq */
if ( !info || info->arch.hvm.emuirq == IRQ_UNBOUND )
{
+ int rc;
+
spin_lock(&d->event_lock);
- map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
+ rc = map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
spin_unlock(&d->event_lock);
+ if ( rc )
+ return rc;
info = pirq_info(d, pirq);
if ( !info )
- return;
- } else if (info->arch.hvm.emuirq != IRQ_MSI_EMU)
- return;
+ return -EBUSY;
+ }
+ else if ( info->arch.hvm.emuirq != IRQ_MSI_EMU )
+ return -EINVAL;
send_guest_pirq(d, info);
- return;
+ return 0;
}
+ return -ERANGE;
}
vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
+
+ return 0;
}
void hvm_set_callback_via(struct domain *d, uint64_t via)
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -123,7 +123,7 @@ void hvm_isa_irq_deassert(
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
-void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
+int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/3] x86/HVM: make vmsi_deliver() return proper error values
2014-06-03 13:52 [PATCH 0/3] XSA-96 follow-ups Jan Beulich
2014-06-03 13:58 ` [PATCH 1/3] x86/HVM: properly propagate errors from HVMOP_inject_msi Jan Beulich
@ 2014-06-03 13:59 ` Jan Beulich
2014-06-03 14:13 ` Andrew Cooper
2014-06-03 14:00 ` [PATCH 3/3] pt-irq fixes and improvements Jan Beulich
2 siblings, 1 reply; 12+ messages in thread
From: Jan Beulich @ 2014-06-03 13:59 UTC (permalink / raw)
To: xen-devel; +Cc: Keir Fraser
[-- Attachment #1: Type: text/plain, Size: 3477 bytes --]
... and propagate this from hvm_inject_msi(). In the course of this I
spotted further room for cleanup:
- vmsi_inj_irq()'s struct domain * parameter was unused
- vmsi_deliver() pointlessly passed on dest_ExtINT to vmsi_inj_irq()
(which that one validly refused to handle)
- vmsi_inj_irq()'s sole caller guarantees a proper delivery mode (i.e.
rather than printing an obscure message we can just BUG())
- some formatting and log message quirks
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -311,9 +311,7 @@ int hvm_inject_msi(struct domain *d, uin
return -ERANGE;
}
- vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
-
- return 0;
+ return vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
}
void hvm_set_callback_via(struct domain *d, uint64_t via)
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -43,14 +43,12 @@
#include <asm/io_apic.h>
static void vmsi_inj_irq(
- struct domain *d,
struct vlapic *target,
uint8_t vector,
uint8_t trig_mode,
uint8_t delivery_mode)
{
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vmsi_inj_irq "
- "irq %d trig %d delive mode %d\n",
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vmsi_inj_irq: vec %02x trig %d dm %d\n",
vector, trig_mode, delivery_mode);
switch ( delivery_mode )
@@ -60,8 +58,7 @@ static void vmsi_inj_irq(
vlapic_set_irq(target, vector, trig_mode);
break;
default:
- gdprintk(XENLOG_WARNING, "error delivery mode %d\n", delivery_mode);
- break;
+ BUG();
}
}
@@ -76,38 +73,31 @@ int vmsi_deliver(
switch ( delivery_mode )
{
case dest_LowestPrio:
- {
target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
if ( target != NULL )
- vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
- else
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
- "vector=%x delivery_mode=%x\n",
- vector, dest_LowestPrio);
- break;
- }
+ {
+ vmsi_inj_irq(target, vector, trig_mode, delivery_mode);
+ break;
+ }
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "null MSI round robin: vector=%02x\n",
+ vector);
+ return -ESRCH;
case dest_Fixed:
- case dest_ExtINT:
- {
for_each_vcpu ( d, v )
if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
0, dest, dest_mode) )
- vmsi_inj_irq(d, vcpu_vlapic(v),
- vector, trig_mode, delivery_mode);
+ vmsi_inj_irq(vcpu_vlapic(v), vector,
+ trig_mode, delivery_mode);
break;
- }
- case dest_SMI:
- case dest_NMI:
- case dest_INIT:
- case dest__reserved_2:
default:
- gdprintk(XENLOG_WARNING, "Unsupported delivery mode %d\n",
- delivery_mode);
- break;
+ printk(XENLOG_G_WARNING
+ "%pv: Unsupported MSI delivery mode %d for Dom%d\n",
+ current, delivery_mode, d->domain_id);
+ return -EINVAL;
}
- return 1;
+ return 0;
}
void vmsi_deliver_pirq(struct domain *d, const struct hvm_pirq_dpci *pirq_dpci)
[-- Attachment #2: x86-HVM-vmsi_deliver-retval.patch --]
[-- Type: text/plain, Size: 3530 bytes --]
x86/HVM: make vmsi_deliver() return proper error values
... and propagate this from hvm_inject_msi(). In the course of this I
spotted further room for cleanup:
- vmsi_inj_irq()'s struct domain * parameter was unused
- vmsi_deliver() pointlessly passed on dest_ExtINT to vmsi_inj_irq()
(which that one validly refused to handle)
- vmsi_inj_irq()'s sole caller guarantees a proper delivery mode (i.e.
rather than printing an obscure message we can just BUG())
- some formatting and log message quirks
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -311,9 +311,7 @@ int hvm_inject_msi(struct domain *d, uin
return -ERANGE;
}
- vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
-
- return 0;
+ return vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
}
void hvm_set_callback_via(struct domain *d, uint64_t via)
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -43,14 +43,12 @@
#include <asm/io_apic.h>
static void vmsi_inj_irq(
- struct domain *d,
struct vlapic *target,
uint8_t vector,
uint8_t trig_mode,
uint8_t delivery_mode)
{
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vmsi_inj_irq "
- "irq %d trig %d delive mode %d\n",
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vmsi_inj_irq: vec %02x trig %d dm %d\n",
vector, trig_mode, delivery_mode);
switch ( delivery_mode )
@@ -60,8 +58,7 @@ static void vmsi_inj_irq(
vlapic_set_irq(target, vector, trig_mode);
break;
default:
- gdprintk(XENLOG_WARNING, "error delivery mode %d\n", delivery_mode);
- break;
+ BUG();
}
}
@@ -76,38 +73,31 @@ int vmsi_deliver(
switch ( delivery_mode )
{
case dest_LowestPrio:
- {
target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
if ( target != NULL )
- vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
- else
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
- "vector=%x delivery_mode=%x\n",
- vector, dest_LowestPrio);
- break;
- }
+ {
+ vmsi_inj_irq(target, vector, trig_mode, delivery_mode);
+ break;
+ }
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "null MSI round robin: vector=%02x\n",
+ vector);
+ return -ESRCH;
case dest_Fixed:
- case dest_ExtINT:
- {
for_each_vcpu ( d, v )
if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
0, dest, dest_mode) )
- vmsi_inj_irq(d, vcpu_vlapic(v),
- vector, trig_mode, delivery_mode);
+ vmsi_inj_irq(vcpu_vlapic(v), vector,
+ trig_mode, delivery_mode);
break;
- }
- case dest_SMI:
- case dest_NMI:
- case dest_INIT:
- case dest__reserved_2:
default:
- gdprintk(XENLOG_WARNING, "Unsupported delivery mode %d\n",
- delivery_mode);
- break;
+ printk(XENLOG_G_WARNING
+ "%pv: Unsupported MSI delivery mode %d for Dom%d\n",
+ current, delivery_mode, d->domain_id);
+ return -EINVAL;
}
- return 1;
+ return 0;
}
void vmsi_deliver_pirq(struct domain *d, const struct hvm_pirq_dpci *pirq_dpci)
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 3/3] pt-irq fixes and improvements
2014-06-03 13:52 [PATCH 0/3] XSA-96 follow-ups Jan Beulich
2014-06-03 13:58 ` [PATCH 1/3] x86/HVM: properly propagate errors from HVMOP_inject_msi Jan Beulich
2014-06-03 13:59 ` [PATCH 2/3] x86/HVM: make vmsi_deliver() return proper error values Jan Beulich
@ 2014-06-03 14:00 ` Jan Beulich
2014-06-03 14:50 ` Andrew Cooper
2 siblings, 1 reply; 12+ messages in thread
From: Jan Beulich @ 2014-06-03 14:00 UTC (permalink / raw)
To: xen-devel
Cc: Kevin Tian, Keir Fraser, Ian Jackson, Ian Campbell,
Stefano Stabellini, Yang Z Zhang
[-- Attachment #1: Type: text/plain, Size: 17597 bytes --]
Tools side:
- don't silently ignore unrecognized PT_IRQ_TYPE_* values
- respect that the interface type contains a union, making the code at
once no longer depend on the hypervisor ignoring the bus field of the
PCI portion of the interface structure)
Hypervisor side:
- don't ignore the PCI bus number passed in
- don't store values (gsi, link) calculated from other stored values
- avoid calling xfree() with a spin lock held where easily possible
- have pt_irq_destroy_bind() respect the passed in type
- scope reduction and constification of various variables
- use switch instead of if/else-if chains
- formatting
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1702,15 +1702,20 @@ int xc_domain_bind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- if ( irq_type == PT_IRQ_TYPE_PCI ||
- irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
+ switch ( irq_type )
{
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
bind->u.pci.bus = bus;
bind->u.pci.device = device;
bind->u.pci.intx = intx;
- }
- else if ( irq_type == PT_IRQ_TYPE_ISA )
+ case PT_IRQ_TYPE_ISA:
bind->u.isa.isa_irq = isa_irq;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
rc = do_domctl(xch, &domctl);
return rc;
@@ -1737,10 +1742,21 @@ int xc_domain_unbind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- bind->u.pci.bus = bus;
- bind->u.pci.device = device;
- bind->u.pci.intx = intx;
- bind->u.isa.isa_irq = isa_irq;
+ switch ( irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ bind->u.pci.bus = bus;
+ bind->u.pci.device = device;
+ bind->u.pci.intx = intx;
+ break;
+ case PT_IRQ_TYPE_ISA:
+ bind->u.isa.isa_irq = isa_irq;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
rc = do_domctl(xch, &domctl);
return rc;
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq(
switch ( type )
{
case MAP_PIRQ_TYPE_GSI: {
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t machine_gsi = 0;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ unsigned int machine_gsi = 0;
if ( *index < 0 || *index >= NR_HVM_IRQS )
{
@@ -52,6 +51,8 @@ static int physdev_hvm_map_pirq(
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci )
{
+ const struct hvm_girq_dpci_mapping *girq;
+
BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS);
list_for_each_entry ( girq,
&hvm_irq_dpci->girq[*index],
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -51,11 +51,8 @@ static int pt_irq_guest_eoi(struct domai
static void pt_irq_time_out(void *data)
{
struct hvm_pirq_dpci *irq_map = data;
- unsigned int guest_gsi;
- struct hvm_irq_dpci *dpci = NULL;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t device, intx;
+ const struct hvm_irq_dpci *dpci;
+ const struct dev_intx_gsi_link *digl;
spin_lock(&irq_map->dom->event_lock);
@@ -63,16 +60,16 @@ static void pt_irq_time_out(void *data)
ASSERT(dpci);
list_for_each_entry ( digl, &irq_map->digl_list, list )
{
- guest_gsi = digl->gsi;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx);
+ const struct hvm_girq_dpci_mapping *girq;
+
list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
{
struct pirq *pirq = pirq_info(irq_map->dom, girq->machine_gsi);
pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
}
- device = digl->device;
- intx = digl->intx;
- hvm_pci_intx_deassert(irq_map->dom, device, intx);
+ hvm_pci_intx_deassert(irq_map->dom, digl->device, digl->intx);
}
pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL);
@@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp
int pt_irq_create_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
struct pirq *info;
- uint32_t guest_gsi;
- uint32_t device, intx, link;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
int rc, pirq = pt_irq_bind->machine_irq;
if ( pirq < 0 || pirq >= d->nr_pirqs )
@@ -136,7 +129,9 @@ int pt_irq_create_bind(
}
pirq_dpci = pirq_dpci(info);
- if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_MSI:
{
uint8_t dest, dest_mode;
int dest_vcpu_id;
@@ -169,15 +164,16 @@ int pt_irq_create_bind(
{
uint32_t mask = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI;
- if ( (pirq_dpci->flags & mask) != mask)
+ if ( (pirq_dpci->flags & mask) != mask )
{
- spin_unlock(&d->event_lock);
- return -EBUSY;
+ spin_unlock(&d->event_lock);
+ return -EBUSY;
}
- /* if pirq is already mapped as vmsi, update the guest data/addr */
+ /* If pirq is already mapped as vmsi, update guest data/addr. */
if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
- pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
+ pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags )
+ {
/* Directly clear pending EOIs before enabling new MSI info. */
pirq_guest_eoi(info);
@@ -185,7 +181,7 @@ int pt_irq_create_bind(
pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
}
}
- /* Caculate dest_vcpu_id for MSI-type pirq migration */
+ /* Calculate dest_vcpu_id for MSI-type pirq migration. */
dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
@@ -193,36 +189,37 @@ int pt_irq_create_bind(
spin_unlock(&d->event_lock);
if ( dest_vcpu_id >= 0 )
hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
+ break;
}
- else
+
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
{
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
- hvm_irq_dpci->link_cnt[link]++;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
+ struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link);
+ struct hvm_girq_dpci_mapping *girq =
+ xmalloc(struct hvm_girq_dpci_mapping);
- digl = xmalloc(struct dev_intx_gsi_link);
- if ( !digl )
+ if ( !digl || !girq )
{
spin_unlock(&d->event_lock);
- return -ENOMEM;
- }
-
- girq = xmalloc(struct hvm_girq_dpci_mapping);
- if ( !girq )
- {
+ xfree(girq);
xfree(digl);
- spin_unlock(&d->event_lock);
return -ENOMEM;
}
+ hvm_irq_dpci->link_cnt[link]++;
+
+ digl->bus = bus;
digl->device = device;
digl->intx = intx;
- digl->gsi = guest_gsi;
- digl->link = link;
list_add_tail(&digl->list, &pirq_dpci->digl_list);
+ girq->bus = bus;
girq->device = device;
girq->intx = intx;
girq->machine_gsi = pirq;
@@ -261,12 +258,12 @@ int pt_irq_create_bind(
kill_timer(&pirq_dpci->timer);
pirq_dpci->dom = NULL;
list_del(&girq->list);
- xfree(girq);
list_del(&digl->list);
hvm_irq_dpci->link_cnt[link]--;
pirq_dpci->flags = 0;
pirq_cleanup_check(info, d);
spin_unlock(&d->event_lock);
+ xfree(girq);
xfree(digl);
return rc;
}
@@ -276,33 +273,51 @@ int pt_irq_create_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, pirq, guest_gsi, device, intx);
+ "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u intx=%u\n",
+ d->domain_id, pirq, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
+ break;
+ }
+
+ default:
+ spin_unlock(&d->event_lock);
+ return -EOPNOTSUPP;
}
+
return 0;
}
int pt_irq_destroy_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
- uint32_t machine_gsi, guest_gsi;
- uint32_t device, intx, link;
+ unsigned int machine_gsi = pt_irq_bind->machine_irq;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
struct dev_intx_gsi_link *digl, *tmp;
struct hvm_girq_dpci_mapping *girq;
struct pirq *pirq;
- machine_gsi = pt_irq_bind->machine_irq;
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ break;
+ case PT_IRQ_TYPE_MSI:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: unbind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, guest_gsi, device, intx);
+ "d%d: unbind: m_gsi=%u g_gsi=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
spin_lock(&d->event_lock);
@@ -314,18 +329,28 @@ int pt_irq_destroy_bind(
return -EINVAL;
}
- hvm_irq_dpci->link_cnt[link]--;
-
list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
{
- if ( girq->machine_gsi == machine_gsi )
+ if ( girq->bus == bus &&
+ girq->device == device &&
+ girq->intx == intx &&
+ girq->machine_gsi == machine_gsi )
{
- list_del(&girq->list);
- xfree(girq);
- break;
+ list_del(&girq->list);
+ xfree(girq);
+ girq = NULL;
+ break;
}
}
+ if ( girq )
+ {
+ spin_unlock(&d->event_lock);
+ return -EINVAL;
+ }
+
+ hvm_irq_dpci->link_cnt[link]--;
+
pirq = pirq_info(d, machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -334,10 +359,9 @@ int pt_irq_destroy_bind(
{
list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
{
- if ( digl->device == device &&
- digl->intx == intx &&
- digl->link == link &&
- digl->gsi == guest_gsi )
+ if ( digl->bus == bus &&
+ digl->device == device &&
+ digl->intx == intx )
{
list_del(&digl->list);
xfree(digl);
@@ -359,8 +383,9 @@ int pt_irq_destroy_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d unmap: m_irq=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, device, intx);
+ "d%d unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
return 0;
}
@@ -481,11 +506,10 @@ static void hvm_pci_msi_assert(
static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
void *arg)
{
- uint32_t device, intx;
- struct dev_intx_gsi_link *digl;
-
if ( test_and_clear_bool(pirq_dpci->masked) )
{
+ const struct dev_intx_gsi_link *digl;
+
if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
{
hvm_pci_msi_assert(d, pirq_dpci);
@@ -496,12 +520,10 @@ static int _hvm_dirq_assist(struct domai
{
struct pirq *info = dpci_pirq(pirq_dpci);
- device = digl->device;
- intx = digl->intx;
if ( hvm_domain_use_pirq(d, info) )
send_guest_pirq(d, info);
else
- hvm_pci_intx_assert(d, device, intx);
+ hvm_pci_intx_assert(d, digl->device, digl->intx);
pirq_dpci->pending++;
if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
@@ -537,16 +559,13 @@ static void hvm_dirq_assist(unsigned lon
}
static void __hvm_dpci_eoi(struct domain *d,
- struct hvm_girq_dpci_mapping *girq,
- union vioapic_redir_entry *ent)
+ const struct hvm_girq_dpci_mapping *girq,
+ const union vioapic_redir_entry *ent)
{
- uint32_t device, intx;
struct pirq *pirq;
struct hvm_pirq_dpci *pirq_dpci;
- device = girq->device;
- intx = girq->intx;
- hvm_pci_intx_deassert(d, device, intx);
+ hvm_pci_intx_deassert(d, girq->device, girq->intx);
pirq = pirq_info(d, girq->machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -556,8 +575,8 @@ static void __hvm_dpci_eoi(struct domain
* since interrupt is still not EOIed
*/
if ( --pirq_dpci->pending ||
- ( ent && ent->fields.mask ) ||
- ! pt_irq_need_timer(pirq_dpci->flags) )
+ (ent && ent->fields.mask) ||
+ !pt_irq_need_timer(pirq_dpci->flags) )
return;
stop_timer(&pirq_dpci->timer);
@@ -565,10 +584,10 @@ static void __hvm_dpci_eoi(struct domain
}
void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
- union vioapic_redir_entry *ent)
+ const union vioapic_redir_entry *ent)
{
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ const struct hvm_girq_dpci_mapping *girq;
if ( !iommu_enabled )
return;
--- a/xen/drivers/passthrough/vtd/x86/vtd.c
+++ b/xen/drivers/passthrough/vtd/x86/vtd.c
@@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int isairq = (long)arg;
- struct dev_intx_gsi_link *digl, *tmp;
+ const struct dev_intx_gsi_link *digl;
- list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+ list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
{
- if ( hvm_irq->pci_link.route[digl->link] == isairq )
+ unsigned int link = hvm_pci_intx_link(digl->device, digl->intx);
+
+ if ( hvm_irq->pci_link.route[link] == isairq )
{
hvm_pci_intx_deassert(d, digl->device, digl->intx);
if ( --pirq_dpci->pending == 0 )
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -123,7 +123,7 @@ int handle_pio(uint16_t port, unsigned i
void hvm_interrupt_post(struct vcpu *v, int vector, int type);
void hvm_io_assist(ioreq_t *p);
void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
- union vioapic_redir_entry *ent);
+ const union vioapic_redir_entry *ent);
void msix_write_completion(struct vcpu *);
struct hvm_hw_stdvga {
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -30,10 +30,9 @@
struct dev_intx_gsi_link {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
- uint8_t gsi;
- uint8_t link;
};
#define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
@@ -69,6 +68,7 @@ struct hvm_gmsi_info {
struct hvm_girq_dpci_mapping {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
uint8_t machine_gsi;
[-- Attachment #2: pt-irq-binding.patch --]
[-- Type: text/plain, Size: 17626 bytes --]
pt-irq fixes and improvements
Tools side:
- don't silently ignore unrecognized PT_IRQ_TYPE_* values
- respect that the interface type contains a union, making the code at
once no longer depend on the hypervisor ignoring the bus field of the
PCI portion of the interface structure)
Hypervisor side:
- don't ignore the PCI bus number passed in
- don't store values (gsi, link) calculated from other stored values
- avoid calling xfree() with a spin lock held where easily possible
- have pt_irq_destroy_bind() respect the passed in type
- scope reduction and constification of various variables
- use switch instead of if/else-if chains
- formatting
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1702,15 +1702,20 @@ int xc_domain_bind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- if ( irq_type == PT_IRQ_TYPE_PCI ||
- irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
+ switch ( irq_type )
{
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
bind->u.pci.bus = bus;
bind->u.pci.device = device;
bind->u.pci.intx = intx;
- }
- else if ( irq_type == PT_IRQ_TYPE_ISA )
+ case PT_IRQ_TYPE_ISA:
bind->u.isa.isa_irq = isa_irq;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
rc = do_domctl(xch, &domctl);
return rc;
@@ -1737,10 +1742,21 @@ int xc_domain_unbind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- bind->u.pci.bus = bus;
- bind->u.pci.device = device;
- bind->u.pci.intx = intx;
- bind->u.isa.isa_irq = isa_irq;
+ switch ( irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ bind->u.pci.bus = bus;
+ bind->u.pci.device = device;
+ bind->u.pci.intx = intx;
+ break;
+ case PT_IRQ_TYPE_ISA:
+ bind->u.isa.isa_irq = isa_irq;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
rc = do_domctl(xch, &domctl);
return rc;
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq(
switch ( type )
{
case MAP_PIRQ_TYPE_GSI: {
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t machine_gsi = 0;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ unsigned int machine_gsi = 0;
if ( *index < 0 || *index >= NR_HVM_IRQS )
{
@@ -52,6 +51,8 @@ static int physdev_hvm_map_pirq(
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci )
{
+ const struct hvm_girq_dpci_mapping *girq;
+
BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS);
list_for_each_entry ( girq,
&hvm_irq_dpci->girq[*index],
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -51,11 +51,8 @@ static int pt_irq_guest_eoi(struct domai
static void pt_irq_time_out(void *data)
{
struct hvm_pirq_dpci *irq_map = data;
- unsigned int guest_gsi;
- struct hvm_irq_dpci *dpci = NULL;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t device, intx;
+ const struct hvm_irq_dpci *dpci;
+ const struct dev_intx_gsi_link *digl;
spin_lock(&irq_map->dom->event_lock);
@@ -63,16 +60,16 @@ static void pt_irq_time_out(void *data)
ASSERT(dpci);
list_for_each_entry ( digl, &irq_map->digl_list, list )
{
- guest_gsi = digl->gsi;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx);
+ const struct hvm_girq_dpci_mapping *girq;
+
list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
{
struct pirq *pirq = pirq_info(irq_map->dom, girq->machine_gsi);
pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
}
- device = digl->device;
- intx = digl->intx;
- hvm_pci_intx_deassert(irq_map->dom, device, intx);
+ hvm_pci_intx_deassert(irq_map->dom, digl->device, digl->intx);
}
pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL);
@@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp
int pt_irq_create_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
struct pirq *info;
- uint32_t guest_gsi;
- uint32_t device, intx, link;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
int rc, pirq = pt_irq_bind->machine_irq;
if ( pirq < 0 || pirq >= d->nr_pirqs )
@@ -136,7 +129,9 @@ int pt_irq_create_bind(
}
pirq_dpci = pirq_dpci(info);
- if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_MSI:
{
uint8_t dest, dest_mode;
int dest_vcpu_id;
@@ -169,15 +164,16 @@ int pt_irq_create_bind(
{
uint32_t mask = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI;
- if ( (pirq_dpci->flags & mask) != mask)
+ if ( (pirq_dpci->flags & mask) != mask )
{
- spin_unlock(&d->event_lock);
- return -EBUSY;
+ spin_unlock(&d->event_lock);
+ return -EBUSY;
}
- /* if pirq is already mapped as vmsi, update the guest data/addr */
+ /* If pirq is already mapped as vmsi, update guest data/addr. */
if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
- pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
+ pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags )
+ {
/* Directly clear pending EOIs before enabling new MSI info. */
pirq_guest_eoi(info);
@@ -185,7 +181,7 @@ int pt_irq_create_bind(
pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
}
}
- /* Caculate dest_vcpu_id for MSI-type pirq migration */
+ /* Calculate dest_vcpu_id for MSI-type pirq migration. */
dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
@@ -193,36 +189,37 @@ int pt_irq_create_bind(
spin_unlock(&d->event_lock);
if ( dest_vcpu_id >= 0 )
hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
+ break;
}
- else
+
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
{
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
- hvm_irq_dpci->link_cnt[link]++;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
+ struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link);
+ struct hvm_girq_dpci_mapping *girq =
+ xmalloc(struct hvm_girq_dpci_mapping);
- digl = xmalloc(struct dev_intx_gsi_link);
- if ( !digl )
+ if ( !digl || !girq )
{
spin_unlock(&d->event_lock);
- return -ENOMEM;
- }
-
- girq = xmalloc(struct hvm_girq_dpci_mapping);
- if ( !girq )
- {
+ xfree(girq);
xfree(digl);
- spin_unlock(&d->event_lock);
return -ENOMEM;
}
+ hvm_irq_dpci->link_cnt[link]++;
+
+ digl->bus = bus;
digl->device = device;
digl->intx = intx;
- digl->gsi = guest_gsi;
- digl->link = link;
list_add_tail(&digl->list, &pirq_dpci->digl_list);
+ girq->bus = bus;
girq->device = device;
girq->intx = intx;
girq->machine_gsi = pirq;
@@ -261,12 +258,12 @@ int pt_irq_create_bind(
kill_timer(&pirq_dpci->timer);
pirq_dpci->dom = NULL;
list_del(&girq->list);
- xfree(girq);
list_del(&digl->list);
hvm_irq_dpci->link_cnt[link]--;
pirq_dpci->flags = 0;
pirq_cleanup_check(info, d);
spin_unlock(&d->event_lock);
+ xfree(girq);
xfree(digl);
return rc;
}
@@ -276,33 +273,51 @@ int pt_irq_create_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, pirq, guest_gsi, device, intx);
+ "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u intx=%u\n",
+ d->domain_id, pirq, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
+ break;
+ }
+
+ default:
+ spin_unlock(&d->event_lock);
+ return -EOPNOTSUPP;
}
+
return 0;
}
int pt_irq_destroy_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
- uint32_t machine_gsi, guest_gsi;
- uint32_t device, intx, link;
+ unsigned int machine_gsi = pt_irq_bind->machine_irq;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
struct dev_intx_gsi_link *digl, *tmp;
struct hvm_girq_dpci_mapping *girq;
struct pirq *pirq;
- machine_gsi = pt_irq_bind->machine_irq;
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ break;
+ case PT_IRQ_TYPE_MSI:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: unbind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, guest_gsi, device, intx);
+ "d%d: unbind: m_gsi=%u g_gsi=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
spin_lock(&d->event_lock);
@@ -314,18 +329,28 @@ int pt_irq_destroy_bind(
return -EINVAL;
}
- hvm_irq_dpci->link_cnt[link]--;
-
list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
{
- if ( girq->machine_gsi == machine_gsi )
+ if ( girq->bus == bus &&
+ girq->device == device &&
+ girq->intx == intx &&
+ girq->machine_gsi == machine_gsi )
{
- list_del(&girq->list);
- xfree(girq);
- break;
+ list_del(&girq->list);
+ xfree(girq);
+ girq = NULL;
+ break;
}
}
+ if ( girq )
+ {
+ spin_unlock(&d->event_lock);
+ return -EINVAL;
+ }
+
+ hvm_irq_dpci->link_cnt[link]--;
+
pirq = pirq_info(d, machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -334,10 +359,9 @@ int pt_irq_destroy_bind(
{
list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
{
- if ( digl->device == device &&
- digl->intx == intx &&
- digl->link == link &&
- digl->gsi == guest_gsi )
+ if ( digl->bus == bus &&
+ digl->device == device &&
+ digl->intx == intx )
{
list_del(&digl->list);
xfree(digl);
@@ -359,8 +383,9 @@ int pt_irq_destroy_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d unmap: m_irq=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, device, intx);
+ "d%d unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
return 0;
}
@@ -481,11 +506,10 @@ static void hvm_pci_msi_assert(
static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
void *arg)
{
- uint32_t device, intx;
- struct dev_intx_gsi_link *digl;
-
if ( test_and_clear_bool(pirq_dpci->masked) )
{
+ const struct dev_intx_gsi_link *digl;
+
if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
{
hvm_pci_msi_assert(d, pirq_dpci);
@@ -496,12 +520,10 @@ static int _hvm_dirq_assist(struct domai
{
struct pirq *info = dpci_pirq(pirq_dpci);
- device = digl->device;
- intx = digl->intx;
if ( hvm_domain_use_pirq(d, info) )
send_guest_pirq(d, info);
else
- hvm_pci_intx_assert(d, device, intx);
+ hvm_pci_intx_assert(d, digl->device, digl->intx);
pirq_dpci->pending++;
if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
@@ -537,16 +559,13 @@ static void hvm_dirq_assist(unsigned lon
}
static void __hvm_dpci_eoi(struct domain *d,
- struct hvm_girq_dpci_mapping *girq,
- union vioapic_redir_entry *ent)
+ const struct hvm_girq_dpci_mapping *girq,
+ const union vioapic_redir_entry *ent)
{
- uint32_t device, intx;
struct pirq *pirq;
struct hvm_pirq_dpci *pirq_dpci;
- device = girq->device;
- intx = girq->intx;
- hvm_pci_intx_deassert(d, device, intx);
+ hvm_pci_intx_deassert(d, girq->device, girq->intx);
pirq = pirq_info(d, girq->machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -556,8 +575,8 @@ static void __hvm_dpci_eoi(struct domain
* since interrupt is still not EOIed
*/
if ( --pirq_dpci->pending ||
- ( ent && ent->fields.mask ) ||
- ! pt_irq_need_timer(pirq_dpci->flags) )
+ (ent && ent->fields.mask) ||
+ !pt_irq_need_timer(pirq_dpci->flags) )
return;
stop_timer(&pirq_dpci->timer);
@@ -565,10 +584,10 @@ static void __hvm_dpci_eoi(struct domain
}
void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
- union vioapic_redir_entry *ent)
+ const union vioapic_redir_entry *ent)
{
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ const struct hvm_girq_dpci_mapping *girq;
if ( !iommu_enabled )
return;
--- a/xen/drivers/passthrough/vtd/x86/vtd.c
+++ b/xen/drivers/passthrough/vtd/x86/vtd.c
@@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int isairq = (long)arg;
- struct dev_intx_gsi_link *digl, *tmp;
+ const struct dev_intx_gsi_link *digl;
- list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+ list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
{
- if ( hvm_irq->pci_link.route[digl->link] == isairq )
+ unsigned int link = hvm_pci_intx_link(digl->device, digl->intx);
+
+ if ( hvm_irq->pci_link.route[link] == isairq )
{
hvm_pci_intx_deassert(d, digl->device, digl->intx);
if ( --pirq_dpci->pending == 0 )
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -123,7 +123,7 @@ int handle_pio(uint16_t port, unsigned i
void hvm_interrupt_post(struct vcpu *v, int vector, int type);
void hvm_io_assist(ioreq_t *p);
void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
- union vioapic_redir_entry *ent);
+ const union vioapic_redir_entry *ent);
void msix_write_completion(struct vcpu *);
struct hvm_hw_stdvga {
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -30,10 +30,9 @@
struct dev_intx_gsi_link {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
- uint8_t gsi;
- uint8_t link;
};
#define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
@@ -69,6 +68,7 @@ struct hvm_gmsi_info {
struct hvm_girq_dpci_mapping {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
uint8_t machine_gsi;
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] x86/HVM: properly propagate errors from HVMOP_inject_msi
2014-06-03 13:58 ` [PATCH 1/3] x86/HVM: properly propagate errors from HVMOP_inject_msi Jan Beulich
@ 2014-06-03 14:05 ` Andrew Cooper
0 siblings, 0 replies; 12+ messages in thread
From: Andrew Cooper @ 2014-06-03 14:05 UTC (permalink / raw)
To: Jan Beulich; +Cc: xen-devel, Keir Fraser, Stefano Stabellini
[-- Attachment #1.1: Type: text/plain, Size: 2984 bytes --]
On 03/06/14 14:58, Jan Beulich wrote:
> There are a number of ways this operation can go wrong, all of which
> got ignored so far.
>
> In the context of this I wonder whether map_domain_emuirq_pirq()
> returning 0 in the "already mapped" case is really intended to be that
> way (this is why the subsequent NULL check here can't be an ASSERT()).
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
>
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -5096,7 +5096,7 @@ static int hvmop_inject_msi(
> if ( rc )
> goto out;
>
> - hvm_inject_msi(d, op.addr, op.data);
> + rc = hvm_inject_msi(d, op.addr, op.data);
>
> out:
> rcu_unlock_domain(d);
> --- a/xen/arch/x86/hvm/irq.c
> +++ b/xen/arch/x86/hvm/irq.c
> @@ -270,7 +270,7 @@ void hvm_set_pci_link_route(struct domai
> d->domain_id, link, old_isa_irq, isa_irq);
> }
>
> -void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
> +int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data)
> {
> uint32_t tmp = (uint32_t) addr;
> uint8_t dest = (tmp & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
> @@ -292,20 +292,28 @@ void hvm_inject_msi(struct domain *d, ui
> /* if it is the first time, allocate the pirq */
> if ( !info || info->arch.hvm.emuirq == IRQ_UNBOUND )
> {
> + int rc;
> +
> spin_lock(&d->event_lock);
> - map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
> + rc = map_domain_emuirq_pirq(d, pirq, IRQ_MSI_EMU);
> spin_unlock(&d->event_lock);
> + if ( rc )
> + return rc;
> info = pirq_info(d, pirq);
> if ( !info )
> - return;
> - } else if (info->arch.hvm.emuirq != IRQ_MSI_EMU)
> - return;
> + return -EBUSY;
> + }
> + else if ( info->arch.hvm.emuirq != IRQ_MSI_EMU )
> + return -EINVAL;
> send_guest_pirq(d, info);
> - return;
> + return 0;
> }
> + return -ERANGE;
> }
>
> vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
> +
> + return 0;
> }
>
> void hvm_set_callback_via(struct domain *d, uint64_t via)
> --- a/xen/include/xen/hvm/irq.h
> +++ b/xen/include/xen/hvm/irq.h
> @@ -123,7 +123,7 @@ void hvm_isa_irq_deassert(
>
> void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
>
> -void hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
> +int hvm_inject_msi(struct domain *d, uint64_t addr, uint32_t data);
>
> void hvm_maybe_deassert_evtchn_irq(void);
> void hvm_assert_evtchn_irq(struct vcpu *v);
>
>
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
[-- Attachment #1.2: Type: text/html, Size: 3793 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] x86/HVM: make vmsi_deliver() return proper error values
2014-06-03 13:59 ` [PATCH 2/3] x86/HVM: make vmsi_deliver() return proper error values Jan Beulich
@ 2014-06-03 14:13 ` Andrew Cooper
0 siblings, 0 replies; 12+ messages in thread
From: Andrew Cooper @ 2014-06-03 14:13 UTC (permalink / raw)
To: Jan Beulich; +Cc: xen-devel, Keir Fraser
[-- Attachment #1.1: Type: text/plain, Size: 3937 bytes --]
On 03/06/14 14:59, Jan Beulich wrote:
> ... and propagate this from hvm_inject_msi(). In the course of this I
> spotted further room for cleanup:
> - vmsi_inj_irq()'s struct domain * parameter was unused
> - vmsi_deliver() pointlessly passed on dest_ExtINT to vmsi_inj_irq()
> (which that one validly refused to handle)
> - vmsi_inj_irq()'s sole caller guarantees a proper delivery mode (i.e.
> rather than printing an obscure message we can just BUG())
> - some formatting and log message quirks
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Arguably under Xen style, the final addition in the final hunk should
have a newline before return 0, but that's trivial.
>
> --- a/xen/arch/x86/hvm/irq.c
> +++ b/xen/arch/x86/hvm/irq.c
> @@ -311,9 +311,7 @@ int hvm_inject_msi(struct domain *d, uin
> return -ERANGE;
> }
>
> - vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
> -
> - return 0;
> + return vmsi_deliver(d, vector, dest, dest_mode, delivery_mode, trig_mode);
> }
>
> void hvm_set_callback_via(struct domain *d, uint64_t via)
> --- a/xen/arch/x86/hvm/vmsi.c
> +++ b/xen/arch/x86/hvm/vmsi.c
> @@ -43,14 +43,12 @@
> #include <asm/io_apic.h>
>
> static void vmsi_inj_irq(
> - struct domain *d,
> struct vlapic *target,
> uint8_t vector,
> uint8_t trig_mode,
> uint8_t delivery_mode)
> {
> - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vmsi_inj_irq "
> - "irq %d trig %d delive mode %d\n",
> + HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vmsi_inj_irq: vec %02x trig %d dm %d\n",
> vector, trig_mode, delivery_mode);
>
> switch ( delivery_mode )
> @@ -60,8 +58,7 @@ static void vmsi_inj_irq(
> vlapic_set_irq(target, vector, trig_mode);
> break;
> default:
> - gdprintk(XENLOG_WARNING, "error delivery mode %d\n", delivery_mode);
> - break;
> + BUG();
> }
> }
>
> @@ -76,38 +73,31 @@ int vmsi_deliver(
> switch ( delivery_mode )
> {
> case dest_LowestPrio:
> - {
> target = vlapic_lowest_prio(d, NULL, 0, dest, dest_mode);
> if ( target != NULL )
> - vmsi_inj_irq(d, target, vector, trig_mode, delivery_mode);
> - else
> - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin: "
> - "vector=%x delivery_mode=%x\n",
> - vector, dest_LowestPrio);
> - break;
> - }
> + {
> + vmsi_inj_irq(target, vector, trig_mode, delivery_mode);
> + break;
> + }
> + HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "null MSI round robin: vector=%02x\n",
> + vector);
> + return -ESRCH;
>
> case dest_Fixed:
> - case dest_ExtINT:
> - {
> for_each_vcpu ( d, v )
> if ( vlapic_match_dest(vcpu_vlapic(v), NULL,
> 0, dest, dest_mode) )
> - vmsi_inj_irq(d, vcpu_vlapic(v),
> - vector, trig_mode, delivery_mode);
> + vmsi_inj_irq(vcpu_vlapic(v), vector,
> + trig_mode, delivery_mode);
> break;
> - }
>
> - case dest_SMI:
> - case dest_NMI:
> - case dest_INIT:
> - case dest__reserved_2:
> default:
> - gdprintk(XENLOG_WARNING, "Unsupported delivery mode %d\n",
> - delivery_mode);
> - break;
> + printk(XENLOG_G_WARNING
> + "%pv: Unsupported MSI delivery mode %d for Dom%d\n",
> + current, delivery_mode, d->domain_id);
> + return -EINVAL;
> }
> - return 1;
> + return 0;
> }
>
> void vmsi_deliver_pirq(struct domain *d, const struct hvm_pirq_dpci *pirq_dpci)
>
>
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
[-- Attachment #1.2: Type: text/html, Size: 4680 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/3] pt-irq fixes and improvements
2014-06-03 14:00 ` [PATCH 3/3] pt-irq fixes and improvements Jan Beulich
@ 2014-06-03 14:50 ` Andrew Cooper
2014-06-04 8:24 ` [PATCH v2 " Jan Beulich
0 siblings, 1 reply; 12+ messages in thread
From: Andrew Cooper @ 2014-06-03 14:50 UTC (permalink / raw)
To: Jan Beulich
Cc: Kevin Tian, Keir Fraser, Ian Jackson, Ian Campbell,
Stefano Stabellini, Yang Z Zhang, xen-devel
On 03/06/14 15:00, Jan Beulich wrote:
> Tools side:
> - don't silently ignore unrecognized PT_IRQ_TYPE_* values
> - respect that the interface type contains a union, making the code at
> once no longer depend on the hypervisor ignoring the bus field of the
> PCI portion of the interface structure)
>
> Hypervisor side:
> - don't ignore the PCI bus number passed in
> - don't store values (gsi, link) calculated from other stored values
> - avoid calling xfree() with a spin lock held where easily possible
> - have pt_irq_destroy_bind() respect the passed in type
> - scope reduction and constification of various variables
> - use switch instead of if/else-if chains
> - formatting
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> with a few
suggestions for further cleanup...
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -1702,15 +1702,20 @@ int xc_domain_bind_pt_irq(
> bind->hvm_domid = domid;
> bind->irq_type = irq_type;
> bind->machine_irq = machine_irq;
> - if ( irq_type == PT_IRQ_TYPE_PCI ||
> - irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
> + switch ( irq_type )
> {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> bind->u.pci.bus = bus;
> bind->u.pci.device = device;
Given all this other cleanup, can you nuke the trailing whitespace here...
> bind->u.pci.intx = intx;
> - }
> - else if ( irq_type == PT_IRQ_TYPE_ISA )
> + case PT_IRQ_TYPE_ISA:
> bind->u.isa.isa_irq = isa_irq;
> + break;
> + default:
> + errno = EINVAL;
> + return -1;
> + }
>
... and here.
> rc = do_domctl(xch, &domctl);
> return rc;
> @@ -1737,10 +1742,21 @@ int xc_domain_unbind_pt_irq(
> bind->hvm_domid = domid;
> bind->irq_type = irq_type;
> bind->machine_irq = machine_irq;
> - bind->u.pci.bus = bus;
> - bind->u.pci.device = device;
> - bind->u.pci.intx = intx;
> - bind->u.isa.isa_irq = isa_irq;
> + switch ( irq_type )
> + {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> + bind->u.pci.bus = bus;
> + bind->u.pci.device = device;
> + bind->u.pci.intx = intx;
> + break;
> + case PT_IRQ_TYPE_ISA:
> + bind->u.isa.isa_irq = isa_irq;
> + break;
> + default:
> + errno = EINVAL;
> + return -1;
> + }
>
And here in this function.
> @@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp
> int pt_irq_create_bind(
> struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
> {
> - struct hvm_irq_dpci *hvm_irq_dpci = NULL;
> + struct hvm_irq_dpci *hvm_irq_dpci;
> struct hvm_pirq_dpci *pirq_dpci;
> struct pirq *info;
> - uint32_t guest_gsi;
> - uint32_t device, intx, link;
> - struct dev_intx_gsi_link *digl;
> - struct hvm_girq_dpci_mapping *girq;
> int rc, pirq = pt_irq_bind->machine_irq;
>
> if ( pirq < 0 || pirq >= d->nr_pirqs )
Given all the cleanup, there is a further piece which could be done
between these two hunks.
There is an int i (declared in a for loop initialiser, despite our
fairly consistent C89 style), which should be unsigned.
> @@ -136,7 +129,9 @@ int pt_irq_create_bind(
> }
> pirq_dpci = pirq_dpci(info);
>
> - if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
> + switch ( pt_irq_bind->irq_type )
> + {
> + case PT_IRQ_TYPE_MSI:
> {
> uint8_t dest, dest_mode;
> int dest_vcpu_id;
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 3/3] pt-irq fixes and improvements
2014-06-03 14:50 ` Andrew Cooper
@ 2014-06-04 8:24 ` Jan Beulich
2014-06-10 0:32 ` Zhang, Yang Z
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Jan Beulich @ 2014-06-04 8:24 UTC (permalink / raw)
To: xen-devel
Cc: Kevin Tian, Keir Fraser, Andrew Cooper, Ian Jackson,
Ian Campbell, Stefano Stabellini, Yang Z Zhang
[-- Attachment #1: Type: text/plain, Size: 18436 bytes --]
Tools side:
- don't silently ignore unrecognized PT_IRQ_TYPE_* values
- respect that the interface type contains a union, making the code at
once no longer depend on the hypervisor ignoring the bus field of the
PCI portion of the interface structure)
Hypervisor side:
- don't ignore the PCI bus number passed in
- don't store values (gsi, link) calculated from other stored values
- avoid calling xfree() with a spin lock held where easily possible
- have pt_irq_destroy_bind() respect the passed in type
- scope reduction and constification of various variables
- use switch instead of if/else-if chains
- formatting
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
v2: A few extra coding style corrections according to Andrew's
suggestions.
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1702,16 +1702,21 @@ int xc_domain_bind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- if ( irq_type == PT_IRQ_TYPE_PCI ||
- irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
+ switch ( irq_type )
{
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
bind->u.pci.bus = bus;
- bind->u.pci.device = device;
+ bind->u.pci.device = device;
bind->u.pci.intx = intx;
- }
- else if ( irq_type == PT_IRQ_TYPE_ISA )
+ case PT_IRQ_TYPE_ISA:
bind->u.isa.isa_irq = isa_irq;
-
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
rc = do_domctl(xch, &domctl);
return rc;
}
@@ -1737,11 +1742,22 @@ int xc_domain_unbind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- bind->u.pci.bus = bus;
- bind->u.pci.device = device;
- bind->u.pci.intx = intx;
- bind->u.isa.isa_irq = isa_irq;
-
+ switch ( irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ bind->u.pci.bus = bus;
+ bind->u.pci.device = device;
+ bind->u.pci.intx = intx;
+ break;
+ case PT_IRQ_TYPE_ISA:
+ bind->u.isa.isa_irq = isa_irq;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
rc = do_domctl(xch, &domctl);
return rc;
}
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq(
switch ( type )
{
case MAP_PIRQ_TYPE_GSI: {
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t machine_gsi = 0;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ unsigned int machine_gsi = 0;
if ( *index < 0 || *index >= NR_HVM_IRQS )
{
@@ -52,6 +51,8 @@ static int physdev_hvm_map_pirq(
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci )
{
+ const struct hvm_girq_dpci_mapping *girq;
+
BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS);
list_for_each_entry ( girq,
&hvm_irq_dpci->girq[*index],
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -51,11 +51,8 @@ static int pt_irq_guest_eoi(struct domai
static void pt_irq_time_out(void *data)
{
struct hvm_pirq_dpci *irq_map = data;
- unsigned int guest_gsi;
- struct hvm_irq_dpci *dpci = NULL;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t device, intx;
+ const struct hvm_irq_dpci *dpci;
+ const struct dev_intx_gsi_link *digl;
spin_lock(&irq_map->dom->event_lock);
@@ -63,16 +60,16 @@ static void pt_irq_time_out(void *data)
ASSERT(dpci);
list_for_each_entry ( digl, &irq_map->digl_list, list )
{
- guest_gsi = digl->gsi;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx);
+ const struct hvm_girq_dpci_mapping *girq;
+
list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
{
struct pirq *pirq = pirq_info(irq_map->dom, girq->machine_gsi);
pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
}
- device = digl->device;
- intx = digl->intx;
- hvm_pci_intx_deassert(irq_map->dom, device, intx);
+ hvm_pci_intx_deassert(irq_map->dom, digl->device, digl->intx);
}
pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL);
@@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp
int pt_irq_create_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
struct pirq *info;
- uint32_t guest_gsi;
- uint32_t device, intx, link;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
int rc, pirq = pt_irq_bind->machine_irq;
if ( pirq < 0 || pirq >= d->nr_pirqs )
@@ -113,6 +106,8 @@ int pt_irq_create_bind(
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci == NULL )
{
+ unsigned int i;
+
hvm_irq_dpci = xzalloc(struct hvm_irq_dpci);
if ( hvm_irq_dpci == NULL )
{
@@ -122,7 +117,7 @@ int pt_irq_create_bind(
softirq_tasklet_init(
&hvm_irq_dpci->dirq_tasklet,
hvm_dirq_assist, (unsigned long)d);
- for ( int i = 0; i < NR_HVM_IRQS; i++ )
+ for ( i = 0; i < NR_HVM_IRQS; i++ )
INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]);
d->arch.hvm_domain.irq.dpci = hvm_irq_dpci;
@@ -136,7 +131,9 @@ int pt_irq_create_bind(
}
pirq_dpci = pirq_dpci(info);
- if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_MSI:
{
uint8_t dest, dest_mode;
int dest_vcpu_id;
@@ -169,15 +166,16 @@ int pt_irq_create_bind(
{
uint32_t mask = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI;
- if ( (pirq_dpci->flags & mask) != mask)
+ if ( (pirq_dpci->flags & mask) != mask )
{
- spin_unlock(&d->event_lock);
- return -EBUSY;
+ spin_unlock(&d->event_lock);
+ return -EBUSY;
}
- /* if pirq is already mapped as vmsi, update the guest data/addr */
+ /* If pirq is already mapped as vmsi, update guest data/addr. */
if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
- pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
+ pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags )
+ {
/* Directly clear pending EOIs before enabling new MSI info. */
pirq_guest_eoi(info);
@@ -185,7 +183,7 @@ int pt_irq_create_bind(
pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
}
}
- /* Caculate dest_vcpu_id for MSI-type pirq migration */
+ /* Calculate dest_vcpu_id for MSI-type pirq migration. */
dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
@@ -193,36 +191,37 @@ int pt_irq_create_bind(
spin_unlock(&d->event_lock);
if ( dest_vcpu_id >= 0 )
hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
+ break;
}
- else
+
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
{
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
- hvm_irq_dpci->link_cnt[link]++;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
+ struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link);
+ struct hvm_girq_dpci_mapping *girq =
+ xmalloc(struct hvm_girq_dpci_mapping);
- digl = xmalloc(struct dev_intx_gsi_link);
- if ( !digl )
+ if ( !digl || !girq )
{
spin_unlock(&d->event_lock);
- return -ENOMEM;
- }
-
- girq = xmalloc(struct hvm_girq_dpci_mapping);
- if ( !girq )
- {
+ xfree(girq);
xfree(digl);
- spin_unlock(&d->event_lock);
return -ENOMEM;
}
+ hvm_irq_dpci->link_cnt[link]++;
+
+ digl->bus = bus;
digl->device = device;
digl->intx = intx;
- digl->gsi = guest_gsi;
- digl->link = link;
list_add_tail(&digl->list, &pirq_dpci->digl_list);
+ girq->bus = bus;
girq->device = device;
girq->intx = intx;
girq->machine_gsi = pirq;
@@ -261,12 +260,12 @@ int pt_irq_create_bind(
kill_timer(&pirq_dpci->timer);
pirq_dpci->dom = NULL;
list_del(&girq->list);
- xfree(girq);
list_del(&digl->list);
hvm_irq_dpci->link_cnt[link]--;
pirq_dpci->flags = 0;
pirq_cleanup_check(info, d);
spin_unlock(&d->event_lock);
+ xfree(girq);
xfree(digl);
return rc;
}
@@ -276,33 +275,51 @@ int pt_irq_create_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, pirq, guest_gsi, device, intx);
+ "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u intx=%u\n",
+ d->domain_id, pirq, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
+ break;
}
+
+ default:
+ spin_unlock(&d->event_lock);
+ return -EOPNOTSUPP;
+ }
+
return 0;
}
int pt_irq_destroy_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
- uint32_t machine_gsi, guest_gsi;
- uint32_t device, intx, link;
+ unsigned int machine_gsi = pt_irq_bind->machine_irq;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
struct dev_intx_gsi_link *digl, *tmp;
struct hvm_girq_dpci_mapping *girq;
struct pirq *pirq;
- machine_gsi = pt_irq_bind->machine_irq;
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ break;
+ case PT_IRQ_TYPE_MSI:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: unbind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, guest_gsi, device, intx);
+ "d%d: unbind: m_gsi=%u g_gsi=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
spin_lock(&d->event_lock);
@@ -314,18 +331,28 @@ int pt_irq_destroy_bind(
return -EINVAL;
}
- hvm_irq_dpci->link_cnt[link]--;
-
list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
{
- if ( girq->machine_gsi == machine_gsi )
+ if ( girq->bus == bus &&
+ girq->device == device &&
+ girq->intx == intx &&
+ girq->machine_gsi == machine_gsi )
{
- list_del(&girq->list);
- xfree(girq);
- break;
+ list_del(&girq->list);
+ xfree(girq);
+ girq = NULL;
+ break;
}
}
+ if ( girq )
+ {
+ spin_unlock(&d->event_lock);
+ return -EINVAL;
+ }
+
+ hvm_irq_dpci->link_cnt[link]--;
+
pirq = pirq_info(d, machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -334,10 +361,9 @@ int pt_irq_destroy_bind(
{
list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
{
- if ( digl->device == device &&
- digl->intx == intx &&
- digl->link == link &&
- digl->gsi == guest_gsi )
+ if ( digl->bus == bus &&
+ digl->device == device &&
+ digl->intx == intx )
{
list_del(&digl->list);
xfree(digl);
@@ -359,8 +385,9 @@ int pt_irq_destroy_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d unmap: m_irq=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, device, intx);
+ "d%d unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
return 0;
}
@@ -481,11 +508,10 @@ static void hvm_pci_msi_assert(
static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
void *arg)
{
- uint32_t device, intx;
- struct dev_intx_gsi_link *digl;
-
if ( test_and_clear_bool(pirq_dpci->masked) )
{
+ const struct dev_intx_gsi_link *digl;
+
if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
{
hvm_pci_msi_assert(d, pirq_dpci);
@@ -496,12 +522,10 @@ static int _hvm_dirq_assist(struct domai
{
struct pirq *info = dpci_pirq(pirq_dpci);
- device = digl->device;
- intx = digl->intx;
if ( hvm_domain_use_pirq(d, info) )
send_guest_pirq(d, info);
else
- hvm_pci_intx_assert(d, device, intx);
+ hvm_pci_intx_assert(d, digl->device, digl->intx);
pirq_dpci->pending++;
if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
@@ -537,16 +561,13 @@ static void hvm_dirq_assist(unsigned lon
}
static void __hvm_dpci_eoi(struct domain *d,
- struct hvm_girq_dpci_mapping *girq,
- union vioapic_redir_entry *ent)
+ const struct hvm_girq_dpci_mapping *girq,
+ const union vioapic_redir_entry *ent)
{
- uint32_t device, intx;
struct pirq *pirq;
struct hvm_pirq_dpci *pirq_dpci;
- device = girq->device;
- intx = girq->intx;
- hvm_pci_intx_deassert(d, device, intx);
+ hvm_pci_intx_deassert(d, girq->device, girq->intx);
pirq = pirq_info(d, girq->machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -556,8 +577,8 @@ static void __hvm_dpci_eoi(struct domain
* since interrupt is still not EOIed
*/
if ( --pirq_dpci->pending ||
- ( ent && ent->fields.mask ) ||
- ! pt_irq_need_timer(pirq_dpci->flags) )
+ (ent && ent->fields.mask) ||
+ !pt_irq_need_timer(pirq_dpci->flags) )
return;
stop_timer(&pirq_dpci->timer);
@@ -565,10 +586,10 @@ static void __hvm_dpci_eoi(struct domain
}
void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
- union vioapic_redir_entry *ent)
+ const union vioapic_redir_entry *ent)
{
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ const struct hvm_girq_dpci_mapping *girq;
if ( !iommu_enabled )
return;
--- a/xen/drivers/passthrough/vtd/x86/vtd.c
+++ b/xen/drivers/passthrough/vtd/x86/vtd.c
@@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int isairq = (long)arg;
- struct dev_intx_gsi_link *digl, *tmp;
+ const struct dev_intx_gsi_link *digl;
- list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+ list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
{
- if ( hvm_irq->pci_link.route[digl->link] == isairq )
+ unsigned int link = hvm_pci_intx_link(digl->device, digl->intx);
+
+ if ( hvm_irq->pci_link.route[link] == isairq )
{
hvm_pci_intx_deassert(d, digl->device, digl->intx);
if ( --pirq_dpci->pending == 0 )
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -123,7 +123,7 @@ int handle_pio(uint16_t port, unsigned i
void hvm_interrupt_post(struct vcpu *v, int vector, int type);
void hvm_io_assist(ioreq_t *p);
void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
- union vioapic_redir_entry *ent);
+ const union vioapic_redir_entry *ent);
void msix_write_completion(struct vcpu *);
struct hvm_hw_stdvga {
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -30,10 +30,9 @@
struct dev_intx_gsi_link {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
- uint8_t gsi;
- uint8_t link;
};
#define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
@@ -69,6 +68,7 @@ struct hvm_gmsi_info {
struct hvm_girq_dpci_mapping {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
uint8_t machine_gsi;
[-- Attachment #2: pt-irq-binding.patch --]
[-- Type: text/plain, Size: 18465 bytes --]
pt-irq fixes and improvements
Tools side:
- don't silently ignore unrecognized PT_IRQ_TYPE_* values
- respect that the interface type contains a union, making the code at
once no longer depend on the hypervisor ignoring the bus field of the
PCI portion of the interface structure)
Hypervisor side:
- don't ignore the PCI bus number passed in
- don't store values (gsi, link) calculated from other stored values
- avoid calling xfree() with a spin lock held where easily possible
- have pt_irq_destroy_bind() respect the passed in type
- scope reduction and constification of various variables
- use switch instead of if/else-if chains
- formatting
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
v2: A few extra coding style corrections according to Andrew's
suggestions.
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1702,16 +1702,21 @@ int xc_domain_bind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- if ( irq_type == PT_IRQ_TYPE_PCI ||
- irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
+ switch ( irq_type )
{
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
bind->u.pci.bus = bus;
- bind->u.pci.device = device;
+ bind->u.pci.device = device;
bind->u.pci.intx = intx;
- }
- else if ( irq_type == PT_IRQ_TYPE_ISA )
+ case PT_IRQ_TYPE_ISA:
bind->u.isa.isa_irq = isa_irq;
-
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
rc = do_domctl(xch, &domctl);
return rc;
}
@@ -1737,11 +1742,22 @@ int xc_domain_unbind_pt_irq(
bind->hvm_domid = domid;
bind->irq_type = irq_type;
bind->machine_irq = machine_irq;
- bind->u.pci.bus = bus;
- bind->u.pci.device = device;
- bind->u.pci.intx = intx;
- bind->u.isa.isa_irq = isa_irq;
-
+ switch ( irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ bind->u.pci.bus = bus;
+ bind->u.pci.device = device;
+ bind->u.pci.intx = intx;
+ break;
+ case PT_IRQ_TYPE_ISA:
+ bind->u.isa.isa_irq = isa_irq;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
rc = do_domctl(xch, &domctl);
return rc;
}
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq(
switch ( type )
{
case MAP_PIRQ_TYPE_GSI: {
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t machine_gsi = 0;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ unsigned int machine_gsi = 0;
if ( *index < 0 || *index >= NR_HVM_IRQS )
{
@@ -52,6 +51,8 @@ static int physdev_hvm_map_pirq(
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci )
{
+ const struct hvm_girq_dpci_mapping *girq;
+
BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS);
list_for_each_entry ( girq,
&hvm_irq_dpci->girq[*index],
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -51,11 +51,8 @@ static int pt_irq_guest_eoi(struct domai
static void pt_irq_time_out(void *data)
{
struct hvm_pirq_dpci *irq_map = data;
- unsigned int guest_gsi;
- struct hvm_irq_dpci *dpci = NULL;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
- uint32_t device, intx;
+ const struct hvm_irq_dpci *dpci;
+ const struct dev_intx_gsi_link *digl;
spin_lock(&irq_map->dom->event_lock);
@@ -63,16 +60,16 @@ static void pt_irq_time_out(void *data)
ASSERT(dpci);
list_for_each_entry ( digl, &irq_map->digl_list, list )
{
- guest_gsi = digl->gsi;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx);
+ const struct hvm_girq_dpci_mapping *girq;
+
list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
{
struct pirq *pirq = pirq_info(irq_map->dom, girq->machine_gsi);
pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
}
- device = digl->device;
- intx = digl->intx;
- hvm_pci_intx_deassert(irq_map->dom, device, intx);
+ hvm_pci_intx_deassert(irq_map->dom, digl->device, digl->intx);
}
pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL);
@@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp
int pt_irq_create_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
struct pirq *info;
- uint32_t guest_gsi;
- uint32_t device, intx, link;
- struct dev_intx_gsi_link *digl;
- struct hvm_girq_dpci_mapping *girq;
int rc, pirq = pt_irq_bind->machine_irq;
if ( pirq < 0 || pirq >= d->nr_pirqs )
@@ -113,6 +106,8 @@ int pt_irq_create_bind(
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci == NULL )
{
+ unsigned int i;
+
hvm_irq_dpci = xzalloc(struct hvm_irq_dpci);
if ( hvm_irq_dpci == NULL )
{
@@ -122,7 +117,7 @@ int pt_irq_create_bind(
softirq_tasklet_init(
&hvm_irq_dpci->dirq_tasklet,
hvm_dirq_assist, (unsigned long)d);
- for ( int i = 0; i < NR_HVM_IRQS; i++ )
+ for ( i = 0; i < NR_HVM_IRQS; i++ )
INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]);
d->arch.hvm_domain.irq.dpci = hvm_irq_dpci;
@@ -136,7 +131,9 @@ int pt_irq_create_bind(
}
pirq_dpci = pirq_dpci(info);
- if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_MSI:
{
uint8_t dest, dest_mode;
int dest_vcpu_id;
@@ -169,15 +166,16 @@ int pt_irq_create_bind(
{
uint32_t mask = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI;
- if ( (pirq_dpci->flags & mask) != mask)
+ if ( (pirq_dpci->flags & mask) != mask )
{
- spin_unlock(&d->event_lock);
- return -EBUSY;
+ spin_unlock(&d->event_lock);
+ return -EBUSY;
}
- /* if pirq is already mapped as vmsi, update the guest data/addr */
+ /* If pirq is already mapped as vmsi, update guest data/addr. */
if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
- pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
+ pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags )
+ {
/* Directly clear pending EOIs before enabling new MSI info. */
pirq_guest_eoi(info);
@@ -185,7 +183,7 @@ int pt_irq_create_bind(
pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
}
}
- /* Caculate dest_vcpu_id for MSI-type pirq migration */
+ /* Calculate dest_vcpu_id for MSI-type pirq migration. */
dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
@@ -193,36 +191,37 @@ int pt_irq_create_bind(
spin_unlock(&d->event_lock);
if ( dest_vcpu_id >= 0 )
hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
+ break;
}
- else
+
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
{
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
- hvm_irq_dpci->link_cnt[link]++;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
+ struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link);
+ struct hvm_girq_dpci_mapping *girq =
+ xmalloc(struct hvm_girq_dpci_mapping);
- digl = xmalloc(struct dev_intx_gsi_link);
- if ( !digl )
+ if ( !digl || !girq )
{
spin_unlock(&d->event_lock);
- return -ENOMEM;
- }
-
- girq = xmalloc(struct hvm_girq_dpci_mapping);
- if ( !girq )
- {
+ xfree(girq);
xfree(digl);
- spin_unlock(&d->event_lock);
return -ENOMEM;
}
+ hvm_irq_dpci->link_cnt[link]++;
+
+ digl->bus = bus;
digl->device = device;
digl->intx = intx;
- digl->gsi = guest_gsi;
- digl->link = link;
list_add_tail(&digl->list, &pirq_dpci->digl_list);
+ girq->bus = bus;
girq->device = device;
girq->intx = intx;
girq->machine_gsi = pirq;
@@ -261,12 +260,12 @@ int pt_irq_create_bind(
kill_timer(&pirq_dpci->timer);
pirq_dpci->dom = NULL;
list_del(&girq->list);
- xfree(girq);
list_del(&digl->list);
hvm_irq_dpci->link_cnt[link]--;
pirq_dpci->flags = 0;
pirq_cleanup_check(info, d);
spin_unlock(&d->event_lock);
+ xfree(girq);
xfree(digl);
return rc;
}
@@ -276,33 +275,51 @@ int pt_irq_create_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, pirq, guest_gsi, device, intx);
+ "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u intx=%u\n",
+ d->domain_id, pirq, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
+ break;
}
+
+ default:
+ spin_unlock(&d->event_lock);
+ return -EOPNOTSUPP;
+ }
+
return 0;
}
int pt_irq_destroy_bind(
struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+ struct hvm_irq_dpci *hvm_irq_dpci;
struct hvm_pirq_dpci *pirq_dpci;
- uint32_t machine_gsi, guest_gsi;
- uint32_t device, intx, link;
+ unsigned int machine_gsi = pt_irq_bind->machine_irq;
+ unsigned int bus = pt_irq_bind->u.pci.bus;
+ unsigned int device = pt_irq_bind->u.pci.device;
+ unsigned int intx = pt_irq_bind->u.pci.intx;
+ unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
+ unsigned int link = hvm_pci_intx_link(device, intx);
struct dev_intx_gsi_link *digl, *tmp;
struct hvm_girq_dpci_mapping *girq;
struct pirq *pirq;
- machine_gsi = pt_irq_bind->machine_irq;
- device = pt_irq_bind->u.pci.device;
- intx = pt_irq_bind->u.pci.intx;
- guest_gsi = hvm_pci_intx_gsi(device, intx);
- link = hvm_pci_intx_link(device, intx);
+ switch ( pt_irq_bind->irq_type )
+ {
+ case PT_IRQ_TYPE_PCI:
+ case PT_IRQ_TYPE_MSI_TRANSLATE:
+ break;
+ case PT_IRQ_TYPE_MSI:
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d: unbind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, guest_gsi, device, intx);
+ "d%d: unbind: m_gsi=%u g_gsi=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, guest_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
spin_lock(&d->event_lock);
@@ -314,18 +331,28 @@ int pt_irq_destroy_bind(
return -EINVAL;
}
- hvm_irq_dpci->link_cnt[link]--;
-
list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
{
- if ( girq->machine_gsi == machine_gsi )
+ if ( girq->bus == bus &&
+ girq->device == device &&
+ girq->intx == intx &&
+ girq->machine_gsi == machine_gsi )
{
- list_del(&girq->list);
- xfree(girq);
- break;
+ list_del(&girq->list);
+ xfree(girq);
+ girq = NULL;
+ break;
}
}
+ if ( girq )
+ {
+ spin_unlock(&d->event_lock);
+ return -EINVAL;
+ }
+
+ hvm_irq_dpci->link_cnt[link]--;
+
pirq = pirq_info(d, machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -334,10 +361,9 @@ int pt_irq_destroy_bind(
{
list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
{
- if ( digl->device == device &&
- digl->intx == intx &&
- digl->link == link &&
- digl->gsi == guest_gsi )
+ if ( digl->bus == bus &&
+ digl->device == device &&
+ digl->intx == intx )
{
list_del(&digl->list);
xfree(digl);
@@ -359,8 +385,9 @@ int pt_irq_destroy_bind(
if ( iommu_verbose )
dprintk(XENLOG_G_INFO,
- "d%d unmap: m_irq=%u device=%u intx=%u\n",
- d->domain_id, machine_gsi, device, intx);
+ "d%d unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n",
+ d->domain_id, machine_gsi, bus,
+ PCI_SLOT(device), PCI_FUNC(device), intx);
return 0;
}
@@ -481,11 +508,10 @@ static void hvm_pci_msi_assert(
static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
void *arg)
{
- uint32_t device, intx;
- struct dev_intx_gsi_link *digl;
-
if ( test_and_clear_bool(pirq_dpci->masked) )
{
+ const struct dev_intx_gsi_link *digl;
+
if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
{
hvm_pci_msi_assert(d, pirq_dpci);
@@ -496,12 +522,10 @@ static int _hvm_dirq_assist(struct domai
{
struct pirq *info = dpci_pirq(pirq_dpci);
- device = digl->device;
- intx = digl->intx;
if ( hvm_domain_use_pirq(d, info) )
send_guest_pirq(d, info);
else
- hvm_pci_intx_assert(d, device, intx);
+ hvm_pci_intx_assert(d, digl->device, digl->intx);
pirq_dpci->pending++;
if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
@@ -537,16 +561,13 @@ static void hvm_dirq_assist(unsigned lon
}
static void __hvm_dpci_eoi(struct domain *d,
- struct hvm_girq_dpci_mapping *girq,
- union vioapic_redir_entry *ent)
+ const struct hvm_girq_dpci_mapping *girq,
+ const union vioapic_redir_entry *ent)
{
- uint32_t device, intx;
struct pirq *pirq;
struct hvm_pirq_dpci *pirq_dpci;
- device = girq->device;
- intx = girq->intx;
- hvm_pci_intx_deassert(d, device, intx);
+ hvm_pci_intx_deassert(d, girq->device, girq->intx);
pirq = pirq_info(d, girq->machine_gsi);
pirq_dpci = pirq_dpci(pirq);
@@ -556,8 +577,8 @@ static void __hvm_dpci_eoi(struct domain
* since interrupt is still not EOIed
*/
if ( --pirq_dpci->pending ||
- ( ent && ent->fields.mask ) ||
- ! pt_irq_need_timer(pirq_dpci->flags) )
+ (ent && ent->fields.mask) ||
+ !pt_irq_need_timer(pirq_dpci->flags) )
return;
stop_timer(&pirq_dpci->timer);
@@ -565,10 +586,10 @@ static void __hvm_dpci_eoi(struct domain
}
void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
- union vioapic_redir_entry *ent)
+ const union vioapic_redir_entry *ent)
{
- struct hvm_irq_dpci *hvm_irq_dpci;
- struct hvm_girq_dpci_mapping *girq;
+ const struct hvm_irq_dpci *hvm_irq_dpci;
+ const struct hvm_girq_dpci_mapping *girq;
if ( !iommu_enabled )
return;
--- a/xen/drivers/passthrough/vtd/x86/vtd.c
+++ b/xen/drivers/passthrough/vtd/x86/vtd.c
@@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int isairq = (long)arg;
- struct dev_intx_gsi_link *digl, *tmp;
+ const struct dev_intx_gsi_link *digl;
- list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+ list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
{
- if ( hvm_irq->pci_link.route[digl->link] == isairq )
+ unsigned int link = hvm_pci_intx_link(digl->device, digl->intx);
+
+ if ( hvm_irq->pci_link.route[link] == isairq )
{
hvm_pci_intx_deassert(d, digl->device, digl->intx);
if ( --pirq_dpci->pending == 0 )
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -123,7 +123,7 @@ int handle_pio(uint16_t port, unsigned i
void hvm_interrupt_post(struct vcpu *v, int vector, int type);
void hvm_io_assist(ioreq_t *p);
void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
- union vioapic_redir_entry *ent);
+ const union vioapic_redir_entry *ent);
void msix_write_completion(struct vcpu *);
struct hvm_hw_stdvga {
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -30,10 +30,9 @@
struct dev_intx_gsi_link {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
- uint8_t gsi;
- uint8_t link;
};
#define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
@@ -69,6 +68,7 @@ struct hvm_gmsi_info {
struct hvm_girq_dpci_mapping {
struct list_head list;
+ uint8_t bus;
uint8_t device;
uint8_t intx;
uint8_t machine_gsi;
[-- Attachment #3: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/3] pt-irq fixes and improvements
2014-06-04 8:24 ` [PATCH v2 " Jan Beulich
@ 2014-06-10 0:32 ` Zhang, Yang Z
2014-06-11 12:32 ` Ping [tools]: " Jan Beulich
2014-06-12 9:02 ` Ian Campbell
2 siblings, 0 replies; 12+ messages in thread
From: Zhang, Yang Z @ 2014-06-10 0:32 UTC (permalink / raw)
To: Jan Beulich, xen-devel
Cc: Tian, Kevin, Keir Fraser, Andrew Cooper, Ian Jackson,
Ian Campbell, Stefano Stabellini
Jan Beulich wrote on 2014-06-04:
> Tools side:
> - don't silently ignore unrecognized PT_IRQ_TYPE_* values
> - respect that the interface type contains a union, making the code at
> once no longer depend on the hypervisor ignoring the bus field of the
> PCI portion of the interface structure) Hypervisor side:
> - don't ignore the PCI bus number passed in
> - don't store values (gsi, link) calculated from other stored values
> - avoid calling xfree() with a spin lock held where easily possible
> - have pt_irq_destroy_bind() respect the passed in type
> - scope reduction and constification of various variables
> - use switch instead of if/else-if chains
> - formatting
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Yang Zhang <yang.z.zhang@intel.com>
> ---
> v2: A few extra coding style corrections according to Andrew's
> suggestions.
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -1702,16 +1702,21 @@ int xc_domain_bind_pt_irq(
> bind->hvm_domid = domid;
> bind->irq_type = irq_type;
> bind->machine_irq = machine_irq;
> - if ( irq_type == PT_IRQ_TYPE_PCI ||
> - irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
> + switch ( irq_type )
> {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> bind->u.pci.bus = bus;
> - bind->u.pci.device = device;
> + bind->u.pci.device = device;
> bind->u.pci.intx = intx;
> - }
> - else if ( irq_type == PT_IRQ_TYPE_ISA )
> + case PT_IRQ_TYPE_ISA:
> bind->u.isa.isa_irq = isa_irq;
> -
> + break;
> + default:
> + errno = EINVAL;
> + return -1;
> + }
> +
> rc = do_domctl(xch, &domctl);
> return rc;
> }
> @@ -1737,11 +1742,22 @@ int xc_domain_unbind_pt_irq(
> bind->hvm_domid = domid;
> bind->irq_type = irq_type;
> bind->machine_irq = machine_irq;
> - bind->u.pci.bus = bus;
> - bind->u.pci.device = device;
> - bind->u.pci.intx = intx;
> - bind->u.isa.isa_irq = isa_irq;
> -
> + switch ( irq_type )
> + {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> + bind->u.pci.bus = bus;
> + bind->u.pci.device = device;
> + bind->u.pci.intx = intx;
> + break;
> + case PT_IRQ_TYPE_ISA:
> + bind->u.isa.isa_irq = isa_irq;
> + break;
> + default:
> + errno = EINVAL;
> + return -1;
> + }
> +
> rc = do_domctl(xch, &domctl);
> return rc;
> }
> --- a/xen/arch/x86/physdev.c
> +++ b/xen/arch/x86/physdev.c
> @@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq(
> switch ( type )
> {
> case MAP_PIRQ_TYPE_GSI: {
> - struct hvm_irq_dpci *hvm_irq_dpci;
> - struct hvm_girq_dpci_mapping *girq;
> - uint32_t machine_gsi = 0;
> + const struct hvm_irq_dpci *hvm_irq_dpci;
> + unsigned int machine_gsi = 0;
>
> if ( *index < 0 || *index >= NR_HVM_IRQS ) { @@ -52,6 +51,8 @@
> static int physdev_hvm_map_pirq( hvm_irq_dpci =
> domain_get_irq_dpci(d); if ( hvm_irq_dpci ) {
> + const struct hvm_girq_dpci_mapping *girq;
> +
> BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS);
> list_for_each_entry ( girq,
> &hvm_irq_dpci->girq[*index],
> --- a/xen/drivers/passthrough/io.c
> +++ b/xen/drivers/passthrough/io.c
> @@ -51,11 +51,8 @@ static int pt_irq_guest_eoi(struct domai static
> void pt_irq_time_out(void *data) {
> struct hvm_pirq_dpci *irq_map = data;
> - unsigned int guest_gsi;
> - struct hvm_irq_dpci *dpci = NULL;
> - struct dev_intx_gsi_link *digl;
> - struct hvm_girq_dpci_mapping *girq;
> - uint32_t device, intx;
> + const struct hvm_irq_dpci *dpci;
> + const struct dev_intx_gsi_link *digl;
>
> spin_lock(&irq_map->dom->event_lock);
> @@ -63,16 +60,16 @@ static void pt_irq_time_out(void *data)
> ASSERT(dpci);
> list_for_each_entry ( digl, &irq_map->digl_list, list )
> {
> - guest_gsi = digl->gsi;
> + unsigned int guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx);
> + const struct hvm_girq_dpci_mapping *girq;
> +
> list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
> {
> struct pirq *pirq = pirq_info(irq_map->dom,
> girq->machine_gsi);
>
> pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
> }
> - device = digl->device;
> - intx = digl->intx;
> - hvm_pci_intx_deassert(irq_map->dom, device, intx);
> + hvm_pci_intx_deassert(irq_map->dom, digl->device,
> + digl->intx);
> }
>
> pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL); @@ -96,13
> +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp int
> +pt_irq_create_bind(
> struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) {
> - struct hvm_irq_dpci *hvm_irq_dpci = NULL;
> + struct hvm_irq_dpci *hvm_irq_dpci;
> struct hvm_pirq_dpci *pirq_dpci;
> struct pirq *info;
> - uint32_t guest_gsi;
> - uint32_t device, intx, link;
> - struct dev_intx_gsi_link *digl;
> - struct hvm_girq_dpci_mapping *girq;
> int rc, pirq = pt_irq_bind->machine_irq;
>
> if ( pirq < 0 || pirq >= d->nr_pirqs ) @@ -113,6 +106,8 @@ int
> pt_irq_create_bind( hvm_irq_dpci = domain_get_irq_dpci(d); if (
> hvm_irq_dpci == NULL ) {
> + unsigned int i;
> +
> hvm_irq_dpci = xzalloc(struct hvm_irq_dpci); if ( hvm_irq_dpci
> == NULL ) { @@ -122,7 +117,7 @@ int pt_irq_create_bind(
> softirq_tasklet_init(
> &hvm_irq_dpci->dirq_tasklet,
> hvm_dirq_assist, (unsigned long)d);
> - for ( int i = 0; i < NR_HVM_IRQS; i++ )
> + for ( i = 0; i < NR_HVM_IRQS; i++ )
> INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]);
> d->arch.hvm_domain.irq.dpci = hvm_irq_dpci; @@ -136,7 +131,9
> @@ int pt_irq_create_bind(
> }
> pirq_dpci = pirq_dpci(info);
> - if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
> + switch ( pt_irq_bind->irq_type )
> + {
> + case PT_IRQ_TYPE_MSI:
> {
> uint8_t dest, dest_mode; int dest_vcpu_id; @@ -169,15 +166,16
> @@ int pt_irq_create_bind( {
> uint32_t mask = HVM_IRQ_DPCI_MACH_MSI |
> HVM_IRQ_DPCI_GUEST_MSI;
>
> - if ( (pirq_dpci->flags & mask) != mask)
> + if ( (pirq_dpci->flags & mask) != mask )
> {
> - spin_unlock(&d->event_lock);
> - return -EBUSY;
> + spin_unlock(&d->event_lock);
> + return -EBUSY;
> }
> - /* if pirq is already mapped as vmsi, update the guest
> data/addr */
> + /* If pirq is already mapped as vmsi, update guest
> + data/addr. */
> if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
> - pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
> + pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags )
> + {
> /* Directly clear pending EOIs before enabling new MSI
> info. */ pirq_guest_eoi(info); @@ -185,7 +183,7 @@
> int pt_irq_create_bind(
> pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
> }
> }
> - /* Caculate dest_vcpu_id for MSI-type pirq migration */
> + /* Calculate dest_vcpu_id for MSI-type pirq migration. */
> dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK; dest_mode =
> !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK); dest_vcpu_id =
> hvm_girq_dest_2_vcpu_id(d, dest, dest_mode); @@ -193,36 +191,37
> @@ int pt_irq_create_bind( spin_unlock(&d->event_lock); if (
> dest_vcpu_id >= 0 )
> hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
> + break;
> }
> - else
> +
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> {
> - device = pt_irq_bind->u.pci.device;
> - intx = pt_irq_bind->u.pci.intx;
> - guest_gsi = hvm_pci_intx_gsi(device, intx);
> - link = hvm_pci_intx_link(device, intx);
> - hvm_irq_dpci->link_cnt[link]++;
> + unsigned int bus = pt_irq_bind->u.pci.bus;
> + unsigned int device = pt_irq_bind->u.pci.device;
> + unsigned int intx = pt_irq_bind->u.pci.intx;
> + unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
> + unsigned int link = hvm_pci_intx_link(device, intx);
> + struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link);
> + struct hvm_girq_dpci_mapping *girq =
> + xmalloc(struct hvm_girq_dpci_mapping);
>
> - digl = xmalloc(struct dev_intx_gsi_link);
> - if ( !digl )
> + if ( !digl || !girq )
> {
> spin_unlock(&d->event_lock);
> - return -ENOMEM;
> - }
> -
> - girq = xmalloc(struct hvm_girq_dpci_mapping);
> - if ( !girq )
> - {
> + xfree(girq);
> xfree(digl); - spin_unlock(&d->event_lock);
> return -ENOMEM;
> }
> + hvm_irq_dpci->link_cnt[link]++;
> +
> + digl->bus = bus;
> digl->device = device;
> digl->intx = intx;
> - digl->gsi = guest_gsi;
> - digl->link = link;
> list_add_tail(&digl->list, &pirq_dpci->digl_list);
> + girq->bus = bus;
> girq->device = device;
> girq->intx = intx;
> girq->machine_gsi = pirq;
> @@ -261,12 +260,12 @@ int pt_irq_create_bind(
> kill_timer(&pirq_dpci->timer);
> pirq_dpci->dom = NULL; list_del(&girq->list); -
> xfree(girq); list_del(&digl->list);
> hvm_irq_dpci->link_cnt[link]--; pirq_dpci->flags = 0;
> pirq_cleanup_check(info, d);
> spin_unlock(&d->event_lock); +
> xfree(girq); xfree(digl); return rc;
> }
> @@ -276,33 +275,51 @@ int pt_irq_create_bind(
>
> if ( iommu_verbose )
> dprintk(XENLOG_G_INFO,
> - "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
> - d->domain_id, pirq, guest_gsi, device, intx); +
> "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u
> intx=%u\n", + d->domain_id, pirq, guest_gsi, bus, +
> PCI_SLOT(device), PCI_FUNC(device), intx); +
> break;
> }
> +
> + default:
> + spin_unlock(&d->event_lock);
> + return -EOPNOTSUPP;
> + }
> +
> return 0;
> }
>
> int pt_irq_destroy_bind(
> struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) {
> - struct hvm_irq_dpci *hvm_irq_dpci = NULL;
> + struct hvm_irq_dpci *hvm_irq_dpci;
> struct hvm_pirq_dpci *pirq_dpci;
> - uint32_t machine_gsi, guest_gsi;
> - uint32_t device, intx, link;
> + unsigned int machine_gsi = pt_irq_bind->machine_irq;
> + unsigned int bus = pt_irq_bind->u.pci.bus;
> + unsigned int device = pt_irq_bind->u.pci.device;
> + unsigned int intx = pt_irq_bind->u.pci.intx;
> + unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
> + unsigned int link = hvm_pci_intx_link(device, intx);
> struct dev_intx_gsi_link *digl, *tmp;
> struct hvm_girq_dpci_mapping *girq;
> struct pirq *pirq;
> - machine_gsi = pt_irq_bind->machine_irq;
> - device = pt_irq_bind->u.pci.device;
> - intx = pt_irq_bind->u.pci.intx;
> - guest_gsi = hvm_pci_intx_gsi(device, intx);
> - link = hvm_pci_intx_link(device, intx);
> + switch ( pt_irq_bind->irq_type )
> + {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> + break;
> + case PT_IRQ_TYPE_MSI:
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
>
> if ( iommu_verbose )
> dprintk(XENLOG_G_INFO,
> - "d%d: unbind: m_gsi=%u g_gsi=%u device=%u intx=%u\n", -
> d->domain_id, machine_gsi, guest_gsi, device, intx); +
> "d%d: unbind: m_gsi=%u g_gsi=%u dev=%02x:%02x.%u
> intx=%u\n",
> + d->domain_id, machine_gsi, guest_gsi, bus, +
> PCI_SLOT(device), PCI_FUNC(device), intx);
>
> spin_lock(&d->event_lock);
> @@ -314,18 +331,28 @@ int pt_irq_destroy_bind(
> return -EINVAL;
> }
> - hvm_irq_dpci->link_cnt[link]--;
> -
> list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
> {
> - if ( girq->machine_gsi == machine_gsi )
> + if ( girq->bus == bus &&
> + girq->device == device &&
> + girq->intx == intx &&
> + girq->machine_gsi == machine_gsi )
> {
> - list_del(&girq->list);
> - xfree(girq);
> - break;
> + list_del(&girq->list);
> + xfree(girq);
> + girq = NULL;
> + break;
> }
> }
> + if ( girq )
> + {
> + spin_unlock(&d->event_lock);
> + return -EINVAL;
> + }
> +
> + hvm_irq_dpci->link_cnt[link]--;
> +
> pirq = pirq_info(d, machine_gsi);
> pirq_dpci = pirq_dpci(pirq);
> @@ -334,10 +361,9 @@ int pt_irq_destroy_bind(
> {
> list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
> {
> - if ( digl->device == device &&
> - digl->intx == intx &&
> - digl->link == link &&
> - digl->gsi == guest_gsi )
> + if ( digl->bus == bus &&
> + digl->device == device &&
> + digl->intx == intx )
> {
> list_del(&digl->list);
> xfree(digl);
> @@ -359,8 +385,9 @@ int pt_irq_destroy_bind(
>
> if ( iommu_verbose )
> dprintk(XENLOG_G_INFO,
> - "d%d unmap: m_irq=%u device=%u intx=%u\n",
> - d->domain_id, machine_gsi, device, intx);
> + "d%d unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n",
> + d->domain_id, machine_gsi, bus,
> + PCI_SLOT(device), PCI_FUNC(device), intx);
>
> return 0;
> }
> @@ -481,11 +508,10 @@ static void hvm_pci_msi_assert( static int
> _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci,
> void *arg) {
> - uint32_t device, intx;
> - struct dev_intx_gsi_link *digl;
> -
> if ( test_and_clear_bool(pirq_dpci->masked) )
> {
> + const struct dev_intx_gsi_link *digl;
> +
> if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
> {
> hvm_pci_msi_assert(d, pirq_dpci); @@ -496,12 +522,10 @@
> static int _hvm_dirq_assist(struct domai
> {
> struct pirq *info = dpci_pirq(pirq_dpci);
> - device = digl->device;
> - intx = digl->intx;
> if ( hvm_domain_use_pirq(d, info) )
> send_guest_pirq(d, info);
> else
> - hvm_pci_intx_assert(d, device, intx);
> + hvm_pci_intx_assert(d, digl->device, digl->intx);
> pirq_dpci->pending++;
>
> if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE ) @@
> -537,16 +561,13 @@ static void hvm_dirq_assist(unsigned lon }
>
> static void __hvm_dpci_eoi(struct domain *d,
> - struct hvm_girq_dpci_mapping *girq,
> - union vioapic_redir_entry *ent)
> + const struct hvm_girq_dpci_mapping *girq,
> + const union vioapic_redir_entry *ent)
> {
> - uint32_t device, intx;
> struct pirq *pirq;
> struct hvm_pirq_dpci *pirq_dpci;
> - device = girq->device;
> - intx = girq->intx;
> - hvm_pci_intx_deassert(d, device, intx);
> + hvm_pci_intx_deassert(d, girq->device, girq->intx);
>
> pirq = pirq_info(d, girq->machine_gsi);
> pirq_dpci = pirq_dpci(pirq);
> @@ -556,8 +577,8 @@ static void __hvm_dpci_eoi(struct domain
> * since interrupt is still not EOIed
> */
> if ( --pirq_dpci->pending ||
> - ( ent && ent->fields.mask ) ||
> - ! pt_irq_need_timer(pirq_dpci->flags) )
> + (ent && ent->fields.mask) ||
> + !pt_irq_need_timer(pirq_dpci->flags) )
> return;
> stop_timer(&pirq_dpci->timer);
> @@ -565,10 +586,10 @@ static void __hvm_dpci_eoi(struct domain }
>
> void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
> - union vioapic_redir_entry *ent)
> + const union vioapic_redir_entry *ent)
> {
> - struct hvm_irq_dpci *hvm_irq_dpci;
> - struct hvm_girq_dpci_mapping *girq;
> + const struct hvm_irq_dpci *hvm_irq_dpci;
> + const struct hvm_girq_dpci_mapping *girq;
>
> if ( !iommu_enabled )
> return;
> --- a/xen/drivers/passthrough/vtd/x86/vtd.c
> +++ b/xen/drivers/passthrough/vtd/x86/vtd.c
> @@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d {
> struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
> unsigned int isairq = (long)arg;
> - struct dev_intx_gsi_link *digl, *tmp;
> + const struct dev_intx_gsi_link *digl;
>
> - list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
> + list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
> {
> - if ( hvm_irq->pci_link.route[digl->link] == isairq )
> + unsigned int link = hvm_pci_intx_link(digl->device,
> + digl->intx);
> +
> + if ( hvm_irq->pci_link.route[link] == isairq )
> {
> hvm_pci_intx_deassert(d, digl->device, digl->intx);
> if ( --pirq_dpci->pending == 0 )
> --- a/xen/include/asm-x86/hvm/io.h
> +++ b/xen/include/asm-x86/hvm/io.h
> @@ -123,7 +123,7 @@ int handle_pio(uint16_t port, unsigned i void
> hvm_interrupt_post(struct vcpu *v, int vector, int type); void
> hvm_io_assist(ioreq_t *p); void hvm_dpci_eoi(struct domain *d,
> unsigned int guest_irq,
> - union vioapic_redir_entry *ent);
> + const union vioapic_redir_entry *ent);
> void msix_write_completion(struct vcpu *);
>
> struct hvm_hw_stdvga {
> --- a/xen/include/xen/hvm/irq.h
> +++ b/xen/include/xen/hvm/irq.h
> @@ -30,10 +30,9 @@
>
> struct dev_intx_gsi_link {
> struct list_head list; + uint8_t bus; uint8_t device; uint8_t
> intx;
> - uint8_t gsi;
> - uint8_t link;
> };
>
> #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
> @@ -69,6 +68,7 @@ struct hvm_gmsi_info {
>
> struct hvm_girq_dpci_mapping {
> struct list_head list; + uint8_t bus; uint8_t device; uint8_t
> intx; uint8_t machine_gsi;
Best regards,
Yang
^ permalink raw reply [flat|nested] 12+ messages in thread
* Ping [tools]: [PATCH v2 3/3] pt-irq fixes and improvements
2014-06-04 8:24 ` [PATCH v2 " Jan Beulich
2014-06-10 0:32 ` Zhang, Yang Z
@ 2014-06-11 12:32 ` Jan Beulich
2014-06-11 16:54 ` Ian Campbell
2014-06-12 9:02 ` Ian Campbell
2 siblings, 1 reply; 12+ messages in thread
From: Jan Beulich @ 2014-06-11 12:32 UTC (permalink / raw)
To: Stefano Stabellini, Ian Campbell, Ian Jackson
Cc: Yang Z Zhang, Andrew Cooper, Kevin Tian, Keir Fraser, xen-devel
>>> On 04.06.14 at 10:24, <JBeulich@suse.com> wrote:
> Tools side:
> - don't silently ignore unrecognized PT_IRQ_TYPE_* values
> - respect that the interface type contains a union, making the code at
> once no longer depend on the hypervisor ignoring the bus field of the
> PCI portion of the interface structure)
This part is still awaiting a tools maintainer's opinion.
Thanks, Jan
> Hypervisor side:
> - don't ignore the PCI bus number passed in
> - don't store values (gsi, link) calculated from other stored values
> - avoid calling xfree() with a spin lock held where easily possible
> - have pt_irq_destroy_bind() respect the passed in type
> - scope reduction and constification of various variables
> - use switch instead of if/else-if chains
> - formatting
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> v2: A few extra coding style corrections according to Andrew's
> suggestions.
>
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -1702,16 +1702,21 @@ int xc_domain_bind_pt_irq(
> bind->hvm_domid = domid;
> bind->irq_type = irq_type;
> bind->machine_irq = machine_irq;
> - if ( irq_type == PT_IRQ_TYPE_PCI ||
> - irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
> + switch ( irq_type )
> {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> bind->u.pci.bus = bus;
> - bind->u.pci.device = device;
> + bind->u.pci.device = device;
> bind->u.pci.intx = intx;
> - }
> - else if ( irq_type == PT_IRQ_TYPE_ISA )
> + case PT_IRQ_TYPE_ISA:
> bind->u.isa.isa_irq = isa_irq;
> -
> + break;
> + default:
> + errno = EINVAL;
> + return -1;
> + }
> +
> rc = do_domctl(xch, &domctl);
> return rc;
> }
> @@ -1737,11 +1742,22 @@ int xc_domain_unbind_pt_irq(
> bind->hvm_domid = domid;
> bind->irq_type = irq_type;
> bind->machine_irq = machine_irq;
> - bind->u.pci.bus = bus;
> - bind->u.pci.device = device;
> - bind->u.pci.intx = intx;
> - bind->u.isa.isa_irq = isa_irq;
> -
> + switch ( irq_type )
> + {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> + bind->u.pci.bus = bus;
> + bind->u.pci.device = device;
> + bind->u.pci.intx = intx;
> + break;
> + case PT_IRQ_TYPE_ISA:
> + bind->u.isa.isa_irq = isa_irq;
> + break;
> + default:
> + errno = EINVAL;
> + return -1;
> + }
> +
> rc = do_domctl(xch, &domctl);
> return rc;
> }
> --- a/xen/arch/x86/physdev.c
> +++ b/xen/arch/x86/physdev.c
> @@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq(
> switch ( type )
> {
> case MAP_PIRQ_TYPE_GSI: {
> - struct hvm_irq_dpci *hvm_irq_dpci;
> - struct hvm_girq_dpci_mapping *girq;
> - uint32_t machine_gsi = 0;
> + const struct hvm_irq_dpci *hvm_irq_dpci;
> + unsigned int machine_gsi = 0;
>
> if ( *index < 0 || *index >= NR_HVM_IRQS )
> {
> @@ -52,6 +51,8 @@ static int physdev_hvm_map_pirq(
> hvm_irq_dpci = domain_get_irq_dpci(d);
> if ( hvm_irq_dpci )
> {
> + const struct hvm_girq_dpci_mapping *girq;
> +
> BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS);
> list_for_each_entry ( girq,
> &hvm_irq_dpci->girq[*index],
> --- a/xen/drivers/passthrough/io.c
> +++ b/xen/drivers/passthrough/io.c
> @@ -51,11 +51,8 @@ static int pt_irq_guest_eoi(struct domai
> static void pt_irq_time_out(void *data)
> {
> struct hvm_pirq_dpci *irq_map = data;
> - unsigned int guest_gsi;
> - struct hvm_irq_dpci *dpci = NULL;
> - struct dev_intx_gsi_link *digl;
> - struct hvm_girq_dpci_mapping *girq;
> - uint32_t device, intx;
> + const struct hvm_irq_dpci *dpci;
> + const struct dev_intx_gsi_link *digl;
>
> spin_lock(&irq_map->dom->event_lock);
>
> @@ -63,16 +60,16 @@ static void pt_irq_time_out(void *data)
> ASSERT(dpci);
> list_for_each_entry ( digl, &irq_map->digl_list, list )
> {
> - guest_gsi = digl->gsi;
> + unsigned int guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx);
> + const struct hvm_girq_dpci_mapping *girq;
> +
> list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
> {
> struct pirq *pirq = pirq_info(irq_map->dom, girq->machine_gsi);
>
> pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
> }
> - device = digl->device;
> - intx = digl->intx;
> - hvm_pci_intx_deassert(irq_map->dom, device, intx);
> + hvm_pci_intx_deassert(irq_map->dom, digl->device, digl->intx);
> }
>
> pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL);
> @@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp
> int pt_irq_create_bind(
> struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
> {
> - struct hvm_irq_dpci *hvm_irq_dpci = NULL;
> + struct hvm_irq_dpci *hvm_irq_dpci;
> struct hvm_pirq_dpci *pirq_dpci;
> struct pirq *info;
> - uint32_t guest_gsi;
> - uint32_t device, intx, link;
> - struct dev_intx_gsi_link *digl;
> - struct hvm_girq_dpci_mapping *girq;
> int rc, pirq = pt_irq_bind->machine_irq;
>
> if ( pirq < 0 || pirq >= d->nr_pirqs )
> @@ -113,6 +106,8 @@ int pt_irq_create_bind(
> hvm_irq_dpci = domain_get_irq_dpci(d);
> if ( hvm_irq_dpci == NULL )
> {
> + unsigned int i;
> +
> hvm_irq_dpci = xzalloc(struct hvm_irq_dpci);
> if ( hvm_irq_dpci == NULL )
> {
> @@ -122,7 +117,7 @@ int pt_irq_create_bind(
> softirq_tasklet_init(
> &hvm_irq_dpci->dirq_tasklet,
> hvm_dirq_assist, (unsigned long)d);
> - for ( int i = 0; i < NR_HVM_IRQS; i++ )
> + for ( i = 0; i < NR_HVM_IRQS; i++ )
> INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]);
>
> d->arch.hvm_domain.irq.dpci = hvm_irq_dpci;
> @@ -136,7 +131,9 @@ int pt_irq_create_bind(
> }
> pirq_dpci = pirq_dpci(info);
>
> - if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
> + switch ( pt_irq_bind->irq_type )
> + {
> + case PT_IRQ_TYPE_MSI:
> {
> uint8_t dest, dest_mode;
> int dest_vcpu_id;
> @@ -169,15 +166,16 @@ int pt_irq_create_bind(
> {
> uint32_t mask = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI;
>
> - if ( (pirq_dpci->flags & mask) != mask)
> + if ( (pirq_dpci->flags & mask) != mask )
> {
> - spin_unlock(&d->event_lock);
> - return -EBUSY;
> + spin_unlock(&d->event_lock);
> + return -EBUSY;
> }
>
> - /* if pirq is already mapped as vmsi, update the guest data/addr
> */
> + /* If pirq is already mapped as vmsi, update guest data/addr.
> */
> if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
> - pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
> + pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags )
> + {
> /* Directly clear pending EOIs before enabling new MSI
> info. */
> pirq_guest_eoi(info);
>
> @@ -185,7 +183,7 @@ int pt_irq_create_bind(
> pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
> }
> }
> - /* Caculate dest_vcpu_id for MSI-type pirq migration */
> + /* Calculate dest_vcpu_id for MSI-type pirq migration. */
> dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
> dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
> dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
> @@ -193,36 +191,37 @@ int pt_irq_create_bind(
> spin_unlock(&d->event_lock);
> if ( dest_vcpu_id >= 0 )
> hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
> + break;
> }
> - else
> +
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> {
> - device = pt_irq_bind->u.pci.device;
> - intx = pt_irq_bind->u.pci.intx;
> - guest_gsi = hvm_pci_intx_gsi(device, intx);
> - link = hvm_pci_intx_link(device, intx);
> - hvm_irq_dpci->link_cnt[link]++;
> + unsigned int bus = pt_irq_bind->u.pci.bus;
> + unsigned int device = pt_irq_bind->u.pci.device;
> + unsigned int intx = pt_irq_bind->u.pci.intx;
> + unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
> + unsigned int link = hvm_pci_intx_link(device, intx);
> + struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link);
> + struct hvm_girq_dpci_mapping *girq =
> + xmalloc(struct hvm_girq_dpci_mapping);
>
> - digl = xmalloc(struct dev_intx_gsi_link);
> - if ( !digl )
> + if ( !digl || !girq )
> {
> spin_unlock(&d->event_lock);
> - return -ENOMEM;
> - }
> -
> - girq = xmalloc(struct hvm_girq_dpci_mapping);
> - if ( !girq )
> - {
> + xfree(girq);
> xfree(digl);
> - spin_unlock(&d->event_lock);
> return -ENOMEM;
> }
>
> + hvm_irq_dpci->link_cnt[link]++;
> +
> + digl->bus = bus;
> digl->device = device;
> digl->intx = intx;
> - digl->gsi = guest_gsi;
> - digl->link = link;
> list_add_tail(&digl->list, &pirq_dpci->digl_list);
>
> + girq->bus = bus;
> girq->device = device;
> girq->intx = intx;
> girq->machine_gsi = pirq;
> @@ -261,12 +260,12 @@ int pt_irq_create_bind(
> kill_timer(&pirq_dpci->timer);
> pirq_dpci->dom = NULL;
> list_del(&girq->list);
> - xfree(girq);
> list_del(&digl->list);
> hvm_irq_dpci->link_cnt[link]--;
> pirq_dpci->flags = 0;
> pirq_cleanup_check(info, d);
> spin_unlock(&d->event_lock);
> + xfree(girq);
> xfree(digl);
> return rc;
> }
> @@ -276,33 +275,51 @@ int pt_irq_create_bind(
>
> if ( iommu_verbose )
> dprintk(XENLOG_G_INFO,
> - "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
> - d->domain_id, pirq, guest_gsi, device, intx);
> + "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u
> intx=%u\n",
> + d->domain_id, pirq, guest_gsi, bus,
> + PCI_SLOT(device), PCI_FUNC(device), intx);
> + break;
> }
> +
> + default:
> + spin_unlock(&d->event_lock);
> + return -EOPNOTSUPP;
> + }
> +
> return 0;
> }
>
> int pt_irq_destroy_bind(
> struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
> {
> - struct hvm_irq_dpci *hvm_irq_dpci = NULL;
> + struct hvm_irq_dpci *hvm_irq_dpci;
> struct hvm_pirq_dpci *pirq_dpci;
> - uint32_t machine_gsi, guest_gsi;
> - uint32_t device, intx, link;
> + unsigned int machine_gsi = pt_irq_bind->machine_irq;
> + unsigned int bus = pt_irq_bind->u.pci.bus;
> + unsigned int device = pt_irq_bind->u.pci.device;
> + unsigned int intx = pt_irq_bind->u.pci.intx;
> + unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx);
> + unsigned int link = hvm_pci_intx_link(device, intx);
> struct dev_intx_gsi_link *digl, *tmp;
> struct hvm_girq_dpci_mapping *girq;
> struct pirq *pirq;
>
> - machine_gsi = pt_irq_bind->machine_irq;
> - device = pt_irq_bind->u.pci.device;
> - intx = pt_irq_bind->u.pci.intx;
> - guest_gsi = hvm_pci_intx_gsi(device, intx);
> - link = hvm_pci_intx_link(device, intx);
> + switch ( pt_irq_bind->irq_type )
> + {
> + case PT_IRQ_TYPE_PCI:
> + case PT_IRQ_TYPE_MSI_TRANSLATE:
> + break;
> + case PT_IRQ_TYPE_MSI:
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
>
> if ( iommu_verbose )
> dprintk(XENLOG_G_INFO,
> - "d%d: unbind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
> - d->domain_id, machine_gsi, guest_gsi, device, intx);
> + "d%d: unbind: m_gsi=%u g_gsi=%u dev=%02x:%02x.%u
> intx=%u\n",
> + d->domain_id, machine_gsi, guest_gsi, bus,
> + PCI_SLOT(device), PCI_FUNC(device), intx);
>
> spin_lock(&d->event_lock);
>
> @@ -314,18 +331,28 @@ int pt_irq_destroy_bind(
> return -EINVAL;
> }
>
> - hvm_irq_dpci->link_cnt[link]--;
> -
> list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
> {
> - if ( girq->machine_gsi == machine_gsi )
> + if ( girq->bus == bus &&
> + girq->device == device &&
> + girq->intx == intx &&
> + girq->machine_gsi == machine_gsi )
> {
> - list_del(&girq->list);
> - xfree(girq);
> - break;
> + list_del(&girq->list);
> + xfree(girq);
> + girq = NULL;
> + break;
> }
> }
>
> + if ( girq )
> + {
> + spin_unlock(&d->event_lock);
> + return -EINVAL;
> + }
> +
> + hvm_irq_dpci->link_cnt[link]--;
> +
> pirq = pirq_info(d, machine_gsi);
> pirq_dpci = pirq_dpci(pirq);
>
> @@ -334,10 +361,9 @@ int pt_irq_destroy_bind(
> {
> list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
> {
> - if ( digl->device == device &&
> - digl->intx == intx &&
> - digl->link == link &&
> - digl->gsi == guest_gsi )
> + if ( digl->bus == bus &&
> + digl->device == device &&
> + digl->intx == intx )
> {
> list_del(&digl->list);
> xfree(digl);
> @@ -359,8 +385,9 @@ int pt_irq_destroy_bind(
>
> if ( iommu_verbose )
> dprintk(XENLOG_G_INFO,
> - "d%d unmap: m_irq=%u device=%u intx=%u\n",
> - d->domain_id, machine_gsi, device, intx);
> + "d%d unmap: m_irq=%u dev=%02x:%02x.%u intx=%u\n",
> + d->domain_id, machine_gsi, bus,
> + PCI_SLOT(device), PCI_FUNC(device), intx);
>
> return 0;
> }
> @@ -481,11 +508,10 @@ static void hvm_pci_msi_assert(
> static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci
> *pirq_dpci,
> void *arg)
> {
> - uint32_t device, intx;
> - struct dev_intx_gsi_link *digl;
> -
> if ( test_and_clear_bool(pirq_dpci->masked) )
> {
> + const struct dev_intx_gsi_link *digl;
> +
> if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
> {
> hvm_pci_msi_assert(d, pirq_dpci);
> @@ -496,12 +522,10 @@ static int _hvm_dirq_assist(struct domai
> {
> struct pirq *info = dpci_pirq(pirq_dpci);
>
> - device = digl->device;
> - intx = digl->intx;
> if ( hvm_domain_use_pirq(d, info) )
> send_guest_pirq(d, info);
> else
> - hvm_pci_intx_assert(d, device, intx);
> + hvm_pci_intx_assert(d, digl->device, digl->intx);
> pirq_dpci->pending++;
>
> if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
> @@ -537,16 +561,13 @@ static void hvm_dirq_assist(unsigned lon
> }
>
> static void __hvm_dpci_eoi(struct domain *d,
> - struct hvm_girq_dpci_mapping *girq,
> - union vioapic_redir_entry *ent)
> + const struct hvm_girq_dpci_mapping *girq,
> + const union vioapic_redir_entry *ent)
> {
> - uint32_t device, intx;
> struct pirq *pirq;
> struct hvm_pirq_dpci *pirq_dpci;
>
> - device = girq->device;
> - intx = girq->intx;
> - hvm_pci_intx_deassert(d, device, intx);
> + hvm_pci_intx_deassert(d, girq->device, girq->intx);
>
> pirq = pirq_info(d, girq->machine_gsi);
> pirq_dpci = pirq_dpci(pirq);
> @@ -556,8 +577,8 @@ static void __hvm_dpci_eoi(struct domain
> * since interrupt is still not EOIed
> */
> if ( --pirq_dpci->pending ||
> - ( ent && ent->fields.mask ) ||
> - ! pt_irq_need_timer(pirq_dpci->flags) )
> + (ent && ent->fields.mask) ||
> + !pt_irq_need_timer(pirq_dpci->flags) )
> return;
>
> stop_timer(&pirq_dpci->timer);
> @@ -565,10 +586,10 @@ static void __hvm_dpci_eoi(struct domain
> }
>
> void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
> - union vioapic_redir_entry *ent)
> + const union vioapic_redir_entry *ent)
> {
> - struct hvm_irq_dpci *hvm_irq_dpci;
> - struct hvm_girq_dpci_mapping *girq;
> + const struct hvm_irq_dpci *hvm_irq_dpci;
> + const struct hvm_girq_dpci_mapping *girq;
>
> if ( !iommu_enabled )
> return;
> --- a/xen/drivers/passthrough/vtd/x86/vtd.c
> +++ b/xen/drivers/passthrough/vtd/x86/vtd.c
> @@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d
> {
> struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
> unsigned int isairq = (long)arg;
> - struct dev_intx_gsi_link *digl, *tmp;
> + const struct dev_intx_gsi_link *digl;
>
> - list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
> + list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
> {
> - if ( hvm_irq->pci_link.route[digl->link] == isairq )
> + unsigned int link = hvm_pci_intx_link(digl->device, digl->intx);
> +
> + if ( hvm_irq->pci_link.route[link] == isairq )
> {
> hvm_pci_intx_deassert(d, digl->device, digl->intx);
> if ( --pirq_dpci->pending == 0 )
> --- a/xen/include/asm-x86/hvm/io.h
> +++ b/xen/include/asm-x86/hvm/io.h
> @@ -123,7 +123,7 @@ int handle_pio(uint16_t port, unsigned i
> void hvm_interrupt_post(struct vcpu *v, int vector, int type);
> void hvm_io_assist(ioreq_t *p);
> void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq,
> - union vioapic_redir_entry *ent);
> + const union vioapic_redir_entry *ent);
> void msix_write_completion(struct vcpu *);
>
> struct hvm_hw_stdvga {
> --- a/xen/include/xen/hvm/irq.h
> +++ b/xen/include/xen/hvm/irq.h
> @@ -30,10 +30,9 @@
>
> struct dev_intx_gsi_link {
> struct list_head list;
> + uint8_t bus;
> uint8_t device;
> uint8_t intx;
> - uint8_t gsi;
> - uint8_t link;
> };
>
> #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0
> @@ -69,6 +68,7 @@ struct hvm_gmsi_info {
>
> struct hvm_girq_dpci_mapping {
> struct list_head list;
> + uint8_t bus;
> uint8_t device;
> uint8_t intx;
> uint8_t machine_gsi;
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Ping [tools]: [PATCH v2 3/3] pt-irq fixes and improvements
2014-06-11 12:32 ` Ping [tools]: " Jan Beulich
@ 2014-06-11 16:54 ` Ian Campbell
0 siblings, 0 replies; 12+ messages in thread
From: Ian Campbell @ 2014-06-11 16:54 UTC (permalink / raw)
To: Jan Beulich
Cc: Kevin Tian, Keir Fraser, Andrew Cooper, Ian Jackson,
Stefano Stabellini, Yang Z Zhang, xen-devel
On Wed, 2014-06-11 at 13:32 +0100, Jan Beulich wrote:
> >>> On 04.06.14 at 10:24, <JBeulich@suse.com> wrote:
> > Tools side:
> > - don't silently ignore unrecognized PT_IRQ_TYPE_* values
> > - respect that the interface type contains a union, making the code at
> > once no longer depend on the hypervisor ignoring the bus field of the
> > PCI portion of the interface structure)
>
> This part is still awaiting a tools maintainer's opinion.
Sorry, I missed that there was a tools bit here. I've moved it into my
queue folder and will look at it ASAP.
Ian.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 3/3] pt-irq fixes and improvements
2014-06-04 8:24 ` [PATCH v2 " Jan Beulich
2014-06-10 0:32 ` Zhang, Yang Z
2014-06-11 12:32 ` Ping [tools]: " Jan Beulich
@ 2014-06-12 9:02 ` Ian Campbell
2 siblings, 0 replies; 12+ messages in thread
From: Ian Campbell @ 2014-06-12 9:02 UTC (permalink / raw)
To: Jan Beulich
Cc: Kevin Tian, Keir Fraser, Andrew Cooper, Ian Jackson,
Stefano Stabellini, Yang Z Zhang, xen-devel
On Wed, 2014-06-04 at 09:24 +0100, Jan Beulich wrote:
> Tools side:
> - don't silently ignore unrecognized PT_IRQ_TYPE_* values
> - respect that the interface type contains a union, making the code at
> once no longer depend on the hypervisor ignoring the bus field of the
> PCI portion of the interface structure)
>
> Hypervisor side:
> - don't ignore the PCI bus number passed in
> - don't store values (gsi, link) calculated from other stored values
> - avoid calling xfree() with a spin lock held where easily possible
> - have pt_irq_destroy_bind() respect the passed in type
> - scope reduction and constification of various variables
> - use switch instead of if/else-if chains
> - formatting
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Toosl:
Acked-by: Ian Campbell <ian.campbell@citrix.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-06-12 9:02 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-03 13:52 [PATCH 0/3] XSA-96 follow-ups Jan Beulich
2014-06-03 13:58 ` [PATCH 1/3] x86/HVM: properly propagate errors from HVMOP_inject_msi Jan Beulich
2014-06-03 14:05 ` Andrew Cooper
2014-06-03 13:59 ` [PATCH 2/3] x86/HVM: make vmsi_deliver() return proper error values Jan Beulich
2014-06-03 14:13 ` Andrew Cooper
2014-06-03 14:00 ` [PATCH 3/3] pt-irq fixes and improvements Jan Beulich
2014-06-03 14:50 ` Andrew Cooper
2014-06-04 8:24 ` [PATCH v2 " Jan Beulich
2014-06-10 0:32 ` Zhang, Yang Z
2014-06-11 12:32 ` Ping [tools]: " Jan Beulich
2014-06-11 16:54 ` Ian Campbell
2014-06-12 9:02 ` Ian Campbell
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.