# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1191340747 -3600
# Node ID c2871913c5c2c09e54169ce86af73ec1314554d9
# Parent e1b574bc36b5068baf0053da32f8ca11a907625a
vtd: Dynamically allocate IRQ-tracking structures, only for those
domains that actually have PCI-passthru devices. Greatly reduces size
of 'struct domain'.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/vmx/intr.c | 21 ++++++----
xen/arch/x86/hvm/vmx/vtd/io.c | 83 ++++++++++++++++++++++++++----------------
xen/include/asm-x86/hvm/irq.h | 16 +++++---
3 files changed, 74 insertions(+), 46 deletions(-)
diff -r e1b574bc36b5 -r c2871913c5c2 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c Tue Oct 02 16:28:58 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/intr.c Tue Oct 02 16:59:07 2007 +0100
@@ -107,19 +107,23 @@ static void enable_intr_window(struct vc
}
}
-static void vmx_dirq_assist(struct domain *d)
+static void vmx_dirq_assist(struct vcpu *v)
{
unsigned int irq;
uint32_t device, intx;
- struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+ struct domain *d = v->domain;
+ struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
- for ( irq = find_first_bit(hvm_irq->dirq_mask, NR_IRQS);
+ if ( !vtd_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) )
+ return;
+
+ for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS);
irq < NR_IRQS;
- irq = find_next_bit(hvm_irq->dirq_mask, NR_IRQS, irq + 1) )
+ irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) )
{
- test_and_clear_bit(irq, &hvm_irq->dirq_mask);
- device = hvm_irq->mirq[irq].device;
- intx = hvm_irq->mirq[irq].intx;
+ test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask);
+ device = hvm_irq_dpci->mirq[irq].device;
+ intx = hvm_irq_dpci->mirq[irq].intx;
hvm_pci_intx_assert(d, device, intx);
}
}
@@ -134,8 +138,7 @@ asmlinkage void vmx_intr_assist(void)
/* Crank the handle on interrupt state. */
pt_update_irq(v);
- if ( vtd_enabled && (v->vcpu_id == 0) )
- vmx_dirq_assist(v->domain);
+ vmx_dirq_assist(v);
hvm_set_callback_irq_level();
diff -r e1b574bc36b5 -r c2871913c5c2 xen/arch/x86/hvm/vmx/vtd/io.c
--- a/xen/arch/x86/hvm/vmx/vtd/io.c Tue Oct 02 16:28:58 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/io.c Tue Oct 02 16:59:07 2007 +0100
@@ -46,27 +46,41 @@
#include <public/domctl.h>
int pt_irq_create_bind_vtd(
- struct domain *d,
- xen_domctl_bind_pt_irq_t * pt_irq_bind)
+ struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
{
- struct hvm_domain *hd = &d->arch.hvm_domain;
+ struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
uint32_t machine_gsi, guest_gsi;
uint32_t device, intx;
+
+ if ( hvm_irq_dpci == NULL )
+ {
+ hvm_irq_dpci = xmalloc(struct hvm_irq_dpci);
+ if ( hvm_irq_dpci == NULL )
+ return -ENOMEM;
+
+ memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
+
+ if ( cmpxchg((unsigned long *)&d->arch.hvm_domain.irq.dpci,
+ 0, (unsigned long)hvm_irq_dpci) != 0 )
+ xfree(hvm_irq_dpci);
+
+ hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+ }
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);
- hd->irq.mirq[machine_gsi].valid = 1;
- hd->irq.mirq[machine_gsi].device = device;
- hd->irq.mirq[machine_gsi].intx = intx;
- hd->irq.mirq[machine_gsi].guest_gsi = guest_gsi;
+ hvm_irq_dpci->mirq[machine_gsi].valid = 1;
+ hvm_irq_dpci->mirq[machine_gsi].device = device;
+ hvm_irq_dpci->mirq[machine_gsi].intx = intx;
+ hvm_irq_dpci->mirq[machine_gsi].guest_gsi = guest_gsi;
- hd->irq.girq[guest_gsi].valid = 1;
- hd->irq.girq[guest_gsi].device = device;
- hd->irq.girq[guest_gsi].intx = intx;
- hd->irq.girq[guest_gsi].machine_gsi = machine_gsi;
+ hvm_irq_dpci->girq[guest_gsi].valid = 1;
+ hvm_irq_dpci->girq[guest_gsi].device = device;
+ hvm_irq_dpci->girq[guest_gsi].intx = intx;
+ hvm_irq_dpci->girq[guest_gsi].machine_gsi = machine_gsi;
/* Deal with gsi for legacy devices */
pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE);
@@ -76,31 +90,31 @@ int pt_irq_create_bind_vtd(
return 0;
}
+
int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
{
uint32_t device, intx;
uint32_t link, isa_irq;
- struct hvm_irq *hvm_irq;
+ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
- if ( !vtd_enabled || (d == dom0) ||
- !d->arch.hvm_domain.irq.mirq[mirq].valid )
+ if ( !vtd_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
+ !hvm_irq->dpci->mirq[mirq].valid )
return 0;
- device = d->arch.hvm_domain.irq.mirq[mirq].device;
- intx = d->arch.hvm_domain.irq.mirq[mirq].intx;
+ device = hvm_irq->dpci->mirq[mirq].device;
+ intx = hvm_irq->dpci->mirq[mirq].intx;
link = hvm_pci_intx_link(device, intx);
- hvm_irq = &d->arch.hvm_domain.irq;
isa_irq = hvm_irq->pci_link.route[link];
- if ( !d->arch.hvm_domain.irq.girq[isa_irq].valid )
+ if ( !hvm_irq->dpci->girq[isa_irq].valid )
{
- d->arch.hvm_domain.irq.girq[isa_irq].valid = 1;
- d->arch.hvm_domain.irq.girq[isa_irq].device = device;
- d->arch.hvm_domain.irq.girq[isa_irq].intx = intx;
- d->arch.hvm_domain.irq.girq[isa_irq].machine_gsi = mirq;
+ hvm_irq->dpci->girq[isa_irq].valid = 1;
+ hvm_irq->dpci->girq[isa_irq].device = device;
+ hvm_irq->dpci->girq[isa_irq].intx = intx;
+ hvm_irq->dpci->girq[isa_irq].machine_gsi = mirq;
}
- if ( !test_and_set_bit(mirq, d->arch.hvm_domain.irq.dirq_mask) )
+ if ( !test_and_set_bit(mirq, hvm_irq->dpci->dirq_mask) )
{
vcpu_kick(d->vcpu[0]);
return 1;
@@ -113,17 +127,19 @@ void hvm_dpci_eoi(unsigned int guest_gsi
void hvm_dpci_eoi(unsigned int guest_gsi, union vioapic_redir_entry *ent)
{
struct domain *d = current->domain;
+ struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
uint32_t device, intx, machine_gsi;
irq_desc_t *desc;
ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
- if ( !vtd_enabled || !d->arch.hvm_domain.irq.girq[guest_gsi].valid )
+ if ( !vtd_enabled || (hvm_irq_dpci == NULL) ||
+ !hvm_irq_dpci->girq[guest_gsi].valid )
return;
- device = d->arch.hvm_domain.irq.girq[guest_gsi].device;
- intx = d->arch.hvm_domain.irq.girq[guest_gsi].intx;
- machine_gsi = d->arch.hvm_domain.irq.girq[guest_gsi].machine_gsi;
+ device = hvm_irq_dpci->girq[guest_gsi].device;
+ intx = hvm_irq_dpci->girq[guest_gsi].intx;
+ machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi;
gdprintk(XENLOG_INFO, "hvm_dpci_eoi:: device %x intx %x\n",
device, intx);
__hvm_pci_intx_deassert(d, device, intx);
@@ -136,15 +152,20 @@ void hvm_dpci_eoi(unsigned int guest_gsi
void iommu_domain_destroy(struct domain *d)
{
- struct hvm_domain *hd = &d->arch.hvm_domain;
+ struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
uint32_t i;
if ( !vtd_enabled )
return;
- for ( i = 0; i < NR_IRQS; i++ )
- if ( hd->irq.mirq[i].valid )
- pirq_guest_unbind(d, i);
+ if ( hvm_irq_dpci != NULL )
+ {
+ for ( i = 0; i < NR_IRQS; i++ )
+ if ( hvm_irq_dpci->mirq[i].valid )
+ pirq_guest_unbind(d, i);
+ d->arch.hvm_domain.irq.dpci = NULL;
+ xfree(hvm_irq_dpci);
+ }
iommu_domain_teardown(d);
}
diff -r e1b574bc36b5 -r c2871913c5c2 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h Tue Oct 02 16:28:58 2007 +0100
+++ b/xen/include/asm-x86/hvm/irq.h Tue Oct 02 16:59:07 2007 +0100
@@ -29,7 +29,7 @@
#include <asm/hvm/vioapic.h>
#include <public/hvm/save.h>
-struct hvm_irq_mapping {
+struct hvm_irq_dpci_mapping {
uint8_t valid;
uint8_t device;
uint8_t intx;
@@ -37,6 +37,14 @@ struct hvm_irq_mapping {
uint8_t guest_gsi;
uint8_t machine_gsi;
};
+};
+
+struct hvm_irq_dpci {
+ /* Machine IRQ to guest device/intx mapping. */
+ struct hvm_irq_dpci_mapping mirq[NR_IRQS];
+ /* Guest IRQ to guest device/intx mapping. */
+ struct hvm_irq_dpci_mapping girq[NR_IRQS];
+ DECLARE_BITMAP(dirq_mask, NR_IRQS);
};
struct hvm_irq {
@@ -99,11 +107,7 @@ struct hvm_irq {
/* Last VCPU that was delivered a LowestPrio interrupt. */
u8 round_robin_prev_vcpu;
- /* machine irq to guest device/intx mapping */
- struct hvm_irq_mapping mirq[NR_IRQS];
- /* guest irq to guest device/intx mapping */
- struct hvm_irq_mapping girq[NR_IRQS];
- DECLARE_BITMAP(dirq_mask, NR_IRQS);
+ struct hvm_irq_dpci *dpci;
};
#define hvm_pci_intx_gsi(dev, intx) \
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|