[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vt-d: Allow pass-through of shared interrupts.
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1192789618 -3600 # Node ID e733e6b73d56e014c5b2eba04564e7ee439c2b59 # Parent bc4afcd4c612afcee7f2fa2fc0ca400c26758876 vt-d: Allow pass-through of shared interrupts. Signed-off-by: Xiaohui Xin <xiaohui.xin@xxxxxxxxx> Signed-off-by: Kevin Tian <kevin.tian@xxxxxxxxx> --- xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c | 2 xen/arch/x86/hvm/vioapic.c | 2 xen/arch/x86/hvm/vmx/intr.c | 12 +++++ xen/arch/x86/hvm/vmx/vtd/dmar.c | 8 --- xen/arch/x86/hvm/vmx/vtd/io.c | 56 ++++++++++++++++--------- xen/arch/x86/hvm/vpic.c | 3 - xen/include/asm-x86/hvm/io.h | 3 - xen/include/asm-x86/hvm/irq.h | 2 xen/include/asm-x86/iommu.h | 5 +- 9 files changed, 62 insertions(+), 31 deletions(-) diff -r bc4afcd4c612 -r e733e6b73d56 xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c --- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c Fri Oct 19 11:26:58 2007 +0100 @@ -18,10 +18,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <xen/sched.h> #include <asm/hvm/iommu.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> -#include <xen/sched.h> extern long amd_iommu_poll_comp_wait; diff -r bc4afcd4c612 -r e733e6b73d56 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/arch/x86/hvm/vioapic.c Fri Oct 19 11:26:58 2007 +0100 @@ -459,7 +459,7 @@ void vioapic_update_EOI(struct domain *d ent->fields.remote_irr = 0; if ( vtd_enabled ) - hvm_dpci_eoi(gsi, ent); + hvm_dpci_eoi(current->domain, gsi, ent); if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) && !ent->fields.mask && diff -r bc4afcd4c612 -r e733e6b73d56 xen/arch/x86/hvm/vmx/intr.c --- a/xen/arch/x86/hvm/vmx/intr.c Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/intr.c Fri Oct 19 11:26:58 2007 +0100 @@ -121,10 +121,22 @@ static void vmx_dirq_assist(struct vcpu irq < NR_IRQS; irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) ) { + stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)]); + 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); + + /* + * Set a timer to see if the guest can finish the interrupt or not. For + * example, the guest OS may unmask the PIC during boot, before the + * guest driver is loaded. hvm_pci_intx_assert() may succeed, but the + * guest will never deal with the irq, then the physical interrupt line + * will never be deasserted. + */ + set_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)], + NOW() + PT_IRQ_TIME_OUT); } } diff -r bc4afcd4c612 -r e733e6b73d56 xen/arch/x86/hvm/vmx/vtd/dmar.c --- a/xen/arch/x86/hvm/vmx/vtd/dmar.c Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/vtd/dmar.c Fri Oct 19 11:26:58 2007 +0100 @@ -492,7 +492,6 @@ acpi_parse_dmar(unsigned long phys_addr, int acpi_dmar_init(void) { - extern int ioapic_ack_new; int rc; if (!vtd_enabled) @@ -509,8 +508,5 @@ int acpi_dmar_init(void) return -ENODEV; } - /* Use fake-vector style of IOAPIC acknowledgement. */ - ioapic_ack_new = 0; - - return 0; -} + return 0; +} diff -r bc4afcd4c612 -r e733e6b73d56 xen/arch/x86/hvm/vmx/vtd/io.c --- a/xen/arch/x86/hvm/vmx/vtd/io.c Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/vtd/io.c Fri Oct 19 11:26:58 2007 +0100 @@ -45,6 +45,18 @@ #include <public/hvm/ioreq.h> #include <public/domctl.h> +static void pt_irq_time_out(void *data) +{ + struct hvm_irq_dpci_mapping *irq_map = data; + unsigned int guest_gsi, machine_gsi; + struct domain *d = irq_map->dom; + + guest_gsi = irq_map->guest_gsi; + machine_gsi = d->arch.hvm_domain.irq.dpci->girq[guest_gsi].machine_gsi; + clear_bit(machine_gsi, d->arch.hvm_domain.irq.dpci->dirq_mask); + hvm_dpci_eoi(irq_map->dom, guest_gsi, NULL); +} + int pt_irq_create_bind_vtd( struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) { @@ -76,17 +88,22 @@ int pt_irq_create_bind_vtd( 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; + hvm_irq_dpci->mirq[machine_gsi].dom = d; 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; + hvm_irq_dpci->girq[guest_gsi].dom = d; - /* Deal with gsi for legacy devices */ + init_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)], + pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0); + + /* Deal with GSI for legacy devices. */ pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE); gdprintk(XENLOG_ERR, - "XEN_DOMCTL_irq_mapping: m_irq = %x device = %x intx = %x\n", - machine_gsi, device, intx); + "XEN_DOMCTL_irq_mapping: m_irq = %x device = %x intx = %x\n", + machine_gsi, device, intx); return 0; } @@ -114,22 +131,25 @@ int hvm_do_IRQ_dpci(struct domain *d, un hvm_irq->dpci->girq[isa_irq].machine_gsi = mirq; } - if ( !test_and_set_bit(mirq, hvm_irq->dpci->dirq_mask) ) - { - vcpu_kick(d->vcpu[0]); - return 1; - } + /* + * Set a timer here to avoid situations where the IRQ line is shared, and + * the device belonging to the pass-through guest is not yet active. In + * this case the guest may not pick up the interrupt (e.g., masked at the + * PIC) and we need to detect that. + */ + set_bit(mirq, hvm_irq->dpci->dirq_mask); + set_timer(&hvm_irq->dpci->hvm_timer[irq_to_vector(mirq)], + NOW() + PT_IRQ_TIME_OUT); + vcpu_kick(d->vcpu[0]); - dprintk(XENLOG_INFO, "mirq already pending\n"); - return 0; + return 1; } -void hvm_dpci_eoi(unsigned int guest_gsi, union vioapic_redir_entry *ent) +void hvm_dpci_eoi(struct domain *d, 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)); @@ -137,17 +157,15 @@ void hvm_dpci_eoi(unsigned int guest_gsi !hvm_irq_dpci->girq[guest_gsi].valid ) return; + machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi; + stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(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); - if ( (ent == NULL) || (ent->fields.mask == 0) ) - { - desc = &irq_desc[irq_to_vector(machine_gsi)]; - desc->handler->end(irq_to_vector(machine_gsi)); - } + if ( (ent == NULL) || !ent->fields.mask ) + pirq_guest_eoi(d, machine_gsi); } void iommu_domain_destroy(struct domain *d) diff -r bc4afcd4c612 -r e733e6b73d56 xen/arch/x86/hvm/vpic.c --- a/xen/arch/x86/hvm/vpic.c Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/arch/x86/hvm/vpic.c Fri Oct 19 11:26:58 2007 +0100 @@ -252,7 +252,8 @@ static void vpic_ioport_write( if ( vtd_enabled ) { irq |= ((addr & 0xa0) == 0xa0) ? 8 : 0; - hvm_dpci_eoi(hvm_isa_irq_to_gsi(irq), NULL); + hvm_dpci_eoi(current->domain, + hvm_isa_irq_to_gsi(irq), NULL); } break; case 6: /* Set Priority */ diff -r bc4afcd4c612 -r e733e6b73d56 xen/include/asm-x86/hvm/io.h --- a/xen/include/asm-x86/hvm/io.h Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/include/asm-x86/hvm/io.h Fri Oct 19 11:26:58 2007 +0100 @@ -151,7 +151,8 @@ extern void handle_mmio(unsigned long gp extern void handle_mmio(unsigned long gpa); extern void hvm_interrupt_post(struct vcpu *v, int vector, int type); extern void hvm_io_assist(void); -extern void hvm_dpci_eoi(unsigned int guest_irq, union vioapic_redir_entry *ent); +extern void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq, + union vioapic_redir_entry *ent); #endif /* __ASM_X86_HVM_IO_H__ */ diff -r bc4afcd4c612 -r e733e6b73d56 xen/include/asm-x86/hvm/irq.h --- a/xen/include/asm-x86/hvm/irq.h Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/include/asm-x86/hvm/irq.h Fri Oct 19 11:26:58 2007 +0100 @@ -33,6 +33,7 @@ struct hvm_irq_dpci_mapping { uint8_t valid; uint8_t device; uint8_t intx; + struct domain *dom; union { uint8_t guest_gsi; uint8_t machine_gsi; @@ -45,6 +46,7 @@ struct hvm_irq_dpci { /* Guest IRQ to guest device/intx mapping. */ struct hvm_irq_dpci_mapping girq[NR_IRQS]; DECLARE_BITMAP(dirq_mask, NR_IRQS); + struct timer hvm_timer[NR_IRQS]; }; struct hvm_irq { diff -r bc4afcd4c612 -r e733e6b73d56 xen/include/asm-x86/iommu.h --- a/xen/include/asm-x86/iommu.h Fri Oct 19 09:31:03 2007 +0100 +++ b/xen/include/asm-x86/iommu.h Fri Oct 19 11:26:58 2007 +0100 @@ -79,7 +79,8 @@ int hvm_do_IRQ_dpci(struct domain *d, un int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq); int dpci_ioport_intercept(ioreq_t *p); int pt_irq_create_bind_vtd(struct domain *d, - xen_domctl_bind_pt_irq_t * pt_irq_bind); + xen_domctl_bind_pt_irq_t *pt_irq_bind); +#define PT_IRQ_TIME_OUT MILLISECS(8) -#endif // _IOMMU_H_ +#endif /* _IOMMU_H_ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |