direct-io.hg

changeset 15525:523bd000ea56

allen: restore vt-d interrupt code base on Guy Zana's request
author root@lweybridge0-64-fc6.sc.intel.com
date Tue Jul 31 12:36:34 2007 -0700 (2007-07-31)
parents 87707c785bba
children 13483c74ce04
files xen/arch/x86/hvm/io.c xen/arch/x86/hvm/vioapic.c xen/arch/x86/hvm/vmx/intr.c xen/arch/x86/hvm/vpic.c xen/arch/x86/io_apic.c xen/arch/x86/irq.c xen/include/asm-x86/hvm/irq.h
line diff
     1.1 --- a/xen/arch/x86/hvm/io.c	Mon Jul 30 13:01:51 2007 -0700
     1.2 +++ b/xen/arch/x86/hvm/io.c	Tue Jul 31 12:36:34 2007 -0700
     1.3 @@ -874,6 +874,60 @@ void hvm_io_assist(void)
     1.4      vcpu_end_shutdown_deferral(v);
     1.5  }
     1.6  
     1.7 +int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
     1.8 +{
     1.9 +    uint32_t device, intx;
    1.10 +    uint32_t link, isa_irq;
    1.11 +    struct hvm_irq *hvm_irq;
    1.12 +
    1.13 +    if ((d == dom0) || !dev_assigned(d))
    1.14 +        return 0;
    1.15 +
    1.16 +    if (d->arch.hvm_domain.irq.mirq[mirq].valid)
    1.17 +    {
    1.18 +        device = d->arch.hvm_domain.irq.mirq[mirq].device;
    1.19 +        intx = d->arch.hvm_domain.irq.mirq[mirq].intx;
    1.20 +        link = hvm_pci_intx_link(device, intx);
    1.21 +        hvm_irq = &d->arch.hvm_domain.irq;
    1.22 +        isa_irq = hvm_irq->pci_link.route[link];
    1.23 +
    1.24 +        if ( !d->arch.hvm_domain.irq.girq[isa_irq].valid )
    1.25 +        {
    1.26 +            d->arch.hvm_domain.irq.girq[isa_irq].valid = 1;
    1.27 +            d->arch.hvm_domain.irq.girq[isa_irq].device = device;
    1.28 +            d->arch.hvm_domain.irq.girq[isa_irq].intx = intx;
    1.29 +            d->arch.hvm_domain.irq.girq[isa_irq].machine_gsi = mirq;
    1.30 +        }
    1.31 +
    1.32 +        if ( !test_and_set_bit(mirq, d->arch.hvm_domain.irq.dirq_mask) )
    1.33 +        {
    1.34 +            vcpu_kick(d->vcpu[0]);
    1.35 +            return 1;
    1.36 +        }
    1.37 +        else
    1.38 +            dprintk(XENLOG_INFO, "Want to pending mirq, but failed\n");
    1.39 +    }
    1.40 +    return 0;
    1.41 +}
    1.42 +
    1.43 +void hvm_dpci_eoi(unsigned int guest_gsi)
    1.44 +{
    1.45 +    struct domain *d = current->domain;
    1.46 +    uint32_t device, intx, machine_gsi;
    1.47 +    irq_desc_t *desc;
    1.48 +
    1.49 +    if (d->arch.hvm_domain.irq.girq[guest_gsi].valid)
    1.50 +    {
    1.51 +        device = d->arch.hvm_domain.irq.girq[guest_gsi].device;
    1.52 +        intx = d->arch.hvm_domain.irq.girq[guest_gsi].intx;
    1.53 +        machine_gsi = d->arch.hvm_domain.irq.girq[guest_gsi].machine_gsi;
    1.54 +        gdprintk(XENLOG_INFO, "hvm_dpci_eoi:: device %x intx %x\n", device, intx);
    1.55 +        hvm_pci_intx_deassert(d, device, intx);
    1.56 +        desc = &irq_desc[irq_to_vector(machine_gsi)];
    1.57 +        desc->handler->end(irq_to_vector(machine_gsi));
    1.58 +    }
    1.59 +}
    1.60 +
    1.61  int dpci_ioport_intercept(ioreq_t *p, int type)
    1.62  {
    1.63      struct domain *d = current->domain;
     2.1 --- a/xen/arch/x86/hvm/vioapic.c	Mon Jul 30 13:01:51 2007 -0700
     2.2 +++ b/xen/arch/x86/hvm/vioapic.c	Tue Jul 31 12:36:34 2007 -0700
     2.3 @@ -462,6 +462,13 @@ void vioapic_update_EOI(struct domain *d
     2.4      ent = &vioapic->redirtbl[gsi];
     2.5  
     2.6      ent->fields.remote_irr = 0;
     2.7 +
     2.8 +    if (dev_assigned(d)) {
     2.9 +        spin_unlock(&d->arch.hvm_domain.irq_lock);
    2.10 +        hvm_dpci_eoi(gsi);
    2.11 +        return;
    2.12 +    }
    2.13 +
    2.14      if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
    2.15           !ent->fields.mask &&
    2.16           hvm_irq->gsi_assert_count[gsi] )
     3.1 --- a/xen/arch/x86/hvm/vmx/intr.c	Mon Jul 30 13:01:51 2007 -0700
     3.2 +++ b/xen/arch/x86/hvm/vmx/intr.c	Tue Jul 31 12:36:34 2007 -0700
     3.3 @@ -126,6 +126,27 @@ static void update_tpr_threshold(struct 
     3.4      __vmwrite(TPR_THRESHOLD, (max_irr > tpr) ? (tpr >> 4) : (max_irr >> 4));
     3.5  }
     3.6  
     3.7 +static void vmx_dirq_assist(struct domain *d)
     3.8 +{
     3.9 +    unsigned int irq;
    3.10 +    uint32_t device;
    3.11 +    uint32_t intx;
    3.12 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    3.13 +
    3.14 +    for (irq = find_first_bit(hvm_irq->dirq_mask, NR_IRQS);
    3.15 +         irq < NR_IRQS;
    3.16 +         irq = find_next_bit(hvm_irq->dirq_mask, NR_IRQS, irq + 1))
    3.17 +    {
    3.18 +        test_and_clear_bit(irq, &hvm_irq->dirq_mask);
    3.19 +
    3.20 +        device = hvm_irq->mirq[irq].device;
    3.21 +        intx = hvm_irq->mirq[irq].intx;
    3.22 +        gdprintk(XENLOG_INFO VTDPREFIX, "hvm_do_IRQ_dpci:injecting intr: device %x intx %x, irq= %x\n",
    3.23 +                 device, intx, irq);
    3.24 +        hvm_pci_intx_assert(d, device, intx);
    3.25 +    }
    3.26 +}
    3.27 +
    3.28  asmlinkage void vmx_intr_assist(void)
    3.29  {
    3.30      int intr_vector;
    3.31 @@ -136,6 +157,9 @@ asmlinkage void vmx_intr_assist(void)
    3.32  
    3.33      pt_update_irq(v);
    3.34  
    3.35 +    if ( v->vcpu_id == 0 )
    3.36 +        vmx_dirq_assist(v->domain);
    3.37 +
    3.38      hvm_set_callback_irq_level();
    3.39  
    3.40      update_tpr_threshold(vcpu_vlapic(v));
     4.1 --- a/xen/arch/x86/hvm/vpic.c	Mon Jul 30 13:01:51 2007 -0700
     4.2 +++ b/xen/arch/x86/hvm/vpic.c	Tue Jul 31 12:36:34 2007 -0700
     4.3 @@ -177,8 +177,9 @@ static int vpic_intack(struct hvm_hw_vpi
     4.4  static void vpic_ioport_write(
     4.5      struct hvm_hw_vpic *vpic, uint32_t addr, uint32_t val)
     4.6  {
     4.7 -    int priority, cmd, irq;
     4.8 +    int priority, cmd, irq = 0, pic_eoi = 0;
     4.9      uint8_t mask;
    4.10 +    uint32_t old_addr = addr;
    4.11  
    4.12      vpic_lock(vpic);
    4.13  
    4.14 @@ -250,6 +251,13 @@ static void vpic_ioport_write(
    4.15                  vpic->isr &= ~(1 << irq);
    4.16                  if ( cmd == 7 )
    4.17                      vpic->priority_add = (irq + 1) & 7;
    4.18 +                /*
    4.19 +                 * chipset register 0xa0 is i8259 EOI register
    4.20 +                 */
    4.21 +                if (( old_addr & 0xa0) == 0xa0 )
    4.22 +                    irq = irq | 0x8;
    4.23 +                if ( irq != 0 )
    4.24 +                    pic_eoi = 1;
    4.25                  break;
    4.26              case 6: /* Set Priority                */
    4.27                  vpic->priority_add = (val + 1) & 7;
    4.28 @@ -295,6 +303,12 @@ static void vpic_ioport_write(
    4.29      vpic_update_int_output(vpic);
    4.30  
    4.31      vpic_unlock(vpic);
    4.32 +
    4.33 +    if ( pic_eoi && irq != 0)
    4.34 +    {
    4.35 +        hvm_dpci_eoi(irq);
    4.36 +        pic_eoi = 0;
    4.37 +    }
    4.38  }
    4.39  
    4.40  static uint32_t vpic_ioport_read(struct hvm_hw_vpic *vpic, uint32_t addr)
     5.1 --- a/xen/arch/x86/io_apic.c	Mon Jul 30 13:01:51 2007 -0700
     5.2 +++ b/xen/arch/x86/io_apic.c	Tue Jul 31 12:36:34 2007 -0700
     5.3 @@ -187,6 +187,68 @@ static void __modify_IO_APIC_irq (unsign
     5.4      }
     5.5  }
     5.6  
     5.7 +int real_vector[MAX_IRQ_SOURCES];
     5.8 +int fake_vector=-1;
     5.9 +
    5.10 +/*
    5.11 + * Following 2 functions are used to workaround spurious interrupt
    5.12 + * problem related to mask/unmask of interrupts.  Instead we program
    5.13 + * an unused vector in the IOAPIC before issueing EOI to LAPIC.
    5.14 + */
    5.15 +static void write_fake_IO_APIC_vector (unsigned int irq)
    5.16 +{
    5.17 +    struct irq_pin_list *entry = irq_2_pin + irq;
    5.18 +    unsigned int pin, reg;
    5.19 +    unsigned long flags;
    5.20 +
    5.21 +    spin_lock_irqsave(&ioapic_lock, flags);
    5.22 +    for (;;) {
    5.23 +        pin = entry->pin;
    5.24 +        if (pin == -1)
    5.25 +            break;
    5.26 +        reg = io_apic_read(entry->apic, 0x10 + pin*2);
    5.27 +        real_vector[irq] = reg & 0xff;
    5.28 +        reg &= ~0xff;
    5.29 +
    5.30 +        if (fake_vector == -1)
    5.31 +            fake_vector = assign_irq_vector(MAX_IRQ_SOURCES-1);
    5.32 +
    5.33 +        reg |= fake_vector;
    5.34 +        io_apic_write(entry->apic, 0x10 + pin*2, reg);
    5.35 +
    5.36 +        if (!entry->next)
    5.37 +            break;
    5.38 +        entry = irq_2_pin + entry->next;
    5.39 +    }
    5.40 +    spin_unlock_irqrestore(&ioapic_lock, flags);
    5.41 +}
    5.42 +
    5.43 +static void restore_real_IO_APIC_vector (unsigned int irq)
    5.44 +{
    5.45 +    struct irq_pin_list *entry = irq_2_pin + irq;
    5.46 +    unsigned int pin, reg;
    5.47 +    unsigned long flags;
    5.48 +
    5.49 +    spin_lock_irqsave(&ioapic_lock, flags);
    5.50 +    for (;;) {
    5.51 +        pin = entry->pin;
    5.52 +        if (pin == -1)
    5.53 +            break;
    5.54 +
    5.55 +        reg = io_apic_read(entry->apic, 0x10 + pin*2);
    5.56 +        reg &= ~0xff;
    5.57 +        reg |= real_vector[irq];
    5.58 +        io_apic_write(entry->apic, 0x10 + pin*2, reg);
    5.59 +        mb();
    5.60 +        *(IO_APIC_BASE(entry->apic) + 0x10) = reg & 0xff;
    5.61 +
    5.62 +        if (!entry->next)
    5.63 +            break;
    5.64 +        entry = irq_2_pin + entry->next;
    5.65 +    }
    5.66 +    spin_unlock_irqrestore(&ioapic_lock, flags);
    5.67 +}
    5.68 +
    5.69  /* mask = 1 */
    5.70  static void __mask_IO_APIC_irq (unsigned int irq)
    5.71  {
    5.72 @@ -1359,7 +1421,7 @@ static void mask_and_ack_level_ioapic_ir
    5.73      if ( ioapic_ack_new )
    5.74          return;
    5.75  
    5.76 -    mask_IO_APIC_irq(irq);
    5.77 +    write_fake_IO_APIC_vector(irq);
    5.78  /*
    5.79   * It appears there is an erratum which affects at least version 0x11
    5.80   * of I/O APIC (that's the 82093AA and cores integrated into various
    5.81 @@ -1402,7 +1464,7 @@ static void end_level_ioapic_irq (unsign
    5.82      if ( !ioapic_ack_new )
    5.83      {
    5.84          if ( !(irq_desc[IO_APIC_VECTOR(irq)].status & IRQ_DISABLED) )
    5.85 -            unmask_IO_APIC_irq(irq);
    5.86 +            restore_real_IO_APIC_vector(irq);
    5.87          return;
    5.88      }
    5.89  
     6.1 --- a/xen/arch/x86/irq.c	Mon Jul 30 13:01:51 2007 -0700
     6.2 +++ b/xen/arch/x86/irq.c	Tue Jul 31 12:36:34 2007 -0700
     6.3 @@ -237,7 +237,8 @@ static void __do_IRQ_guest(int vector)
     6.4          if ( (action->ack_type != ACKTYPE_NONE) &&
     6.5               !test_and_set_bit(irq, d->pirq_mask) )
     6.6              action->in_flight++;
     6.7 -        send_guest_pirq(d, irq);
     6.8 +        if (!hvm_do_IRQ_dpci(d, irq))
     6.9 +            send_guest_pirq(d, irq);
    6.10      }
    6.11  }
    6.12  
     7.1 --- a/xen/include/asm-x86/hvm/irq.h	Mon Jul 30 13:01:51 2007 -0700
     7.2 +++ b/xen/include/asm-x86/hvm/irq.h	Tue Jul 31 12:36:34 2007 -0700
     7.3 @@ -103,6 +103,7 @@ struct hvm_irq {
     7.4      struct hvm_irq_mapping mirq[NR_IRQS];
     7.5      /* guest irq to guest device/intx mapping */
     7.6      struct hvm_irq_mapping girq[NR_IRQS];
     7.7 +    DECLARE_BITMAP(dirq_mask, NR_IRQS);
     7.8  };
     7.9  
    7.10  #define hvm_pci_intx_gsi(dev, intx)  \