[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86 hvm: Allow delivery of legacy 8259 interrupts to VCPUs != 0.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1246476149 -3600
# Node ID 80839a223746adfb3d7b7688085a84017fe3cf39
# Parent  479f1fa084d6af8611b0973be0fb6d642db1f9f9
x86 hvm: Allow delivery of legacy 8259 interrupts to VCPUs != 0.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/firmware/hvmloader/hvmloader.c |   12 ++++++---
 tools/firmware/hvmloader/mp_tables.c |   40 +++++++++++++++---------------
 xen/arch/x86/hvm/vioapic.c           |   17 +++++++-----
 xen/arch/x86/hvm/vlapic.c            |   46 ++++++++++++++++++++++++++++-------
 xen/arch/x86/hvm/vpic.c              |    8 ++----
 xen/include/asm-x86/hvm/domain.h     |    3 ++
 xen/include/asm-x86/hvm/vlapic.h     |    2 +
 7 files changed, 84 insertions(+), 44 deletions(-)

diff -r 479f1fa084d6 -r 80839a223746 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Wed Jul 01 14:58:31 2009 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c      Wed Jul 01 20:22:29 2009 +0100
@@ -141,13 +141,17 @@ static void init_hypercalls(void)
 
 static void apic_setup(void)
 {
-    /* Set the IOAPIC ID to tha static value used in the MP/ACPI tables. */
+    /* Set the IOAPIC ID to the static value used in the MP/ACPI tables. */
     ioapic_write(0x00, IOAPIC_ID);
 
-    /* Set up Virtual Wire mode. */
+    /* NMIs are delivered direct to the BSP. */
     lapic_write(APIC_SPIV, APIC_SPIV_APIC_ENABLED | 0xFF);
-    lapic_write(APIC_LVT0, APIC_MODE_EXTINT << 8);
-    lapic_write(APIC_LVT1, APIC_MODE_NMI    << 8);
+    lapic_write(APIC_LVT0, (APIC_MODE_EXTINT << 8) | APIC_LVT_MASKED);
+    lapic_write(APIC_LVT1, APIC_MODE_NMI << 8);
+
+    /* 8259A ExtInts are delivered through IOAPIC pin 0 (Virtual Wire Mode). */
+    ioapic_write(0x10, APIC_DM_EXTINT);
+    ioapic_write(0x11, SET_APIC_ID(LAPIC_ID(0)));
 }
 
 static void pci_setup(void)
diff -r 479f1fa084d6 -r 80839a223746 tools/firmware/hvmloader/mp_tables.c
--- a/tools/firmware/hvmloader/mp_tables.c      Wed Jul 01 14:58:31 2009 +0100
+++ b/tools/firmware/hvmloader/mp_tables.c      Wed Jul 01 20:22:29 2009 +0100
@@ -233,21 +233,6 @@ static void fill_mp_ioapic_entry(struct 
 }
 
 
-/* fills in an IO interrupt entry for IOAPIC 'ioapic_id' */
-static void fill_mp_io_intr_entry(
-    struct mp_io_intr_entry *mpiie,
-    int src_bus_id, int src_bus_irq, int ioapic_id, int dst_ioapic_intin)
-{
-    mpiie->type = ENTRY_TYPE_IO_INTR;
-    mpiie->intr_type = INTR_TYPE_INT;
-    mpiie->io_intr_flags = (PCI_ISA_IRQ_MASK & (1U<<src_bus_irq)) ? 0xf : 0x0;
-    mpiie->src_bus_id = src_bus_id;
-    mpiie->src_bus_irq = src_bus_irq;
-    mpiie->dst_ioapic_id = ioapic_id;
-    mpiie->dst_ioapic_intin = dst_ioapic_intin;
-}
-
-
 /* fill in the mp floating processor structure */
 static void fill_mpfps(struct mp_floating_pointer_struct *mpfps, uint32_t mpct)
 {
@@ -316,6 +301,7 @@ void create_mp_tables(void)
     void *mp_table_base;
     char *p;
     int vcpu_nr, i, length;
+    struct mp_io_intr_entry *mpiie;
 
     vcpu_nr = hvm_info->nr_vcpus;
 
@@ -343,12 +329,28 @@ void create_mp_tables(void)
     fill_mp_ioapic_entry((struct mp_ioapic_entry *)p);
     p += sizeof(struct mp_ioapic_entry);
 
+    /* I/O interrupt assignment: IOAPIC pin 0 is connected to 8259 ExtInt. */
+    mpiie = (struct mp_io_intr_entry *)p;
+    memset(mpiie, 0, sizeof(*mpiie));
+    mpiie->type = ENTRY_TYPE_IO_INTR;
+    mpiie->intr_type = INTR_TYPE_EXTINT;
+    mpiie->dst_ioapic_id = IOAPIC_ID;
+    p += sizeof(*mpiie);
+
+    /* I/O interrupt assignment for every legacy 8259 interrupt source. */
     for ( i = 0; i < 16; i++ )
     {
-        if ( i == 2 ) continue; /* skip the slave PIC connection */
-        fill_mp_io_intr_entry((struct mp_io_intr_entry *)p, 
-                              BUS_ID_ISA, i, IOAPIC_ID, (i == 0) ? 2 : i);
-        p += sizeof(struct mp_io_intr_entry);
+        if ( i == 2 )
+            continue; /* skip the slave PIC connection */
+        mpiie = (struct mp_io_intr_entry *)p;
+        mpiie->type = ENTRY_TYPE_IO_INTR;
+        mpiie->intr_type = INTR_TYPE_EXTINT;
+        mpiie->io_intr_flags = (PCI_ISA_IRQ_MASK & (1U << i)) ? 0xf : 0x0;
+        mpiie->src_bus_id = BUS_ID_ISA;
+        mpiie->src_bus_irq = i;
+        mpiie->dst_ioapic_id = IOAPIC_ID;
+        mpiie->dst_ioapic_intin = (i == 0) ? 2 : i;
+        p += sizeof(*mpiie);
     }
 
     length = p - (char *)mp_table_base;
diff -r 479f1fa084d6 -r 80839a223746 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Wed Jul 01 14:58:31 2009 +0100
+++ b/xen/arch/x86/hvm/vioapic.c        Wed Jul 01 20:22:29 2009 +0100
@@ -146,10 +146,14 @@ static void vioapic_write_redirent(
 
     *pent = ent;
 
-    if ( (ent.fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
-         !ent.fields.mask &&
-         !ent.fields.remote_irr &&
-         hvm_irq->gsi_assert_count[idx] )
+    if ( idx == 0 )
+    {
+        vlapic_adjust_i8259_target(d);
+    }
+    else if ( (ent.fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
+              !ent.fields.mask &&
+              !ent.fields.remote_irr &&
+              hvm_irq->gsi_assert_count[idx] )
     {
         pent->fields.remote_irr = 1;
         vioapic_deliver(vioapic, idx);
@@ -159,8 +163,7 @@ static void vioapic_write_redirent(
 }
 
 static void vioapic_write_indirect(
-    struct hvm_hw_vioapic *vioapic, unsigned long addr,
-    unsigned long length, unsigned long val)
+    struct hvm_hw_vioapic *vioapic, unsigned long length, unsigned long val)
 {
     switch ( vioapic->ioregsel )
     {
@@ -213,7 +216,7 @@ static int vioapic_write(
         break;
 
     case VIOAPIC_REG_WINDOW:
-        vioapic_write_indirect(vioapic, addr, length, val);
+        vioapic_write_indirect(vioapic, length, val);
         break;
 
 #if VIOAPIC_IS_IOSAPIC
diff -r 479f1fa084d6 -r 80839a223746 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Jul 01 14:58:31 2009 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Wed Jul 01 20:22:29 2009 +0100
@@ -697,6 +697,8 @@ static int vlapic_write(struct vcpu *v, 
             val |= APIC_LVT_MASKED;
         val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
         vlapic_set_reg(vlapic, offset, val);
+        if ( offset == APIC_LVT0 )
+            vlapic_adjust_i8259_target(v->domain);
         break;
 
     case APIC_TMICT:
@@ -776,18 +778,43 @@ void vlapic_msr_set(struct vlapic *vlapi
                 "apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr);
 }
 
-int vlapic_accept_pic_intr(struct vcpu *v)
-{
+static int __vlapic_accept_pic_intr(struct vcpu *v)
+{
+    struct domain *d = v->domain;
     struct vlapic *vlapic = vcpu_vlapic(v);
     uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0);
-
-    /*
-     * Only CPU0 is wired to the 8259A. INTA cycles occur if LINT0 is set up
-     * accept ExtInts, or if the LAPIC is disabled (so LINT0 behaves as INTR).
-     */
-    return ((v->vcpu_id == 0) &&
-            (((lvt0 & (APIC_MODE_MASK|APIC_LVT_MASKED)) == APIC_DM_EXTINT) ||
+    union vioapic_redir_entry redir0 = domain_vioapic(d)->redirtbl[0];
+
+    /* We deliver 8259 interrupts to the appropriate CPU as follows. */
+    return ((/* IOAPIC pin0 is unmasked and routing to this LAPIC? */
+             ((redir0.fields.delivery_mode == dest_ExtINT) &&
+              !redir0.fields.mask &&
+              redir0.fields.dest_id == VLAPIC_ID(vlapic) &&
+              !vlapic_disabled(vlapic)) ||
+             /* LAPIC has LVT0 unmasked for ExtInts? */
+             ((lvt0 & (APIC_MODE_MASK|APIC_LVT_MASKED)) == APIC_DM_EXTINT) ||
+             /* LAPIC is fully disabled? */
              vlapic_hw_disabled(vlapic)));
+}
+
+int vlapic_accept_pic_intr(struct vcpu *v)
+{
+    return ((v == v->domain->arch.hvm_domain.i8259_target) &&
+            __vlapic_accept_pic_intr(v));
+}
+
+void vlapic_adjust_i8259_target(struct domain *d)
+{
+    struct vcpu *v;
+
+    for_each_vcpu ( d, v )
+        if ( __vlapic_accept_pic_intr(v) )
+            goto found;
+
+    v = d->vcpu ? d->vcpu[0] : NULL;
+
+ found:
+    d->arch.hvm_domain.i8259_target = v;
 }
 
 int vlapic_has_pending_irq(struct vcpu *v)
@@ -946,6 +973,7 @@ static int lapic_load_regs(struct domain
     if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 ) 
         return -EINVAL;
 
+    vlapic_adjust_i8259_target(d);
     lapic_rearm(s);
     return 0;
 }
diff -r 479f1fa084d6 -r 80839a223746 xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Wed Jul 01 14:58:31 2009 +0100
+++ b/xen/arch/x86/hvm/vpic.c   Wed Jul 01 20:22:29 2009 +0100
@@ -109,11 +109,9 @@ static void vpic_update_int_output(struc
     {
         if ( vpic->is_master )
         {
-            /* Master INT line is connected to VCPU0's VLAPIC LVT0. */
-            struct vcpu *v = vpic_domain(vpic)->vcpu ?
-                vpic_domain(vpic)->vcpu[0] : NULL;
-
-            if ( (v != NULL) && vlapic_accept_pic_intr(v) )
+            /* Master INT line is connected in Virtual Wire Mode. */
+            struct vcpu *v = vpic_domain(vpic)->arch.hvm_domain.i8259_target;
+            if ( v != NULL )
                 vcpu_kick(v);
         }
         else
diff -r 479f1fa084d6 -r 80839a223746 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Wed Jul 01 14:58:31 2009 +0100
+++ b/xen/include/asm-x86/hvm/domain.h  Wed Jul 01 20:22:29 2009 +0100
@@ -57,6 +57,9 @@ struct hvm_domain {
     struct hvm_vioapic    *vioapic;
     struct hvm_hw_stdvga   stdvga;
 
+    /* VCPU which is current target for 8259 interrupts. */
+    struct vcpu           *i8259_target;
+
     /* hvm_print_line() logging. */
     char                   pbuf[80];
     int                    pbuf_idx;
diff -r 479f1fa084d6 -r 80839a223746 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Wed Jul 01 14:58:31 2009 +0100
+++ b/xen/include/asm-x86/hvm/vlapic.h  Wed Jul 01 20:22:29 2009 +0100
@@ -93,6 +93,8 @@ void vlapic_msr_set(struct vlapic *vlapi
 
 int vlapic_accept_pic_intr(struct vcpu *v);
 
+void vlapic_adjust_i8259_target(struct domain *d);
+
 struct vlapic *apic_lowest_prio(struct domain *d, uint32_t bitmap);
 
 int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.