IWAMOTO Toshihiro
2011-Jan-13 05:19 UTC
[Xen-devel] [PATCH] MP interrupt delivery fix for xen-3.4
Please backport the following xen-4.0-testing.hg changesets to xen-3.4. They are necessary for kexec/kdump to work on MP guests. Backporting is mostly obvious but the changeset 19691:c4b2a3c9a61a, which is slightly different from 19912:721c14d7f60b, will cause a conflict. A combined diff which is ready to be applyed on xen-3.4-testing.hg is also attached. changeset: 19877:80839a223746 user: Keir Fraser <keir.fraser@citrix.com> date: Wed Jul 01 20:22:29 2009 +0100 files: tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/mp_tables.c xen/arch/x86/hvm/vioapic.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpic.c xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/vlapic.h description: x86 hvm: Allow delivery of legacy 8259 interrupts to VCPUs != 0. changeset: 19906:2fadef1b008f user: Keir Fraser <keir.fraser@citrix.com> date: Tue Jul 07 14:08:47 2009 +0100 files: xen/arch/x86/hvm/hpet.c xen/include/asm-x86/hvm/vpt.h description: x86,hvm: cleanup hpet.c vcpu handling same as i8254.c/rtc.c - introduce macros: domain_vhpet, vcpu_vhpet, vhpet_domain, vhpet_vcpu - remove *vcpu field from struct HPETState - modify guest_time_hpet() takes *vhpet instead of *vcpu as 1st - argument changeset: 19907:a29bb4efff00 user: Keir Fraser <keir.fraser@citrix.com> date: Tue Jul 07 14:21:16 2009 +0100 files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpt.c xen/include/asm-x86/hvm/vpt.h description: x86,hvm: Allow delivery of timer interrupts to VCPUs != 0 This patch is needed for kexec/kdump since VCPU#0 is halted. changeset: 19912:721c14d7f60b user: Keir Fraser <keir.fraser@citrix.com> date: Wed Jul 08 14:22:00 2009 +0100 files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c xen/include/asm-x86/hvm/vlapic.h description: x86 hvm: Use ''x'' as parameter name for macros converting between {vcpu,domain} and {vlapic,vpic,vrtc,hpet}. Completely avoids accidental aliasing. diff -r 14709d196e43 tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Wed Jun 30 18:26:13 2010 +0100 +++ b/tools/firmware/hvmloader/hvmloader.c Thu Jan 13 14:17:37 2011 +0900 @@ -141,13 +141,17 @@ 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 14709d196e43 tools/firmware/hvmloader/mp_tables.c --- a/tools/firmware/hvmloader/mp_tables.c Wed Jun 30 18:26:13 2010 +0100 +++ b/tools/firmware/hvmloader/mp_tables.c Thu Jan 13 14:17:37 2011 +0900 @@ -233,21 +233,6 @@ } -/* 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 *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 @@ 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 14709d196e43 xen/arch/x86/hvm/hpet.c --- a/xen/arch/x86/hvm/hpet.c Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/arch/x86/hvm/hpet.c Thu Jan 13 14:17:37 2011 +0900 @@ -24,6 +24,12 @@ #include <xen/sched.h> #include <xen/event.h> +#define domain_vhpet(x) (&(x)->arch.hvm_domain.pl_time.vhpet) +#define vcpu_vhpet(x) (domain_vhpet((x)->domain)) +#define vhpet_domain(x) (container_of((x), struct domain, \ + arch.hvm_domain.pl_time.vhpet)) +#define vhpet_vcpu(x) (pt_global_vcpu_target(vhpet_domain(x))) + #define HPET_BASE_ADDRESS 0xfed00000ULL #define HPET_MMAP_SIZE 1024 #define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */ @@ -31,7 +37,8 @@ /* Frequency_of_Xen_systeme_time / frequency_of_HPET = 16 */ #define STIME_PER_HPET_TICK 16 -#define guest_time_hpet(v) (hvm_get_guest_time(v) / STIME_PER_HPET_TICK) +#define guest_time_hpet(hpet) \ + (hvm_get_guest_time(vhpet_vcpu(hpet)) / STIME_PER_HPET_TICK) #define HPET_ID 0x000 #define HPET_PERIOD 0x004 @@ -94,7 +101,7 @@ ASSERT(spin_is_locked(&h->lock)); if ( hpet_enabled(h) ) - return guest_time_hpet(h->vcpu) + h->mc_offset; + return guest_time_hpet(h) + h->mc_offset; else return h->hpet.mc64; } @@ -176,7 +183,7 @@ struct vcpu *v, unsigned long addr, unsigned long length, unsigned long *pval) { - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; + HPETState *h = vcpu_vhpet(v); unsigned long result; uint64_t val; @@ -230,7 +237,7 @@ { /* HPET specification requires PIT shouldn''t generate * interrupts if LegacyReplacementRoute is set for timer0 */ - PITState *pit = &h->vcpu->domain->arch.hvm_domain.pl_time.vpit; + PITState *pit = &vhpet_domain(h)->arch.hvm_domain.pl_time.vpit; pit_stop_channel0_irq(pit); } @@ -272,7 +279,7 @@ * being enabled (now). */ oneshot = !timer_is_periodic(h, tn); - create_periodic_time(h->vcpu, &h->pt[tn], + create_periodic_time(vhpet_vcpu(h), &h->pt[tn], hpet_tick_to_ns(h, diff), oneshot ? 0 : hpet_tick_to_ns(h, h->hpet.period[tn]), irq, NULL, NULL); @@ -290,7 +297,7 @@ struct vcpu *v, unsigned long addr, unsigned long length, unsigned long val) { - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; + HPETState *h = vcpu_vhpet(v); uint64_t old_val, new_val; int tn, i; @@ -323,7 +330,7 @@ if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) ) { /* Enable main counter and interrupt generation. */ - h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu); + h->mc_offset = h->hpet.mc64 - guest_time_hpet(h); for ( i = 0; i < HPET_TIMER_NUM; i++ ) { h->hpet.comparator64[i] @@ -337,7 +344,7 @@ else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) ) { /* Halt main counter and disable interrupt generation. */ - h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu); + h->hpet.mc64 = h->mc_offset + guest_time_hpet(h); for ( i = 0; i < HPET_TIMER_NUM; i++ ) if ( timer_enabled(h, i) ) set_stop_timer(i); @@ -487,13 +494,13 @@ static int hpet_save(struct domain *d, hvm_domain_context_t *h) { - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; + HPETState *hp = domain_vhpet(d); int rc; spin_lock(&hp->lock); /* Write the proper value into the main counter */ - hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu); + hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp); /* Save the HPET registers */ rc = _hvm_init_entry(h, HVM_SAVE_CODE(HPET), 0, HVM_SAVE_LENGTH(HPET)); @@ -531,7 +538,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h) { - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; + HPETState *hp = domain_vhpet(d); struct hvm_hw_hpet *rec; uint64_t cmp; int i; @@ -572,7 +579,7 @@ #undef C /* Recalculate the offset between the main counter and guest time */ - hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu); + hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp); /* restart all timers */ @@ -590,14 +597,13 @@ void hpet_init(struct vcpu *v) { - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; + HPETState *h = vcpu_vhpet(v); int i; memset(h, 0, sizeof(HPETState)); spin_lock_init(&h->lock); - h->vcpu = v; h->stime_freq = S_TO_NS; h->hpet_to_ns_scale = ((S_TO_NS * STIME_PER_HPET_TICK) << 10) / h->stime_freq; @@ -622,7 +628,7 @@ void hpet_deinit(struct domain *d) { int i; - HPETState *h = &d->arch.hvm_domain.pl_time.vhpet; + HPETState *h = domain_vhpet(d); spin_lock(&h->lock); diff -r 14709d196e43 xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/arch/x86/hvm/i8254.c Thu Jan 13 14:17:37 2011 +0900 @@ -42,7 +42,7 @@ #define vcpu_vpit(x) (domain_vpit((x)->domain)) #define vpit_domain(x) (container_of((x), struct domain, \ arch.hvm_domain.pl_time.vpit)) -#define vpit_vcpu(x) (vpit_domain(x)->vcpu[0]) +#define vpit_vcpu(x) (pt_global_vcpu_target(vpit_domain(x))) #define RW_STATE_LSB 1 #define RW_STATE_MSB 2 diff -r 14709d196e43 xen/arch/x86/hvm/rtc.c --- a/xen/arch/x86/hvm/rtc.c Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/arch/x86/hvm/rtc.c Thu Jan 13 14:17:37 2011 +0900 @@ -32,7 +32,7 @@ #define vcpu_vrtc(x) (domain_vrtc((x)->domain)) #define vrtc_domain(x) (container_of((x), struct domain, \ arch.hvm_domain.pl_time.vrtc)) -#define vrtc_vcpu(x) (vrtc_domain(x)->vcpu[0]) +#define vrtc_vcpu(x) (pt_global_vcpu_target(vrtc_domain(x))) static void rtc_periodic_cb(struct vcpu *v, void *opaque) { diff -r 14709d196e43 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/arch/x86/hvm/vioapic.c Thu Jan 13 14:17:37 2011 +0900 @@ -146,10 +146,14 @@ *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_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 @@ 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 14709d196e43 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/arch/x86/hvm/vlapic.c Thu Jan 13 14:17:37 2011 +0900 @@ -697,6 +697,8 @@ 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,46 @@ "apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr); } +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); + 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) { - struct vlapic *vlapic = vcpu_vlapic(v); - uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0); + return ((v == v->domain->arch.hvm_domain.i8259_target) && + __vlapic_accept_pic_intr(v)); +} - /* - * 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) || - vlapic_hw_disabled(vlapic))); +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: + if ( d->arch.hvm_domain.i8259_target == v ) + return; + d->arch.hvm_domain.i8259_target = v; + pt_adjust_global_vcpu_target(v); } int vlapic_has_pending_irq(struct vcpu *v) @@ -946,6 +976,7 @@ if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 ) return -EINVAL; + vlapic_adjust_i8259_target(d); lapic_rearm(s); return 0; } diff -r 14709d196e43 xen/arch/x86/hvm/vpic.c --- a/xen/arch/x86/hvm/vpic.c Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/arch/x86/hvm/vpic.c Thu Jan 13 14:17:37 2011 +0900 @@ -109,9 +109,9 @@ { if ( vpic->is_master ) { - /* Master INT line is connected to VCPU0''s VLAPIC LVT0. */ - struct vcpu *v = vpic_domain(vpic)->vcpu[0]; - 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 14709d196e43 xen/arch/x86/hvm/vpt.c --- a/xen/arch/x86/hvm/vpt.c Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/arch/x86/hvm/vpt.c Thu Jan 13 14:17:37 2011 +0900 @@ -434,3 +434,53 @@ */ kill_timer(&pt->timer); } + +static void pt_adjust_vcpu(struct periodic_time *pt, struct vcpu *v) +{ + int on_list; + + ASSERT(pt->source == PTSRC_isa); + + if ( pt->vcpu == NULL ) + return; + + pt_lock(pt); + on_list = pt->on_list; + if ( pt->on_list ) + list_del(&pt->list); + pt->on_list = 0; + pt_unlock(pt); + + spin_lock(&v->arch.hvm_vcpu.tm_lock); + pt->vcpu = v; + if ( on_list ) + { + pt->on_list = 1; + list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); + + migrate_timer(&pt->timer, v->processor); + } + spin_unlock(&v->arch.hvm_vcpu.tm_lock); +} + +void pt_adjust_global_vcpu_target(struct vcpu *v) +{ + struct pl_time *pl_time = &v->domain->arch.hvm_domain.pl_time; + int i; + + if ( v == NULL ) + return; + + spin_lock(&pl_time->vpit.lock); + pt_adjust_vcpu(&pl_time->vpit.pt0, v); + spin_unlock(&pl_time->vpit.lock); + + spin_lock(&pl_time->vrtc.lock); + pt_adjust_vcpu(&pl_time->vrtc.pt, v); + spin_unlock(&pl_time->vrtc.lock); + + spin_lock(&pl_time->vhpet.lock); + for ( i = 0; i < HPET_TIMER_NUM; i++ ) + pt_adjust_vcpu(&pl_time->vhpet.pt[i], v); + spin_unlock(&pl_time->vhpet.lock); +} diff -r 14709d196e43 xen/include/asm-x86/hvm/domain.h --- a/xen/include/asm-x86/hvm/domain.h Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/include/asm-x86/hvm/domain.h Thu Jan 13 14:17:37 2011 +0900 @@ -56,6 +56,9 @@ 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 14709d196e43 xen/include/asm-x86/hvm/vlapic.h --- a/xen/include/asm-x86/hvm/vlapic.h Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/include/asm-x86/hvm/vlapic.h Thu Jan 13 14:17:37 2011 +0900 @@ -92,6 +92,8 @@ 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); diff -r 14709d196e43 xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Wed Jun 30 18:26:13 2010 +0100 +++ b/xen/include/asm-x86/hvm/vpt.h Thu Jan 13 14:17:37 2011 +0900 @@ -92,7 +92,6 @@ typedef struct HPETState { struct hpet_registers hpet; - struct vcpu *vcpu; uint64_t stime_freq; uint64_t hpet_to_ns_scale; /* hpet ticks to ns (multiplied by 2^10) */ uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns */ @@ -145,6 +144,10 @@ void pt_reset(struct vcpu *v); void pt_migrate(struct vcpu *v); +void pt_adjust_global_vcpu_target(struct vcpu *v); +#define pt_global_vcpu_target(d) \ + ((d)->arch.hvm_domain.i8259_target ? : (d)->vcpu ? (d)->vcpu[0] : NULL) + /* Is given periodic timer active? */ #define pt_active(pt) ((pt)->on_list) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2011-Jan-13 12:33 UTC
Re: [Xen-devel] [PATCH] MP interrupt delivery fix for xen-3.4
On 13/01/2011 05:19, "IWAMOTO Toshihiro" <iwamoto@valinux.co.jp> wrote:> Please backport the following xen-4.0-testing.hg changesets to > xen-3.4. They are necessary for kexec/kdump to work on MP guests. > Backporting is mostly obvious but the changeset 19691:c4b2a3c9a61a, > which is slightly different from 19912:721c14d7f60b, will cause a > conflict.I no longer maintain 3.4 and I''m not accepting patches to it. -- Keir> A combined diff which is ready to be applyed on xen-3.4-testing.hg is > also attached. > > changeset: 19877:80839a223746 > user: Keir Fraser <keir.fraser@citrix.com> > date: Wed Jul 01 20:22:29 2009 +0100 > files: tools/firmware/hvmloader/hvmloader.c > tools/firmware/hvmloader/mp_tables.c xen/arch/x86/hvm/vioapic.c > xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpic.c > xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/vlapic.h > description: > x86 hvm: Allow delivery of legacy 8259 interrupts to VCPUs != 0. > > changeset: 19906:2fadef1b008f > user: Keir Fraser <keir.fraser@citrix.com> > date: Tue Jul 07 14:08:47 2009 +0100 > files: xen/arch/x86/hvm/hpet.c xen/include/asm-x86/hvm/vpt.h > description: > x86,hvm: cleanup hpet.c vcpu handling same as i8254.c/rtc.c > > - introduce macros: domain_vhpet, vcpu_vhpet, vhpet_domain, vhpet_vcpu > - remove *vcpu field from struct HPETState > - modify guest_time_hpet() takes *vhpet instead of *vcpu as 1st > - argument > > changeset: 19907:a29bb4efff00 > user: Keir Fraser <keir.fraser@citrix.com> > date: Tue Jul 07 14:21:16 2009 +0100 > files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c > xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c > xen/arch/x86/hvm/vpt.c xen/include/asm-x86/hvm/vpt.h > description: > x86,hvm: Allow delivery of timer interrupts to VCPUs != 0 > > This patch is needed for kexec/kdump since VCPU#0 is halted. > > changeset: 19912:721c14d7f60b > user: Keir Fraser <keir.fraser@citrix.com> > date: Wed Jul 08 14:22:00 2009 +0100 > files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c > xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c > xen/include/asm-x86/hvm/vlapic.h > description: > x86 hvm: Use ''x'' as parameter name for macros converting between > {vcpu,domain} and {vlapic,vpic,vrtc,hpet}. Completely avoids > accidental aliasing. > > > > diff -r 14709d196e43 tools/firmware/hvmloader/hvmloader.c > --- a/tools/firmware/hvmloader/hvmloader.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/tools/firmware/hvmloader/hvmloader.c Thu Jan 13 14:17:37 2011 +0900 > @@ -141,13 +141,17 @@ > > 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 14709d196e43 tools/firmware/hvmloader/mp_tables.c > --- a/tools/firmware/hvmloader/mp_tables.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/tools/firmware/hvmloader/mp_tables.c Thu Jan 13 14:17:37 2011 +0900 > @@ -233,21 +233,6 @@ > } > > > -/* 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 *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 @@ > 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 14709d196e43 xen/arch/x86/hvm/hpet.c > --- a/xen/arch/x86/hvm/hpet.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/arch/x86/hvm/hpet.c Thu Jan 13 14:17:37 2011 +0900 > @@ -24,6 +24,12 @@ > #include <xen/sched.h> > #include <xen/event.h> > > +#define domain_vhpet(x) (&(x)->arch.hvm_domain.pl_time.vhpet) > +#define vcpu_vhpet(x) (domain_vhpet((x)->domain)) > +#define vhpet_domain(x) (container_of((x), struct domain, \ > + arch.hvm_domain.pl_time.vhpet)) > +#define vhpet_vcpu(x) (pt_global_vcpu_target(vhpet_domain(x))) > + > #define HPET_BASE_ADDRESS 0xfed00000ULL > #define HPET_MMAP_SIZE 1024 > #define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */ > @@ -31,7 +37,8 @@ > > /* Frequency_of_Xen_systeme_time / frequency_of_HPET = 16 */ > #define STIME_PER_HPET_TICK 16 > -#define guest_time_hpet(v) (hvm_get_guest_time(v) / STIME_PER_HPET_TICK) > +#define guest_time_hpet(hpet) \ > + (hvm_get_guest_time(vhpet_vcpu(hpet)) / STIME_PER_HPET_TICK) > > #define HPET_ID 0x000 > #define HPET_PERIOD 0x004 > @@ -94,7 +101,7 @@ > ASSERT(spin_is_locked(&h->lock)); > > if ( hpet_enabled(h) ) > - return guest_time_hpet(h->vcpu) + h->mc_offset; > + return guest_time_hpet(h) + h->mc_offset; > else > return h->hpet.mc64; > } > @@ -176,7 +183,7 @@ > struct vcpu *v, unsigned long addr, unsigned long length, > unsigned long *pval) > { > - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; > + HPETState *h = vcpu_vhpet(v); > unsigned long result; > uint64_t val; > > @@ -230,7 +237,7 @@ > { > /* HPET specification requires PIT shouldn''t generate > * interrupts if LegacyReplacementRoute is set for timer0 */ > - PITState *pit = &h->vcpu->domain->arch.hvm_domain.pl_time.vpit; > + PITState *pit = &vhpet_domain(h)->arch.hvm_domain.pl_time.vpit; > pit_stop_channel0_irq(pit); > } > > @@ -272,7 +279,7 @@ > * being enabled (now). > */ > oneshot = !timer_is_periodic(h, tn); > - create_periodic_time(h->vcpu, &h->pt[tn], > + create_periodic_time(vhpet_vcpu(h), &h->pt[tn], > hpet_tick_to_ns(h, diff), > oneshot ? 0 : hpet_tick_to_ns(h, > h->hpet.period[tn]), > irq, NULL, NULL); > @@ -290,7 +297,7 @@ > struct vcpu *v, unsigned long addr, > unsigned long length, unsigned long val) > { > - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; > + HPETState *h = vcpu_vhpet(v); > uint64_t old_val, new_val; > int tn, i; > > @@ -323,7 +330,7 @@ > if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) ) > { > /* Enable main counter and interrupt generation. */ > - h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu); > + h->mc_offset = h->hpet.mc64 - guest_time_hpet(h); > for ( i = 0; i < HPET_TIMER_NUM; i++ ) > { > h->hpet.comparator64[i] > @@ -337,7 +344,7 @@ > else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) > ) > { > /* Halt main counter and disable interrupt generation. */ > - h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu); > + h->hpet.mc64 = h->mc_offset + guest_time_hpet(h); > for ( i = 0; i < HPET_TIMER_NUM; i++ ) > if ( timer_enabled(h, i) ) > set_stop_timer(i); > @@ -487,13 +494,13 @@ > > static int hpet_save(struct domain *d, hvm_domain_context_t *h) > { > - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; > + HPETState *hp = domain_vhpet(d); > int rc; > > spin_lock(&hp->lock); > > /* Write the proper value into the main counter */ > - hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu); > + hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp); > > /* Save the HPET registers */ > rc = _hvm_init_entry(h, HVM_SAVE_CODE(HPET), 0, HVM_SAVE_LENGTH(HPET)); > @@ -531,7 +538,7 @@ > > static int hpet_load(struct domain *d, hvm_domain_context_t *h) > { > - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; > + HPETState *hp = domain_vhpet(d); > struct hvm_hw_hpet *rec; > uint64_t cmp; > int i; > @@ -572,7 +579,7 @@ > #undef C > > /* Recalculate the offset between the main counter and guest time */ > - hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu); > + hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp); > > /* restart all timers */ > > @@ -590,14 +597,13 @@ > > void hpet_init(struct vcpu *v) > { > - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; > + HPETState *h = vcpu_vhpet(v); > int i; > > memset(h, 0, sizeof(HPETState)); > > spin_lock_init(&h->lock); > > - h->vcpu = v; > h->stime_freq = S_TO_NS; > > h->hpet_to_ns_scale = ((S_TO_NS * STIME_PER_HPET_TICK) << 10) / > h->stime_freq; > @@ -622,7 +628,7 @@ > void hpet_deinit(struct domain *d) > { > int i; > - HPETState *h = &d->arch.hvm_domain.pl_time.vhpet; > + HPETState *h = domain_vhpet(d); > > spin_lock(&h->lock); > > diff -r 14709d196e43 xen/arch/x86/hvm/i8254.c > --- a/xen/arch/x86/hvm/i8254.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/arch/x86/hvm/i8254.c Thu Jan 13 14:17:37 2011 +0900 > @@ -42,7 +42,7 @@ > #define vcpu_vpit(x) (domain_vpit((x)->domain)) > #define vpit_domain(x) (container_of((x), struct domain, \ > arch.hvm_domain.pl_time.vpit)) > -#define vpit_vcpu(x) (vpit_domain(x)->vcpu[0]) > +#define vpit_vcpu(x) (pt_global_vcpu_target(vpit_domain(x))) > > #define RW_STATE_LSB 1 > #define RW_STATE_MSB 2 > diff -r 14709d196e43 xen/arch/x86/hvm/rtc.c > --- a/xen/arch/x86/hvm/rtc.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/arch/x86/hvm/rtc.c Thu Jan 13 14:17:37 2011 +0900 > @@ -32,7 +32,7 @@ > #define vcpu_vrtc(x) (domain_vrtc((x)->domain)) > #define vrtc_domain(x) (container_of((x), struct domain, \ > arch.hvm_domain.pl_time.vrtc)) > -#define vrtc_vcpu(x) (vrtc_domain(x)->vcpu[0]) > +#define vrtc_vcpu(x) (pt_global_vcpu_target(vrtc_domain(x))) > > static void rtc_periodic_cb(struct vcpu *v, void *opaque) > { > diff -r 14709d196e43 xen/arch/x86/hvm/vioapic.c > --- a/xen/arch/x86/hvm/vioapic.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/arch/x86/hvm/vioapic.c Thu Jan 13 14:17:37 2011 +0900 > @@ -146,10 +146,14 @@ > > *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_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 @@ > 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 14709d196e43 xen/arch/x86/hvm/vlapic.c > --- a/xen/arch/x86/hvm/vlapic.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/arch/x86/hvm/vlapic.c Thu Jan 13 14:17:37 2011 +0900 > @@ -697,6 +697,8 @@ > 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,46 @@ > "apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr); > } > > +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); > + 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) > { > - struct vlapic *vlapic = vcpu_vlapic(v); > - uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0); > + return ((v == v->domain->arch.hvm_domain.i8259_target) && > + __vlapic_accept_pic_intr(v)); > +} > > - /* > - * 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) || > - vlapic_hw_disabled(vlapic))); > +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: > + if ( d->arch.hvm_domain.i8259_target == v ) > + return; > + d->arch.hvm_domain.i8259_target = v; > + pt_adjust_global_vcpu_target(v); > } > > int vlapic_has_pending_irq(struct vcpu *v) > @@ -946,6 +976,7 @@ > if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 ) > return -EINVAL; > > + vlapic_adjust_i8259_target(d); > lapic_rearm(s); > return 0; > } > diff -r 14709d196e43 xen/arch/x86/hvm/vpic.c > --- a/xen/arch/x86/hvm/vpic.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/arch/x86/hvm/vpic.c Thu Jan 13 14:17:37 2011 +0900 > @@ -109,9 +109,9 @@ > { > if ( vpic->is_master ) > { > - /* Master INT line is connected to VCPU0''s VLAPIC LVT0. */ > - struct vcpu *v = vpic_domain(vpic)->vcpu[0]; > - 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 14709d196e43 xen/arch/x86/hvm/vpt.c > --- a/xen/arch/x86/hvm/vpt.c Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/arch/x86/hvm/vpt.c Thu Jan 13 14:17:37 2011 +0900 > @@ -434,3 +434,53 @@ > */ > kill_timer(&pt->timer); > } > + > +static void pt_adjust_vcpu(struct periodic_time *pt, struct vcpu *v) > +{ > + int on_list; > + > + ASSERT(pt->source == PTSRC_isa); > + > + if ( pt->vcpu == NULL ) > + return; > + > + pt_lock(pt); > + on_list = pt->on_list; > + if ( pt->on_list ) > + list_del(&pt->list); > + pt->on_list = 0; > + pt_unlock(pt); > + > + spin_lock(&v->arch.hvm_vcpu.tm_lock); > + pt->vcpu = v; > + if ( on_list ) > + { > + pt->on_list = 1; > + list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); > + > + migrate_timer(&pt->timer, v->processor); > + } > + spin_unlock(&v->arch.hvm_vcpu.tm_lock); > +} > + > +void pt_adjust_global_vcpu_target(struct vcpu *v) > +{ > + struct pl_time *pl_time = &v->domain->arch.hvm_domain.pl_time; > + int i; > + > + if ( v == NULL ) > + return; > + > + spin_lock(&pl_time->vpit.lock); > + pt_adjust_vcpu(&pl_time->vpit.pt0, v); > + spin_unlock(&pl_time->vpit.lock); > + > + spin_lock(&pl_time->vrtc.lock); > + pt_adjust_vcpu(&pl_time->vrtc.pt, v); > + spin_unlock(&pl_time->vrtc.lock); > + > + spin_lock(&pl_time->vhpet.lock); > + for ( i = 0; i < HPET_TIMER_NUM; i++ ) > + pt_adjust_vcpu(&pl_time->vhpet.pt[i], v); > + spin_unlock(&pl_time->vhpet.lock); > +} > diff -r 14709d196e43 xen/include/asm-x86/hvm/domain.h > --- a/xen/include/asm-x86/hvm/domain.h Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/include/asm-x86/hvm/domain.h Thu Jan 13 14:17:37 2011 +0900 > @@ -56,6 +56,9 @@ > 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 14709d196e43 xen/include/asm-x86/hvm/vlapic.h > --- a/xen/include/asm-x86/hvm/vlapic.h Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/include/asm-x86/hvm/vlapic.h Thu Jan 13 14:17:37 2011 +0900 > @@ -92,6 +92,8 @@ > > 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); > diff -r 14709d196e43 xen/include/asm-x86/hvm/vpt.h > --- a/xen/include/asm-x86/hvm/vpt.h Wed Jun 30 18:26:13 2010 +0100 > +++ b/xen/include/asm-x86/hvm/vpt.h Thu Jan 13 14:17:37 2011 +0900 > @@ -92,7 +92,6 @@ > > typedef struct HPETState { > struct hpet_registers hpet; > - struct vcpu *vcpu; > uint64_t stime_freq; > uint64_t hpet_to_ns_scale; /* hpet ticks to ns (multiplied by 2^10) */ > uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns */ > @@ -145,6 +144,10 @@ > void pt_reset(struct vcpu *v); > void pt_migrate(struct vcpu *v); > > +void pt_adjust_global_vcpu_target(struct vcpu *v); > +#define pt_global_vcpu_target(d) \ > + ((d)->arch.hvm_domain.i8259_target ? : (d)->vcpu ? (d)->vcpu[0] : NULL) > + > /* Is given periodic timer active? */ > #define pt_active(pt) ((pt)->on_list) > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
IWAMOTO Toshihiro
2011-Jan-14 06:50 UTC
Re: [Xen-devel] [PATCH] MP interrupt delivery fix for xen-3.4
At Thu, 13 Jan 2011 12:33:13 +0000, Keir Fraser wrote:> > On 13/01/2011 05:19, "IWAMOTO Toshihiro" <iwamoto@valinux.co.jp> wrote: > > > Please backport the following xen-4.0-testing.hg changesets to > > xen-3.4. They are necessary for kexec/kdump to work on MP guests. > > Backporting is mostly obvious but the changeset 19691:c4b2a3c9a61a, > > which is slightly different from 19912:721c14d7f60b, will cause a > > conflict. > > I no longer maintain 3.4 and I''m not accepting patches to it.Sad to hear that. I see. -- IWAMOTO Toshihiro _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
George Dunlap
2011-Jan-14 12:13 UTC
Re: [Xen-devel] [PATCH] MP interrupt delivery fix for xen-3.4
Would it be reasonable to ask if anyone is willing to step up as a "legacy/stable maintainer"? Given that 3.4 is still in the just-released Citrix product, it''s hardly at the end of its life yet. :-) -George On Thu, Jan 13, 2011 at 12:33 PM, Keir Fraser <keir@xen.org> wrote:> On 13/01/2011 05:19, "IWAMOTO Toshihiro" <iwamoto@valinux.co.jp> wrote: > >> Please backport the following xen-4.0-testing.hg changesets to >> xen-3.4. They are necessary for kexec/kdump to work on MP guests. >> Backporting is mostly obvious but the changeset 19691:c4b2a3c9a61a, >> which is slightly different from 19912:721c14d7f60b, will cause a >> conflict. > > I no longer maintain 3.4 and I''m not accepting patches to it. > > -- Keir > >> A combined diff which is ready to be applyed on xen-3.4-testing.hg is >> also attached. >> >> changeset: 19877:80839a223746 >> user: Keir Fraser <keir.fraser@citrix.com> >> date: Wed Jul 01 20:22:29 2009 +0100 >> files: tools/firmware/hvmloader/hvmloader.c >> tools/firmware/hvmloader/mp_tables.c xen/arch/x86/hvm/vioapic.c >> xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpic.c >> xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/vlapic.h >> description: >> x86 hvm: Allow delivery of legacy 8259 interrupts to VCPUs != 0. >> >> changeset: 19906:2fadef1b008f >> user: Keir Fraser <keir.fraser@citrix.com> >> date: Tue Jul 07 14:08:47 2009 +0100 >> files: xen/arch/x86/hvm/hpet.c xen/include/asm-x86/hvm/vpt.h >> description: >> x86,hvm: cleanup hpet.c vcpu handling same as i8254.c/rtc.c >> >> - introduce macros: domain_vhpet, vcpu_vhpet, vhpet_domain, vhpet_vcpu >> - remove *vcpu field from struct HPETState >> - modify guest_time_hpet() takes *vhpet instead of *vcpu as 1st >> - argument >> >> changeset: 19907:a29bb4efff00 >> user: Keir Fraser <keir.fraser@citrix.com> >> date: Tue Jul 07 14:21:16 2009 +0100 >> files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c >> xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c >> xen/arch/x86/hvm/vpt.c xen/include/asm-x86/hvm/vpt.h >> description: >> x86,hvm: Allow delivery of timer interrupts to VCPUs != 0 >> >> This patch is needed for kexec/kdump since VCPU#0 is halted. >> >> changeset: 19912:721c14d7f60b >> user: Keir Fraser <keir.fraser@citrix.com> >> date: Wed Jul 08 14:22:00 2009 +0100 >> files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c >> xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c >> xen/include/asm-x86/hvm/vlapic.h >> description: >> x86 hvm: Use ''x'' as parameter name for macros converting between >> {vcpu,domain} and {vlapic,vpic,vrtc,hpet}. Completely avoids >> accidental aliasing. >> >> >> >> diff -r 14709d196e43 tools/firmware/hvmloader/hvmloader.c >> --- a/tools/firmware/hvmloader/hvmloader.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/tools/firmware/hvmloader/hvmloader.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -141,13 +141,17 @@ >> >> 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 14709d196e43 tools/firmware/hvmloader/mp_tables.c >> --- a/tools/firmware/hvmloader/mp_tables.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/tools/firmware/hvmloader/mp_tables.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -233,21 +233,6 @@ >> } >> >> >> -/* 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 *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 @@ >> 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 14709d196e43 xen/arch/x86/hvm/hpet.c >> --- a/xen/arch/x86/hvm/hpet.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/arch/x86/hvm/hpet.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -24,6 +24,12 @@ >> #include <xen/sched.h> >> #include <xen/event.h> >> >> +#define domain_vhpet(x) (&(x)->arch.hvm_domain.pl_time.vhpet) >> +#define vcpu_vhpet(x) (domain_vhpet((x)->domain)) >> +#define vhpet_domain(x) (container_of((x), struct domain, \ >> + arch.hvm_domain.pl_time.vhpet)) >> +#define vhpet_vcpu(x) (pt_global_vcpu_target(vhpet_domain(x))) >> + >> #define HPET_BASE_ADDRESS 0xfed00000ULL >> #define HPET_MMAP_SIZE 1024 >> #define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */ >> @@ -31,7 +37,8 @@ >> >> /* Frequency_of_Xen_systeme_time / frequency_of_HPET = 16 */ >> #define STIME_PER_HPET_TICK 16 >> -#define guest_time_hpet(v) (hvm_get_guest_time(v) / STIME_PER_HPET_TICK) >> +#define guest_time_hpet(hpet) \ >> + (hvm_get_guest_time(vhpet_vcpu(hpet)) / STIME_PER_HPET_TICK) >> >> #define HPET_ID 0x000 >> #define HPET_PERIOD 0x004 >> @@ -94,7 +101,7 @@ >> ASSERT(spin_is_locked(&h->lock)); >> >> if ( hpet_enabled(h) ) >> - return guest_time_hpet(h->vcpu) + h->mc_offset; >> + return guest_time_hpet(h) + h->mc_offset; >> else >> return h->hpet.mc64; >> } >> @@ -176,7 +183,7 @@ >> struct vcpu *v, unsigned long addr, unsigned long length, >> unsigned long *pval) >> { >> - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; >> + HPETState *h = vcpu_vhpet(v); >> unsigned long result; >> uint64_t val; >> >> @@ -230,7 +237,7 @@ >> { >> /* HPET specification requires PIT shouldn''t generate >> * interrupts if LegacyReplacementRoute is set for timer0 */ >> - PITState *pit = &h->vcpu->domain->arch.hvm_domain.pl_time.vpit; >> + PITState *pit = &vhpet_domain(h)->arch.hvm_domain.pl_time.vpit; >> pit_stop_channel0_irq(pit); >> } >> >> @@ -272,7 +279,7 @@ >> * being enabled (now). >> */ >> oneshot = !timer_is_periodic(h, tn); >> - create_periodic_time(h->vcpu, &h->pt[tn], >> + create_periodic_time(vhpet_vcpu(h), &h->pt[tn], >> hpet_tick_to_ns(h, diff), >> oneshot ? 0 : hpet_tick_to_ns(h, >> h->hpet.period[tn]), >> irq, NULL, NULL); >> @@ -290,7 +297,7 @@ >> struct vcpu *v, unsigned long addr, >> unsigned long length, unsigned long val) >> { >> - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; >> + HPETState *h = vcpu_vhpet(v); >> uint64_t old_val, new_val; >> int tn, i; >> >> @@ -323,7 +330,7 @@ >> if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) ) >> { >> /* Enable main counter and interrupt generation. */ >> - h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu); >> + h->mc_offset = h->hpet.mc64 - guest_time_hpet(h); >> for ( i = 0; i < HPET_TIMER_NUM; i++ ) >> { >> h->hpet.comparator64[i] >> @@ -337,7 +344,7 @@ >> else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) >> ) >> { >> /* Halt main counter and disable interrupt generation. */ >> - h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu); >> + h->hpet.mc64 = h->mc_offset + guest_time_hpet(h); >> for ( i = 0; i < HPET_TIMER_NUM; i++ ) >> if ( timer_enabled(h, i) ) >> set_stop_timer(i); >> @@ -487,13 +494,13 @@ >> >> static int hpet_save(struct domain *d, hvm_domain_context_t *h) >> { >> - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; >> + HPETState *hp = domain_vhpet(d); >> int rc; >> >> spin_lock(&hp->lock); >> >> /* Write the proper value into the main counter */ >> - hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu); >> + hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp); >> >> /* Save the HPET registers */ >> rc = _hvm_init_entry(h, HVM_SAVE_CODE(HPET), 0, HVM_SAVE_LENGTH(HPET)); >> @@ -531,7 +538,7 @@ >> >> static int hpet_load(struct domain *d, hvm_domain_context_t *h) >> { >> - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; >> + HPETState *hp = domain_vhpet(d); >> struct hvm_hw_hpet *rec; >> uint64_t cmp; >> int i; >> @@ -572,7 +579,7 @@ >> #undef C >> >> /* Recalculate the offset between the main counter and guest time */ >> - hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu); >> + hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp); >> >> /* restart all timers */ >> >> @@ -590,14 +597,13 @@ >> >> void hpet_init(struct vcpu *v) >> { >> - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; >> + HPETState *h = vcpu_vhpet(v); >> int i; >> >> memset(h, 0, sizeof(HPETState)); >> >> spin_lock_init(&h->lock); >> >> - h->vcpu = v; >> h->stime_freq = S_TO_NS; >> >> h->hpet_to_ns_scale = ((S_TO_NS * STIME_PER_HPET_TICK) << 10) / >> h->stime_freq; >> @@ -622,7 +628,7 @@ >> void hpet_deinit(struct domain *d) >> { >> int i; >> - HPETState *h = &d->arch.hvm_domain.pl_time.vhpet; >> + HPETState *h = domain_vhpet(d); >> >> spin_lock(&h->lock); >> >> diff -r 14709d196e43 xen/arch/x86/hvm/i8254.c >> --- a/xen/arch/x86/hvm/i8254.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/arch/x86/hvm/i8254.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -42,7 +42,7 @@ >> #define vcpu_vpit(x) (domain_vpit((x)->domain)) >> #define vpit_domain(x) (container_of((x), struct domain, \ >> arch.hvm_domain.pl_time.vpit)) >> -#define vpit_vcpu(x) (vpit_domain(x)->vcpu[0]) >> +#define vpit_vcpu(x) (pt_global_vcpu_target(vpit_domain(x))) >> >> #define RW_STATE_LSB 1 >> #define RW_STATE_MSB 2 >> diff -r 14709d196e43 xen/arch/x86/hvm/rtc.c >> --- a/xen/arch/x86/hvm/rtc.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/arch/x86/hvm/rtc.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -32,7 +32,7 @@ >> #define vcpu_vrtc(x) (domain_vrtc((x)->domain)) >> #define vrtc_domain(x) (container_of((x), struct domain, \ >> arch.hvm_domain.pl_time.vrtc)) >> -#define vrtc_vcpu(x) (vrtc_domain(x)->vcpu[0]) >> +#define vrtc_vcpu(x) (pt_global_vcpu_target(vrtc_domain(x))) >> >> static void rtc_periodic_cb(struct vcpu *v, void *opaque) >> { >> diff -r 14709d196e43 xen/arch/x86/hvm/vioapic.c >> --- a/xen/arch/x86/hvm/vioapic.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/arch/x86/hvm/vioapic.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -146,10 +146,14 @@ >> >> *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_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 @@ >> 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 14709d196e43 xen/arch/x86/hvm/vlapic.c >> --- a/xen/arch/x86/hvm/vlapic.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/arch/x86/hvm/vlapic.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -697,6 +697,8 @@ >> 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,46 @@ >> "apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr); >> } >> >> +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); >> + 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) >> { >> - struct vlapic *vlapic = vcpu_vlapic(v); >> - uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0); >> + return ((v == v->domain->arch.hvm_domain.i8259_target) && >> + __vlapic_accept_pic_intr(v)); >> +} >> >> - /* >> - * 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) || >> - vlapic_hw_disabled(vlapic))); >> +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: >> + if ( d->arch.hvm_domain.i8259_target == v ) >> + return; >> + d->arch.hvm_domain.i8259_target = v; >> + pt_adjust_global_vcpu_target(v); >> } >> >> int vlapic_has_pending_irq(struct vcpu *v) >> @@ -946,6 +976,7 @@ >> if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 ) >> return -EINVAL; >> >> + vlapic_adjust_i8259_target(d); >> lapic_rearm(s); >> return 0; >> } >> diff -r 14709d196e43 xen/arch/x86/hvm/vpic.c >> --- a/xen/arch/x86/hvm/vpic.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/arch/x86/hvm/vpic.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -109,9 +109,9 @@ >> { >> if ( vpic->is_master ) >> { >> - /* Master INT line is connected to VCPU0''s VLAPIC LVT0. */ >> - struct vcpu *v = vpic_domain(vpic)->vcpu[0]; >> - 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 14709d196e43 xen/arch/x86/hvm/vpt.c >> --- a/xen/arch/x86/hvm/vpt.c Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/arch/x86/hvm/vpt.c Thu Jan 13 14:17:37 2011 +0900 >> @@ -434,3 +434,53 @@ >> */ >> kill_timer(&pt->timer); >> } >> + >> +static void pt_adjust_vcpu(struct periodic_time *pt, struct vcpu *v) >> +{ >> + int on_list; >> + >> + ASSERT(pt->source == PTSRC_isa); >> + >> + if ( pt->vcpu == NULL ) >> + return; >> + >> + pt_lock(pt); >> + on_list = pt->on_list; >> + if ( pt->on_list ) >> + list_del(&pt->list); >> + pt->on_list = 0; >> + pt_unlock(pt); >> + >> + spin_lock(&v->arch.hvm_vcpu.tm_lock); >> + pt->vcpu = v; >> + if ( on_list ) >> + { >> + pt->on_list = 1; >> + list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); >> + >> + migrate_timer(&pt->timer, v->processor); >> + } >> + spin_unlock(&v->arch.hvm_vcpu.tm_lock); >> +} >> + >> +void pt_adjust_global_vcpu_target(struct vcpu *v) >> +{ >> + struct pl_time *pl_time = &v->domain->arch.hvm_domain.pl_time; >> + int i; >> + >> + if ( v == NULL ) >> + return; >> + >> + spin_lock(&pl_time->vpit.lock); >> + pt_adjust_vcpu(&pl_time->vpit.pt0, v); >> + spin_unlock(&pl_time->vpit.lock); >> + >> + spin_lock(&pl_time->vrtc.lock); >> + pt_adjust_vcpu(&pl_time->vrtc.pt, v); >> + spin_unlock(&pl_time->vrtc.lock); >> + >> + spin_lock(&pl_time->vhpet.lock); >> + for ( i = 0; i < HPET_TIMER_NUM; i++ ) >> + pt_adjust_vcpu(&pl_time->vhpet.pt[i], v); >> + spin_unlock(&pl_time->vhpet.lock); >> +} >> diff -r 14709d196e43 xen/include/asm-x86/hvm/domain.h >> --- a/xen/include/asm-x86/hvm/domain.h Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/include/asm-x86/hvm/domain.h Thu Jan 13 14:17:37 2011 +0900 >> @@ -56,6 +56,9 @@ >> 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 14709d196e43 xen/include/asm-x86/hvm/vlapic.h >> --- a/xen/include/asm-x86/hvm/vlapic.h Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/include/asm-x86/hvm/vlapic.h Thu Jan 13 14:17:37 2011 +0900 >> @@ -92,6 +92,8 @@ >> >> 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); >> diff -r 14709d196e43 xen/include/asm-x86/hvm/vpt.h >> --- a/xen/include/asm-x86/hvm/vpt.h Wed Jun 30 18:26:13 2010 +0100 >> +++ b/xen/include/asm-x86/hvm/vpt.h Thu Jan 13 14:17:37 2011 +0900 >> @@ -92,7 +92,6 @@ >> >> typedef struct HPETState { >> struct hpet_registers hpet; >> - struct vcpu *vcpu; >> uint64_t stime_freq; >> uint64_t hpet_to_ns_scale; /* hpet ticks to ns (multiplied by 2^10) */ >> uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns */ >> @@ -145,6 +144,10 @@ >> void pt_reset(struct vcpu *v); >> void pt_migrate(struct vcpu *v); >> >> +void pt_adjust_global_vcpu_target(struct vcpu *v); >> +#define pt_global_vcpu_target(d) \ >> + ((d)->arch.hvm_domain.i8259_target ? : (d)->vcpu ? (d)->vcpu[0] : NULL) >> + >> /* Is given periodic timer active? */ >> #define pt_active(pt) ((pt)->on_list) >> >> >> _______________________________________________ >> Xen-devel mailing list >> Xen-devel@lists.xensource.com >> http://lists.xensource.com/xen-devel > > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel >_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2011-Jan-14 12:24 UTC
Re: [Xen-devel] [PATCH] MP interrupt delivery fix for xen-3.4
Sure, if someone we deem competent wants to step up, that''d be absolutely fine. -- Keir On 14/01/2011 12:13, "George Dunlap" <George.Dunlap@eu.citrix.com> wrote:> Would it be reasonable to ask if anyone is willing to step up as a > "legacy/stable maintainer"? Given that 3.4 is still in the > just-released Citrix product, it''s hardly at the end of its life yet. > :-) > > -George > > On Thu, Jan 13, 2011 at 12:33 PM, Keir Fraser <keir@xen.org> wrote: >> On 13/01/2011 05:19, "IWAMOTO Toshihiro" <iwamoto@valinux.co.jp> wrote: >> >>> Please backport the following xen-4.0-testing.hg changesets to >>> xen-3.4. They are necessary for kexec/kdump to work on MP guests. >>> Backporting is mostly obvious but the changeset 19691:c4b2a3c9a61a, >>> which is slightly different from 19912:721c14d7f60b, will cause a >>> conflict. >> >> I no longer maintain 3.4 and I''m not accepting patches to it. >> >> -- Keir >> >>> A combined diff which is ready to be applyed on xen-3.4-testing.hg is >>> also attached. >>> >>> changeset: 19877:80839a223746 >>> user: Keir Fraser <keir.fraser@citrix.com> >>> date: Wed Jul 01 20:22:29 2009 +0100 >>> files: tools/firmware/hvmloader/hvmloader.c >>> tools/firmware/hvmloader/mp_tables.c xen/arch/x86/hvm/vioapic.c >>> xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpic.c >>> xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/vlapic.h >>> description: >>> x86 hvm: Allow delivery of legacy 8259 interrupts to VCPUs != 0. >>> >>> changeset: 19906:2fadef1b008f >>> user: Keir Fraser <keir.fraser@citrix.com> >>> date: Tue Jul 07 14:08:47 2009 +0100 >>> files: xen/arch/x86/hvm/hpet.c xen/include/asm-x86/hvm/vpt.h >>> description: >>> x86,hvm: cleanup hpet.c vcpu handling same as i8254.c/rtc.c >>> >>> - introduce macros: domain_vhpet, vcpu_vhpet, vhpet_domain, vhpet_vcpu >>> - remove *vcpu field from struct HPETState >>> - modify guest_time_hpet() takes *vhpet instead of *vcpu as 1st >>> - argument >>> >>> changeset: 19907:a29bb4efff00 >>> user: Keir Fraser <keir.fraser@citrix.com> >>> date: Tue Jul 07 14:21:16 2009 +0100 >>> files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c >>> xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c >>> xen/arch/x86/hvm/vpt.c xen/include/asm-x86/hvm/vpt.h >>> description: >>> x86,hvm: Allow delivery of timer interrupts to VCPUs != 0 >>> >>> This patch is needed for kexec/kdump since VCPU#0 is halted. >>> >>> changeset: 19912:721c14d7f60b >>> user: Keir Fraser <keir.fraser@citrix.com> >>> date: Wed Jul 08 14:22:00 2009 +0100 >>> files: xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/i8254.c >>> xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c >>> xen/include/asm-x86/hvm/vlapic.h >>> description: >>> x86 hvm: Use ''x'' as parameter name for macros converting between >>> {vcpu,domain} and {vlapic,vpic,vrtc,hpet}. Completely avoids >>> accidental aliasing. >>> >>> >>> >>> diff -r 14709d196e43 tools/firmware/hvmloader/hvmloader.c >>> --- a/tools/firmware/hvmloader/hvmloader.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/tools/firmware/hvmloader/hvmloader.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -141,13 +141,17 @@ >>> >>> 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 14709d196e43 tools/firmware/hvmloader/mp_tables.c >>> --- a/tools/firmware/hvmloader/mp_tables.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/tools/firmware/hvmloader/mp_tables.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -233,21 +233,6 @@ >>> } >>> >>> >>> -/* 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 *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 @@ >>> 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 14709d196e43 xen/arch/x86/hvm/hpet.c >>> --- a/xen/arch/x86/hvm/hpet.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/arch/x86/hvm/hpet.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -24,6 +24,12 @@ >>> #include <xen/sched.h> >>> #include <xen/event.h> >>> >>> +#define domain_vhpet(x) (&(x)->arch.hvm_domain.pl_time.vhpet) >>> +#define vcpu_vhpet(x) (domain_vhpet((x)->domain)) >>> +#define vhpet_domain(x) (container_of((x), struct domain, \ >>> + arch.hvm_domain.pl_time.vhpet)) >>> +#define vhpet_vcpu(x) (pt_global_vcpu_target(vhpet_domain(x))) >>> + >>> #define HPET_BASE_ADDRESS 0xfed00000ULL >>> #define HPET_MMAP_SIZE 1024 >>> #define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */ >>> @@ -31,7 +37,8 @@ >>> >>> /* Frequency_of_Xen_systeme_time / frequency_of_HPET = 16 */ >>> #define STIME_PER_HPET_TICK 16 >>> -#define guest_time_hpet(v) (hvm_get_guest_time(v) / STIME_PER_HPET_TICK) >>> +#define guest_time_hpet(hpet) \ >>> + (hvm_get_guest_time(vhpet_vcpu(hpet)) / STIME_PER_HPET_TICK) >>> >>> #define HPET_ID 0x000 >>> #define HPET_PERIOD 0x004 >>> @@ -94,7 +101,7 @@ >>> ASSERT(spin_is_locked(&h->lock)); >>> >>> if ( hpet_enabled(h) ) >>> - return guest_time_hpet(h->vcpu) + h->mc_offset; >>> + return guest_time_hpet(h) + h->mc_offset; >>> else >>> return h->hpet.mc64; >>> } >>> @@ -176,7 +183,7 @@ >>> struct vcpu *v, unsigned long addr, unsigned long length, >>> unsigned long *pval) >>> { >>> - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; >>> + HPETState *h = vcpu_vhpet(v); >>> unsigned long result; >>> uint64_t val; >>> >>> @@ -230,7 +237,7 @@ >>> { >>> /* HPET specification requires PIT shouldn''t generate >>> * interrupts if LegacyReplacementRoute is set for timer0 */ >>> - PITState *pit = &h->vcpu->domain->arch.hvm_domain.pl_time.vpit; >>> + PITState *pit = &vhpet_domain(h)->arch.hvm_domain.pl_time.vpit; >>> pit_stop_channel0_irq(pit); >>> } >>> >>> @@ -272,7 +279,7 @@ >>> * being enabled (now). >>> */ >>> oneshot = !timer_is_periodic(h, tn); >>> - create_periodic_time(h->vcpu, &h->pt[tn], >>> + create_periodic_time(vhpet_vcpu(h), &h->pt[tn], >>> hpet_tick_to_ns(h, diff), >>> oneshot ? 0 : hpet_tick_to_ns(h, >>> h->hpet.period[tn]), >>> irq, NULL, NULL); >>> @@ -290,7 +297,7 @@ >>> struct vcpu *v, unsigned long addr, >>> unsigned long length, unsigned long val) >>> { >>> - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; >>> + HPETState *h = vcpu_vhpet(v); >>> uint64_t old_val, new_val; >>> int tn, i; >>> >>> @@ -323,7 +330,7 @@ >>> if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) ) >>> { >>> /* Enable main counter and interrupt generation. */ >>> - h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu); >>> + h->mc_offset = h->hpet.mc64 - guest_time_hpet(h); >>> for ( i = 0; i < HPET_TIMER_NUM; i++ ) >>> { >>> h->hpet.comparator64[i] >>> @@ -337,7 +344,7 @@ >>> else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & >>> HPET_CFG_ENABLE) >>> ) >>> { >>> /* Halt main counter and disable interrupt generation. */ >>> - h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu); >>> + h->hpet.mc64 = h->mc_offset + guest_time_hpet(h); >>> for ( i = 0; i < HPET_TIMER_NUM; i++ ) >>> if ( timer_enabled(h, i) ) >>> set_stop_timer(i); >>> @@ -487,13 +494,13 @@ >>> >>> static int hpet_save(struct domain *d, hvm_domain_context_t *h) >>> { >>> - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; >>> + HPETState *hp = domain_vhpet(d); >>> int rc; >>> >>> spin_lock(&hp->lock); >>> >>> /* Write the proper value into the main counter */ >>> - hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu); >>> + hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp); >>> >>> /* Save the HPET registers */ >>> rc = _hvm_init_entry(h, HVM_SAVE_CODE(HPET), 0, HVM_SAVE_LENGTH(HPET)); >>> @@ -531,7 +538,7 @@ >>> >>> static int hpet_load(struct domain *d, hvm_domain_context_t *h) >>> { >>> - HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; >>> + HPETState *hp = domain_vhpet(d); >>> struct hvm_hw_hpet *rec; >>> uint64_t cmp; >>> int i; >>> @@ -572,7 +579,7 @@ >>> #undef C >>> >>> /* Recalculate the offset between the main counter and guest time */ >>> - hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu); >>> + hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp); >>> >>> /* restart all timers */ >>> >>> @@ -590,14 +597,13 @@ >>> >>> void hpet_init(struct vcpu *v) >>> { >>> - HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; >>> + HPETState *h = vcpu_vhpet(v); >>> int i; >>> >>> memset(h, 0, sizeof(HPETState)); >>> >>> spin_lock_init(&h->lock); >>> >>> - h->vcpu = v; >>> h->stime_freq = S_TO_NS; >>> >>> h->hpet_to_ns_scale = ((S_TO_NS * STIME_PER_HPET_TICK) << 10) / >>> h->stime_freq; >>> @@ -622,7 +628,7 @@ >>> void hpet_deinit(struct domain *d) >>> { >>> int i; >>> - HPETState *h = &d->arch.hvm_domain.pl_time.vhpet; >>> + HPETState *h = domain_vhpet(d); >>> >>> spin_lock(&h->lock); >>> >>> diff -r 14709d196e43 xen/arch/x86/hvm/i8254.c >>> --- a/xen/arch/x86/hvm/i8254.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/arch/x86/hvm/i8254.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -42,7 +42,7 @@ >>> #define vcpu_vpit(x) (domain_vpit((x)->domain)) >>> #define vpit_domain(x) (container_of((x), struct domain, \ >>> arch.hvm_domain.pl_time.vpit)) >>> -#define vpit_vcpu(x) (vpit_domain(x)->vcpu[0]) >>> +#define vpit_vcpu(x) (pt_global_vcpu_target(vpit_domain(x))) >>> >>> #define RW_STATE_LSB 1 >>> #define RW_STATE_MSB 2 >>> diff -r 14709d196e43 xen/arch/x86/hvm/rtc.c >>> --- a/xen/arch/x86/hvm/rtc.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/arch/x86/hvm/rtc.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -32,7 +32,7 @@ >>> #define vcpu_vrtc(x) (domain_vrtc((x)->domain)) >>> #define vrtc_domain(x) (container_of((x), struct domain, \ >>> arch.hvm_domain.pl_time.vrtc)) >>> -#define vrtc_vcpu(x) (vrtc_domain(x)->vcpu[0]) >>> +#define vrtc_vcpu(x) (pt_global_vcpu_target(vrtc_domain(x))) >>> >>> static void rtc_periodic_cb(struct vcpu *v, void *opaque) >>> { >>> diff -r 14709d196e43 xen/arch/x86/hvm/vioapic.c >>> --- a/xen/arch/x86/hvm/vioapic.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/arch/x86/hvm/vioapic.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -146,10 +146,14 @@ >>> >>> *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_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 @@ >>> 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 14709d196e43 xen/arch/x86/hvm/vlapic.c >>> --- a/xen/arch/x86/hvm/vlapic.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/arch/x86/hvm/vlapic.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -697,6 +697,8 @@ >>> 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,46 @@ >>> "apic base msr is 0x%016"PRIx64, vlapic->hw.apic_base_msr); >>> } >>> >>> +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); >>> + 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) >>> { >>> - struct vlapic *vlapic = vcpu_vlapic(v); >>> - uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0); >>> + return ((v == v->domain->arch.hvm_domain.i8259_target) && >>> + __vlapic_accept_pic_intr(v)); >>> +} >>> >>> - /* >>> - * 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) >>> || >>> - vlapic_hw_disabled(vlapic))); >>> +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: >>> + if ( d->arch.hvm_domain.i8259_target == v ) >>> + return; >>> + d->arch.hvm_domain.i8259_target = v; >>> + pt_adjust_global_vcpu_target(v); >>> } >>> >>> int vlapic_has_pending_irq(struct vcpu *v) >>> @@ -946,6 +976,7 @@ >>> if ( hvm_load_entry(LAPIC_REGS, h, s->regs) != 0 ) >>> return -EINVAL; >>> >>> + vlapic_adjust_i8259_target(d); >>> lapic_rearm(s); >>> return 0; >>> } >>> diff -r 14709d196e43 xen/arch/x86/hvm/vpic.c >>> --- a/xen/arch/x86/hvm/vpic.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/arch/x86/hvm/vpic.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -109,9 +109,9 @@ >>> { >>> if ( vpic->is_master ) >>> { >>> - /* Master INT line is connected to VCPU0''s VLAPIC LVT0. */ >>> - struct vcpu *v = vpic_domain(vpic)->vcpu[0]; >>> - 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 14709d196e43 xen/arch/x86/hvm/vpt.c >>> --- a/xen/arch/x86/hvm/vpt.c Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/arch/x86/hvm/vpt.c Thu Jan 13 14:17:37 2011 +0900 >>> @@ -434,3 +434,53 @@ >>> */ >>> kill_timer(&pt->timer); >>> } >>> + >>> +static void pt_adjust_vcpu(struct periodic_time *pt, struct vcpu *v) >>> +{ >>> + int on_list; >>> + >>> + ASSERT(pt->source == PTSRC_isa); >>> + >>> + if ( pt->vcpu == NULL ) >>> + return; >>> + >>> + pt_lock(pt); >>> + on_list = pt->on_list; >>> + if ( pt->on_list ) >>> + list_del(&pt->list); >>> + pt->on_list = 0; >>> + pt_unlock(pt); >>> + >>> + spin_lock(&v->arch.hvm_vcpu.tm_lock); >>> + pt->vcpu = v; >>> + if ( on_list ) >>> + { >>> + pt->on_list = 1; >>> + list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); >>> + >>> + migrate_timer(&pt->timer, v->processor); >>> + } >>> + spin_unlock(&v->arch.hvm_vcpu.tm_lock); >>> +} >>> + >>> +void pt_adjust_global_vcpu_target(struct vcpu *v) >>> +{ >>> + struct pl_time *pl_time = &v->domain->arch.hvm_domain.pl_time; >>> + int i; >>> + >>> + if ( v == NULL ) >>> + return; >>> + >>> + spin_lock(&pl_time->vpit.lock); >>> + pt_adjust_vcpu(&pl_time->vpit.pt0, v); >>> + spin_unlock(&pl_time->vpit.lock); >>> + >>> + spin_lock(&pl_time->vrtc.lock); >>> + pt_adjust_vcpu(&pl_time->vrtc.pt, v); >>> + spin_unlock(&pl_time->vrtc.lock); >>> + >>> + spin_lock(&pl_time->vhpet.lock); >>> + for ( i = 0; i < HPET_TIMER_NUM; i++ ) >>> + pt_adjust_vcpu(&pl_time->vhpet.pt[i], v); >>> + spin_unlock(&pl_time->vhpet.lock); >>> +} >>> diff -r 14709d196e43 xen/include/asm-x86/hvm/domain.h >>> --- a/xen/include/asm-x86/hvm/domain.h Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/include/asm-x86/hvm/domain.h Thu Jan 13 14:17:37 2011 +0900 >>> @@ -56,6 +56,9 @@ >>> 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 14709d196e43 xen/include/asm-x86/hvm/vlapic.h >>> --- a/xen/include/asm-x86/hvm/vlapic.h Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/include/asm-x86/hvm/vlapic.h Thu Jan 13 14:17:37 2011 +0900 >>> @@ -92,6 +92,8 @@ >>> >>> 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); >>> diff -r 14709d196e43 xen/include/asm-x86/hvm/vpt.h >>> --- a/xen/include/asm-x86/hvm/vpt.h Wed Jun 30 18:26:13 2010 +0100 >>> +++ b/xen/include/asm-x86/hvm/vpt.h Thu Jan 13 14:17:37 2011 +0900 >>> @@ -92,7 +92,6 @@ >>> >>> typedef struct HPETState { >>> struct hpet_registers hpet; >>> - struct vcpu *vcpu; >>> uint64_t stime_freq; >>> uint64_t hpet_to_ns_scale; /* hpet ticks to ns (multiplied by 2^10) */ >>> uint64_t hpet_to_ns_limit; /* max hpet ticks convertable to ns */ >>> @@ -145,6 +144,10 @@ >>> void pt_reset(struct vcpu *v); >>> void pt_migrate(struct vcpu *v); >>> >>> +void pt_adjust_global_vcpu_target(struct vcpu *v); >>> +#define pt_global_vcpu_target(d) \ >>> + ((d)->arch.hvm_domain.i8259_target ? : (d)->vcpu ? (d)->vcpu[0] : NULL) >>> + >>> /* Is given periodic timer active? */ >>> #define pt_active(pt) ((pt)->on_list) >>> >>> >>> _______________________________________________ >>> Xen-devel mailing list >>> Xen-devel@lists.xensource.com >>> http://lists.xensource.com/xen-devel >> >> >> >> _______________________________________________ >> Xen-devel mailing list >> Xen-devel@lists.xensource.com >> http://lists.xensource.com/xen-devel >>_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel