[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |