[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Save/restore cleanups 03: IRQ
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Date 1169291860 0 # Node ID 2457741f4ec308b1dd3368296df88a3806249afe # Parent dccdc3ee0efca7894870e1699233eca1d9bfc463 [HVM] Save/restore cleanups 03: IRQ IRQ, PIC, IOAPIC and LAPIC Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/hpet.c | 5 - xen/arch/x86/hvm/hvm.c | 2 xen/arch/x86/hvm/irq.c | 52 +++++------ xen/arch/x86/hvm/svm/svm.c | 2 xen/arch/x86/hvm/vioapic.c | 119 ++++++++----------------- xen/arch/x86/hvm/vlapic.c | 99 +++++++++------------ xen/arch/x86/hvm/vmx/vmx.c | 2 xen/arch/x86/hvm/vpic.c | 84 +++++------------ xen/include/asm-x86/hvm/domain.h | 7 + xen/include/asm-x86/hvm/irq.h | 65 ------------- xen/include/asm-x86/hvm/vioapic.h | 41 -------- xen/include/asm-x86/hvm/vlapic.h | 25 ++--- xen/include/asm-x86/hvm/vpic.h | 46 --------- xen/include/public/hvm/save.h | 178 +++++++++++++++++++++++++++++++++++++- 14 files changed, 334 insertions(+), 393 deletions(-) diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/hpet.c --- a/xen/arch/x86/hvm/hpet.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/hpet.c Sat Jan 20 11:17:40 2007 +0000 @@ -314,7 +314,6 @@ static void hpet_route_interrupt(HPETSta { unsigned int tn_int_route = timer_int_route(h, tn); struct domain *d = h->vcpu->domain; - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) ) { @@ -336,9 +335,9 @@ static void hpet_route_interrupt(HPETSta } /* We only support edge-triggered interrupt now */ - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); vioapic_irq_positive_edge(d, tn_int_route); - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } static void hpet_timer_fn(void *opaque) diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/hvm.c Sat Jan 20 11:17:40 2007 +0000 @@ -135,7 +135,7 @@ int hvm_domain_initialise(struct domain spin_lock_init(&d->arch.hvm_domain.pbuf_lock); spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); - spin_lock_init(&d->arch.hvm_domain.irq.lock); + spin_lock_init(&d->arch.hvm_domain.irq_lock); rc = shadow_enable(d, SHM2_refcounts|SHM2_translate|SHM2_external); if ( rc != 0 ) diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/irq.c --- a/xen/arch/x86/hvm/irq.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/irq.c Sat Jan 20 11:17:40 2007 +0000 @@ -28,7 +28,7 @@ static void __hvm_pci_intx_assert( static void __hvm_pci_intx_assert( struct domain *d, unsigned int device, unsigned int intx) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; unsigned int gsi, link, isa_irq; ASSERT((device <= 31) && (intx <= 3)); @@ -53,17 +53,15 @@ void hvm_pci_intx_assert( void hvm_pci_intx_assert( struct domain *d, unsigned int device, unsigned int intx) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); __hvm_pci_intx_assert(d, device, intx); - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } static void __hvm_pci_intx_deassert( struct domain *d, unsigned int device, unsigned int intx) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; unsigned int gsi, link, isa_irq; ASSERT((device <= 31) && (intx <= 3)); @@ -84,22 +82,20 @@ void hvm_pci_intx_deassert( void hvm_pci_intx_deassert( struct domain *d, unsigned int device, unsigned int intx) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); __hvm_pci_intx_deassert(d, device, intx); - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } void hvm_isa_irq_assert( struct domain *d, unsigned int isa_irq) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); ASSERT(isa_irq <= 15); - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq) && (hvm_irq->gsi_assert_count[gsi]++ == 0) ) @@ -108,31 +104,31 @@ void hvm_isa_irq_assert( vpic_irq_positive_edge(d, isa_irq); } - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } void hvm_isa_irq_deassert( struct domain *d, unsigned int isa_irq) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); ASSERT(isa_irq <= 15); - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq) && (--hvm_irq->gsi_assert_count[gsi] == 0) ) vpic_irq_negative_edge(d, isa_irq); - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } void hvm_set_callback_irq_level(void) { struct vcpu *v = current; struct domain *d = v->domain; - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; unsigned int gsi, pdev, pintx, asserted; /* Fast lock-free tests. */ @@ -140,7 +136,7 @@ void hvm_set_callback_irq_level(void) (hvm_irq->callback_via_type == HVMIRQ_callback_none) ) return; - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); /* NB. Do not check the evtchn_upcall_mask. It is not used in HVM mode. */ asserted = !!vcpu_info(v, evtchn_upcall_pending); @@ -177,17 +173,17 @@ void hvm_set_callback_irq_level(void) } out: - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; u8 old_isa_irq; ASSERT((link <= 3) && (isa_irq <= 15)); - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); old_isa_irq = hvm_irq->pci_link_route[link]; if ( old_isa_irq == isa_irq ) @@ -207,7 +203,7 @@ void hvm_set_pci_link_route(struct domai } out: - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); dprintk(XENLOG_G_INFO, "Dom%u PCI link %u changed %u -> %u\n", d->domain_id, link, old_isa_irq, isa_irq); @@ -215,7 +211,7 @@ void hvm_set_pci_link_route(struct domai void hvm_set_callback_via(struct domain *d, uint64_t via) { - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; unsigned int gsi=0, pdev=0, pintx=0; uint8_t via_type; @@ -224,7 +220,7 @@ void hvm_set_callback_via(struct domain (via_type > HVMIRQ_callback_pci_intx) ) via_type = HVMIRQ_callback_none; - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); /* Tear down old callback via. */ if ( hvm_irq->callback_via_asserted ) @@ -271,7 +267,7 @@ void hvm_set_callback_via(struct domain break; } - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); dprintk(XENLOG_G_INFO, "Dom%u callback via changed to ", d->domain_id); switch ( via_type ) @@ -300,7 +296,7 @@ int cpu_has_pending_irq(struct vcpu *v) if ( !vlapic_accept_pic_intr(v) ) return 0; - return plat->irq.vpic[0].int_output; + return plat->vpic[0].int_output; } int cpu_get_interrupt(struct vcpu *v, int *type) @@ -322,7 +318,7 @@ int get_isa_irq_vector(struct vcpu *v, i unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); if ( type == APIC_DM_EXTINT ) - return (v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].irq_base + return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base + (isa_irq & 7)); return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector; @@ -335,7 +331,7 @@ int is_isa_irq_masked(struct vcpu *v, in if ( is_lvtt(v, isa_irq) ) return !is_lvtt_enabled(v); - return ((v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].imr & + return ((v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr & (1 << (isa_irq & 7))) && domain_vioapic(v->domain)->redirtbl[gsi].fields.mask); } diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Sat Jan 20 11:17:40 2007 +0000 @@ -1960,7 +1960,7 @@ static inline void svm_do_msr_access( msr_content = vmcb->sysenter_eip; break; case MSR_IA32_APICBASE: - msr_content = vcpu_vlapic(v)->apic_base_msr; + msr_content = vcpu_vlapic(v)->hw.apic_base_msr; break; default: if (long_mode_do_msr_read(regs)) diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/vioapic.c Sat Jan 20 11:17:40 2007 +0000 @@ -47,9 +47,9 @@ #define opt_hvm_debug_level opt_vmx_debug_level #endif -static void vioapic_deliver(struct vioapic *vioapic, int irq); - -static unsigned long vioapic_read_indirect(struct vioapic *vioapic, +static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq); + +static unsigned long vioapic_read_indirect(struct hvm_hw_vioapic *vioapic, unsigned long addr, unsigned long length) { @@ -96,7 +96,7 @@ static unsigned long vioapic_read(struct unsigned long addr, unsigned long length) { - struct vioapic *vioapic = domain_vioapic(v->domain); + struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); uint32_t result; HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vioapic_read addr %lx\n", addr); @@ -122,13 +122,13 @@ static unsigned long vioapic_read(struct } static void vioapic_write_redirent( - struct vioapic *vioapic, unsigned int idx, int top_word, uint32_t val) + struct hvm_hw_vioapic *vioapic, unsigned int idx, int top_word, uint32_t val) { struct domain *d = vioapic_domain(vioapic); - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; union vioapic_redir_entry *pent, ent; - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); pent = &vioapic->redirtbl[idx]; ent = *pent; @@ -157,11 +157,11 @@ static void vioapic_write_redirent( vioapic_deliver(vioapic, idx); } - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } static void vioapic_write_indirect( - struct vioapic *vioapic, unsigned long addr, + struct hvm_hw_vioapic *vioapic, unsigned long addr, unsigned long length, unsigned long val) { switch ( vioapic->ioregsel ) @@ -206,7 +206,7 @@ static void vioapic_write(struct vcpu *v unsigned long length, unsigned long val) { - struct vioapic *vioapic = domain_vioapic(v->domain); + struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); addr &= 0xff; @@ -233,7 +233,7 @@ static void vioapic_write(struct vcpu *v static int vioapic_range(struct vcpu *v, unsigned long addr) { - struct vioapic *vioapic = domain_vioapic(v->domain); + struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); return ((addr >= vioapic->base_address && (addr < vioapic->base_address + VIOAPIC_MEM_LENGTH))); @@ -246,7 +246,7 @@ struct hvm_mmio_handler vioapic_mmio_han }; static void ioapic_inj_irq( - struct vioapic *vioapic, + struct hvm_hw_vioapic *vioapic, struct vlapic *target, uint8_t vector, uint8_t trig_mode, @@ -270,7 +270,7 @@ static void ioapic_inj_irq( } static uint32_t ioapic_get_delivery_bitmask( - struct vioapic *vioapic, uint16_t dest, uint8_t dest_mode) + struct hvm_hw_vioapic *vioapic, uint16_t dest, uint8_t dest_mode) { uint32_t mask = 0; struct vcpu *v; @@ -316,7 +316,7 @@ static inline int pit_channel0_enabled(v return pt->enabled; } -static void vioapic_deliver(struct vioapic *vioapic, int irq) +static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq) { uint16_t dest = vioapic->redirtbl[irq].fields.dest_id; uint8_t dest_mode = vioapic->redirtbl[irq].fields.dest_mode; @@ -327,7 +327,7 @@ static void vioapic_deliver(struct vioap struct vlapic *target; struct vcpu *v; - ASSERT(spin_is_locked(&vioapic_domain(vioapic)->arch.hvm_domain.irq.lock)); + ASSERT(spin_is_locked(&vioapic_domain(vioapic)->arch.hvm_domain.irq_lock)); HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "dest=%x dest_mode=%x delivery_mode=%x " @@ -409,13 +409,13 @@ static void vioapic_deliver(struct vioap void vioapic_irq_positive_edge(struct domain *d, unsigned int irq) { - struct vioapic *vioapic = domain_vioapic(d); + struct hvm_hw_vioapic *vioapic = domain_vioapic(d); union vioapic_redir_entry *ent; HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_irq_positive_edge irq %x", irq); ASSERT(irq < VIOAPIC_NUM_PINS); - ASSERT(spin_is_locked(&d->arch.hvm_domain.irq.lock)); + ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock)); ent = &vioapic->redirtbl[irq]; if ( ent->fields.mask ) @@ -432,7 +432,7 @@ void vioapic_irq_positive_edge(struct do } } -static int get_eoi_gsi(struct vioapic *vioapic, int vector) +static int get_eoi_gsi(struct hvm_hw_vioapic *vioapic, int vector) { int i; @@ -445,12 +445,12 @@ static int get_eoi_gsi(struct vioapic *v void vioapic_update_EOI(struct domain *d, int vector) { - struct vioapic *vioapic = domain_vioapic(d); - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_vioapic *vioapic = domain_vioapic(d); + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; union vioapic_redir_entry *ent; int gsi; - spin_lock(&hvm_irq->lock); + spin_lock(&d->arch.hvm_domain.irq_lock); if ( (gsi = get_eoi_gsi(vioapic, vector)) == -1 ) { @@ -470,11 +470,11 @@ void vioapic_update_EOI(struct domain *d } out: - spin_unlock(&hvm_irq->lock); + spin_unlock(&d->arch.hvm_domain.irq_lock); } #ifdef HVM_DEBUG_SUSPEND -static void ioapic_info(struct vioapic *s) +static void ioapic_info(struct hvm_hw_vioapic *s) { int i; printk("*****ioapic state:*****\n"); @@ -486,7 +486,7 @@ static void ioapic_info(struct vioapic * } } -static void hvmirq_info(struct hvm_irq *hvm_irq) +static void hvmirq_info(struct hvm_hw_irq *hvm_irq) { int i; printk("*****hvmirq state:*****\n"); @@ -515,87 +515,44 @@ static void hvmirq_info(struct hvm_irq * printk("hvmirq round_robin_prev_vcpu:0x%"PRIx8".\n", hvm_irq->round_robin_prev_vcpu); } #else -static void ioapic_info(struct vioapic *s) -{ -} -static void hvmirq_info(struct hvm_irq *hvm_irq) +static void ioapic_info(struct hvm_hw_vioapic *s) +{ +} +static void hvmirq_info(struct hvm_hw_irq *hvm_irq) { } #endif static void ioapic_save(hvm_domain_context_t *h, void *opaque) { - int i; struct domain *d = opaque; - struct vioapic *s = domain_vioapic(d); - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_vioapic *s = domain_vioapic(d); + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; ioapic_info(s); hvmirq_info(hvm_irq); - /* save iopaic state*/ - hvm_put_32u(h, s->ioregsel); - hvm_put_32u(h, s->id); - hvm_put_64u(h, s->base_address); - for (i = 0; i < VIOAPIC_NUM_PINS; i++) { - hvm_put_64u(h, s->redirtbl[i].bits); - } + /* save io-apic state*/ + hvm_put_struct(h, s); /* save hvm irq state */ - hvm_put_buffer(h, (char*)hvm_irq->pci_intx, 16); - hvm_put_buffer(h, (char*)hvm_irq->isa_irq, 2); - hvm_put_32u(h, hvm_irq->callback_via_asserted); - hvm_put_32u(h, hvm_irq->callback_via_type); - hvm_put_32u(h, hvm_irq->callback_via.gsi); - - for (i = 0; i < 4; i++) - hvm_put_8u(h, hvm_irq->pci_link_route[i]); - - for (i = 0; i < 4; i++) - hvm_put_8u(h, hvm_irq->pci_link_assert_count[i]); - - for (i = 0; i < VIOAPIC_NUM_PINS; i++) - hvm_put_8u(h, hvm_irq->gsi_assert_count[i]); - - hvm_put_8u(h, hvm_irq->round_robin_prev_vcpu); - + hvm_put_struct(h, hvm_irq); } static int ioapic_load(hvm_domain_context_t *h, void *opaque, int version_id) { - int i; struct domain *d = opaque; - struct vioapic *s = domain_vioapic(d); - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + struct hvm_hw_vioapic *s = domain_vioapic(d); + struct hvm_hw_irq *hvm_irq = &d->arch.hvm_domain.irq; if (version_id != 1) return -EINVAL; /* restore ioapic state */ - s->ioregsel = hvm_get_32u(h); - s->id = hvm_get_32u(h); - s->base_address = hvm_get_64u(h); - for (i = 0; i < VIOAPIC_NUM_PINS; i++) { - s->redirtbl[i].bits = hvm_get_64u(h); - } + hvm_get_struct(h, s); /* restore irq state */ - hvm_get_buffer(h, (char*)hvm_irq->pci_intx, 16); - hvm_get_buffer(h, (char*)hvm_irq->isa_irq, 2); - hvm_irq->callback_via_asserted = hvm_get_32u(h); - hvm_irq->callback_via_type = hvm_get_32u(h); - hvm_irq->callback_via.gsi = hvm_get_32u(h); - - for (i = 0; i < 4; i++) - hvm_irq->pci_link_route[i] = hvm_get_8u(h); - - for (i = 0; i < 4; i++) - hvm_irq->pci_link_assert_count[i] = hvm_get_8u(h); - - for (i = 0; i < VIOAPIC_NUM_PINS; i++) - hvm_irq->gsi_assert_count[i] = hvm_get_8u(h); - - hvm_irq->round_robin_prev_vcpu = hvm_get_8u(h); + hvm_get_struct(h, hvm_irq); ioapic_info(s); hvmirq_info(hvm_irq); @@ -605,7 +562,7 @@ static int ioapic_load(hvm_domain_contex void vioapic_init(struct domain *d) { - struct vioapic *vioapic = domain_vioapic(d); + struct hvm_hw_vioapic *vioapic = domain_vioapic(d); int i; hvm_register_savevm(d, "xen_hvm_ioapic", 0, 1, ioapic_save, ioapic_load, d); diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/vlapic.c Sat Jan 20 11:17:40 2007 +0000 @@ -81,7 +81,7 @@ static unsigned int vlapic_lvt_mask[VLAP (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC) #define vlapic_base_address(vlapic) \ - (vlapic->apic_base_msr & MSR_IA32_APICBASE_BASE) + (vlapic->hw.apic_base_msr & MSR_IA32_APICBASE_BASE) static int vlapic_reset(struct vlapic *vlapic); @@ -100,15 +100,16 @@ static int vlapic_reset(struct vlapic *v #define vlapic_clear_vector(vec, bitmap) \ clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)) -static int vlapic_find_highest_vector(u32 *bitmap) -{ +static int vlapic_find_highest_vector(void *bitmap) +{ + uint32_t *word = bitmap; int word_offset = MAX_VECTOR / 32; /* Work backwards through the bitmap (first 32-bit word in every four). */ - while ( (word_offset != 0) && (bitmap[(--word_offset)*4] == 0) ) + while ( (word_offset != 0) && (word[(--word_offset)*4] == 0) ) continue; - return (fls(bitmap[word_offset*4]) - 1) + (word_offset * 32); + return (fls(word[word_offset*4]) - 1) + (word_offset * 32); } @@ -118,19 +119,19 @@ static int vlapic_find_highest_vector(u3 static int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic) { - return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR); + return vlapic_test_and_set_vector(vector, &vlapic->regs->data[APIC_IRR]); } static void vlapic_clear_irr(int vector, struct vlapic *vlapic) { - vlapic_clear_vector(vector, vlapic->regs + APIC_IRR); + vlapic_clear_vector(vector, &vlapic->regs->data[APIC_IRR]); } int vlapic_find_highest_irr(struct vlapic *vlapic) { int result; - result = vlapic_find_highest_vector(vlapic->regs + APIC_IRR); + result = vlapic_find_highest_vector(&vlapic->regs->data[APIC_IRR]); ASSERT((result == -1) || (result >= 16)); return result; @@ -142,7 +143,7 @@ int vlapic_set_irq(struct vlapic *vlapic ret = !vlapic_test_and_set_irr(vec, vlapic); if ( trig ) - vlapic_set_vector(vec, vlapic->regs + APIC_TMR); + vlapic_set_vector(vec, &vlapic->regs->data[APIC_TMR]); /* We may need to wake up target vcpu, besides set pending bit here */ return ret; @@ -152,7 +153,7 @@ int vlapic_find_highest_isr(struct vlapi { int result; - result = vlapic_find_highest_vector(vlapic->regs + APIC_ISR); + result = vlapic_find_highest_vector(&vlapic->regs->data[APIC_ISR]); ASSERT((result == -1) || (result >= 16)); return result; @@ -279,7 +280,7 @@ static int vlapic_accept_irq(struct vcpu { HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "level trig mode for vector %d\n", vector); - vlapic_set_vector(vector, vlapic->regs + APIC_TMR); + vlapic_set_vector(vector, &vlapic->regs->data[APIC_TMR]); } vcpu_kick(v); @@ -375,9 +376,9 @@ void vlapic_EOI_set(struct vlapic *vlapi if ( vector == -1 ) return; - vlapic_clear_vector(vector, vlapic->regs + APIC_ISR); - - if ( vlapic_test_and_clear_vector(vector, vlapic->regs + APIC_TMR) ) + vlapic_clear_vector(vector, &vlapic->regs->data[APIC_ISR]); + + if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) ) vioapic_update_EOI(vlapic_domain(vlapic), vector); } @@ -433,7 +434,7 @@ static uint32_t vlapic_get_tmcct(struct counter_passed = (hvm_get_guest_time(v) - vlapic->pt.last_plt_gtime) // TSC * 1000000000ULL / ticks_per_sec(v) // NS - / APIC_BUS_CYCLE_NS / vlapic->timer_divisor; + / APIC_BUS_CYCLE_NS / vlapic->hw.timer_divisor; tmcct = tmict - counter_passed; HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, @@ -450,12 +451,12 @@ static void vlapic_set_tdcr(struct vlapi val &= 0xb; vlapic_set_reg(vlapic, APIC_TDCR, val); - /* Update the demangled timer_divisor. */ + /* Update the demangled hw.timer_divisor. */ val = ((val & 3) | ((val & 8) >> 1)) + 1; - vlapic->timer_divisor = 1 << (val & 7); + vlapic->hw.timer_divisor = 1 << (val & 7); HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, - "vlapic_set_tdcr timer_divisor: %d.", vlapic->timer_divisor); + "vlapic_set_tdcr timer_divisor: %d.", vlapic->hw.timer_divisor); } static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset, @@ -614,7 +615,7 @@ static void vlapic_write(struct vcpu *v, int i; uint32_t lvt_val; - vlapic->disabled |= VLAPIC_SW_DISABLED; + vlapic->hw.disabled |= VLAPIC_SW_DISABLED; for ( i = 0; i < VLAPIC_LVT_NUM; i++ ) { @@ -624,7 +625,7 @@ static void vlapic_write(struct vcpu *v, } } else - vlapic->disabled &= ~VLAPIC_SW_DISABLED; + vlapic->hw.disabled &= ~VLAPIC_SW_DISABLED; break; case APIC_ESR: @@ -656,7 +657,7 @@ static void vlapic_write(struct vcpu *v, case APIC_TMICT: { - uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * vlapic->timer_divisor; + uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * vlapic->hw.timer_divisor; vlapic_set_reg(vlapic, APIC_TMICT, val); create_periodic_time(current, &vlapic->pt, period, vlapic->pt.irq, @@ -672,7 +673,7 @@ static void vlapic_write(struct vcpu *v, case APIC_TDCR: vlapic_set_tdcr(vlapic, val & 0xb); HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divisor is 0x%x", - vlapic->timer_divisor); + vlapic->hw.timer_divisor); break; default: @@ -697,23 +698,23 @@ struct hvm_mmio_handler vlapic_mmio_hand void vlapic_msr_set(struct vlapic *vlapic, uint64_t value) { - if ( (vlapic->apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE ) + if ( (vlapic->hw.apic_base_msr ^ value) & MSR_IA32_APICBASE_ENABLE ) { if ( value & MSR_IA32_APICBASE_ENABLE ) { vlapic_reset(vlapic); - vlapic->disabled &= ~VLAPIC_HW_DISABLED; + vlapic->hw.disabled &= ~VLAPIC_HW_DISABLED; } else { - vlapic->disabled |= VLAPIC_HW_DISABLED; - } - } - - vlapic->apic_base_msr = value; + vlapic->hw.disabled |= VLAPIC_HW_DISABLED; + } + } + + vlapic->hw.apic_base_msr = value; HVM_DBG_LOG(DBG_LEVEL_VLAPIC, - "apic base msr is 0x%016"PRIx64".", vlapic->apic_base_msr); + "apic base msr is 0x%016"PRIx64".", vlapic->hw.apic_base_msr); } int vlapic_accept_pic_intr(struct vcpu *v) @@ -754,7 +755,7 @@ int cpu_get_apic_interrupt(struct vcpu * if ( vector == -1 ) return -1; - vlapic_set_vector(vector, vlapic->regs + APIC_ISR); + vlapic_set_vector(vector, &vlapic->regs->data[APIC_ISR]); vlapic_clear_irr(vector, vlapic); *mode = APIC_DM_FIXED; @@ -790,7 +791,7 @@ static int vlapic_reset(struct vlapic *v vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); vlapic_set_reg(vlapic, APIC_SPIV, 0xff); - vlapic->disabled |= VLAPIC_SW_DISABLED; + vlapic->hw.disabled |= VLAPIC_SW_DISABLED; return 1; } @@ -799,10 +800,9 @@ static void lapic_info(struct vlapic *s) static void lapic_info(struct vlapic *s) { printk("*****lapic state:*****\n"); - printk("lapic 0x%"PRIx64".\n", s->apic_base_msr); - printk("lapic 0x%x.\n", s->disabled); - printk("lapic 0x%x.\n", s->timer_divisor); - printk("lapic 0x%x.\n", s->timer_pending_count); + printk("lapic 0x%"PRIx64".\n", s->hw.apic_base_msr); + printk("lapic 0x%x.\n", s->hw.disabled); + printk("lapic 0x%x.\n", s->hw.timer_divisor); } #else static void lapic_info(struct vlapic *s) @@ -816,15 +816,8 @@ static void lapic_save(hvm_domain_contex lapic_info(s); - hvm_put_64u(h, s->apic_base_msr); - hvm_put_32u(h, s->disabled); - hvm_put_32u(h, s->timer_divisor); - - /*XXX: need this?*/ - hvm_put_32u(h, s->timer_pending_count); - - hvm_put_buffer(h, (char*)s->regs, 0x3f0); - + hvm_put_struct(h, &s->hw); + hvm_put_struct(h, s->regs); } static int lapic_load(hvm_domain_context_t *h, void *opaque, int version_id) @@ -836,19 +829,13 @@ static int lapic_load(hvm_domain_context if (version_id != 1) return -EINVAL; - s->apic_base_msr = hvm_get_64u(h); - s->disabled = hvm_get_32u(h); - s->timer_divisor = hvm_get_32u(h); - - /*XXX: need this?*/ - s->timer_pending_count = hvm_get_32u(h); - - hvm_get_buffer(h, (char*)s->regs, 0x3f0); + hvm_get_struct(h, &s->hw); + hvm_get_struct(h, s->regs); /* rearm the actiemr if needed */ tmict = vlapic_get_reg(s, APIC_TMICT); if (tmict > 0) { - uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)tmict * s->timer_divisor; + uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)tmict * s->hw.timer_divisor; create_periodic_time(v, &s->pt, period, s->pt.irq, vlapic_lvtt_period(s), NULL, s); @@ -887,9 +874,9 @@ int vlapic_init(struct vcpu *v) hvm_register_savevm(v->domain, "xen_hvm_lapic", v->vcpu_id, 1, lapic_save, lapic_load, vlapic); vlapic_reset(vlapic); - vlapic->apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; + vlapic->hw.apic_base_msr = MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; if ( v->vcpu_id == 0 ) - vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP; + vlapic->hw.apic_base_msr |= MSR_IA32_APICBASE_BSP; init_timer(&vlapic->pt.timer, pt_timer_fn, &vlapic->pt, v->processor); diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Sat Jan 20 11:17:40 2007 +0000 @@ -2309,7 +2309,7 @@ static inline int vmx_do_msr_read(struct msr_content = __vmread(GUEST_SYSENTER_EIP); break; case MSR_IA32_APICBASE: - msr_content = vcpu_vlapic(v)->apic_base_msr; + msr_content = vcpu_vlapic(v)->hw.apic_base_msr; break; default: if ( long_mode_do_msr_read(regs) ) diff -r dccdc3ee0efc -r 2457741f4ec3 xen/arch/x86/hvm/vpic.c --- a/xen/arch/x86/hvm/vpic.c Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/arch/x86/hvm/vpic.c Sat Jan 20 11:17:40 2007 +0000 @@ -35,9 +35,9 @@ #include <asm/hvm/support.h> #define vpic_domain(v) (container_of((v), struct domain, \ - arch.hvm_domain.irq.vpic[!vpic->is_master])) -#define __vpic_lock(v) &container_of((v), struct hvm_irq, \ - vpic[!(v)->is_master])->lock + arch.hvm_domain.vpic[!vpic->is_master])) +#define __vpic_lock(v) &container_of((v), struct hvm_domain, \ + vpic[!(v)->is_master])->irq_lock #define vpic_lock(v) spin_lock(__vpic_lock(v)) #define vpic_unlock(v) spin_unlock(__vpic_lock(v)) #define vpic_is_locked(v) spin_is_locked(__vpic_lock(v)) @@ -45,7 +45,7 @@ /* Return the highest priority found in mask. Return 8 if none. */ #define VPIC_PRIO_NONE 8 -static int vpic_get_priority(struct vpic *vpic, uint8_t mask) +static int vpic_get_priority(struct hvm_hw_vpic *vpic, uint8_t mask) { int prio; @@ -61,7 +61,7 @@ static int vpic_get_priority(struct vpic } /* Return the PIC's highest priority pending interrupt. Return -1 if none. */ -static int vpic_get_highest_priority_irq(struct vpic *vpic) +static int vpic_get_highest_priority_irq(struct hvm_hw_vpic *vpic) { int cur_priority, priority, irq; uint8_t mask; @@ -92,7 +92,7 @@ static int vpic_get_highest_priority_irq return (priority < cur_priority) ? irq : -1; } -static void vpic_update_int_output(struct vpic *vpic) +static void vpic_update_int_output(struct hvm_hw_vpic *vpic) { int irq; @@ -129,7 +129,7 @@ static void vpic_update_int_output(struc } } -static void __vpic_intack(struct vpic *vpic, int irq) +static void __vpic_intack(struct hvm_hw_vpic *vpic, int irq) { uint8_t mask = 1 << irq; @@ -147,7 +147,7 @@ static void __vpic_intack(struct vpic *v vpic_update_int_output(vpic); } -static int vpic_intack(struct vpic *vpic) +static int vpic_intack(struct hvm_hw_vpic *vpic) { int irq = -1; @@ -174,7 +174,7 @@ static int vpic_intack(struct vpic *vpic return irq; } -static void vpic_ioport_write(struct vpic *vpic, uint32_t addr, uint32_t val) +static void vpic_ioport_write(struct hvm_hw_vpic *vpic, uint32_t addr, uint32_t val) { int priority, cmd, irq; uint8_t mask; @@ -291,7 +291,7 @@ static void vpic_ioport_write(struct vpi vpic_unlock(vpic); } -static uint32_t vpic_ioport_read(struct vpic *vpic, uint32_t addr) +static uint32_t vpic_ioport_read(struct hvm_hw_vpic *vpic, uint32_t addr) { if ( vpic->poll ) { @@ -307,7 +307,7 @@ static uint32_t vpic_ioport_read(struct static int vpic_intercept_pic_io(ioreq_t *p) { - struct vpic *vpic; + struct hvm_hw_vpic *vpic; uint32_t data; if ( (p->size != 1) || (p->count != 1) ) @@ -316,7 +316,7 @@ static int vpic_intercept_pic_io(ioreq_t return 1; } - vpic = ¤t->domain->arch.hvm_domain.irq.vpic[p->addr >> 7]; + vpic = ¤t->domain->arch.hvm_domain.vpic[p->addr >> 7]; if ( p->dir == IOREQ_WRITE ) { @@ -340,7 +340,7 @@ static int vpic_intercept_pic_io(ioreq_t static int vpic_intercept_elcr_io(ioreq_t *p) { - struct vpic *vpic; + struct hvm_hw_vpic *vpic; uint32_t data; if ( (p->size != 1) || (p->count != 1) ) @@ -349,7 +349,7 @@ static int vpic_intercept_elcr_io(ioreq_ return 1; } - vpic = ¤t->domain->arch.hvm_domain.irq.vpic[p->addr & 1]; + vpic = ¤t->domain->arch.hvm_domain.vpic[p->addr & 1]; if ( p->dir == IOREQ_WRITE ) { @@ -379,7 +379,7 @@ static int vpic_intercept_elcr_io(ioreq_ } #ifdef HVM_DEBUG_SUSPEND -static void vpic_info(struct vpic *s) +static void vpic_info(struct hvm_hw_vpic *s) { printk("*****pic state:*****\n"); printk("pic 0x%x.\n", s->irr); @@ -399,61 +399,27 @@ static void vpic_info(struct vpic *s) printk("pic 0x%x.\n", s->is_master); } #else -static void vpic_info(struct vpic *s) +static void vpic_info(struct hvm_hw_vpic *s) { } #endif static void vpic_save(hvm_domain_context_t *h, void *opaque) { - struct vpic *s = opaque; + struct hvm_hw_vpic *s = opaque; vpic_info(s); - - hvm_put_8u(h, s->irr); - hvm_put_8u(h, s->imr); - hvm_put_8u(h, s->isr); - hvm_put_8u(h, s->irq_base); - hvm_put_8u(h, s->init_state); - hvm_put_8u(h, s->priority_add); - hvm_put_8u(h, s->readsel_isr); - - hvm_put_8u(h, s->poll); - hvm_put_8u(h, s->auto_eoi); - - hvm_put_8u(h, s->rotate_on_auto_eoi); - hvm_put_8u(h, s->special_fully_nested_mode); - hvm_put_8u(h, s->special_mask_mode); - - hvm_put_8u(h, s->elcr); - hvm_put_8u(h, s->int_output); + hvm_put_struct(h, s); } static int vpic_load(hvm_domain_context_t *h, void *opaque, int version_id) { - struct vpic *s = opaque; + struct hvm_hw_vpic *s = opaque; if (version_id != 1) return -EINVAL; - s->irr = hvm_get_8u(h); - s->imr = hvm_get_8u(h); - s->isr = hvm_get_8u(h); - s->irq_base = hvm_get_8u(h); - s->init_state = hvm_get_8u(h); - s->priority_add = hvm_get_8u(h); - s->readsel_isr = hvm_get_8u(h); - - s->poll = hvm_get_8u(h); - s->auto_eoi = hvm_get_8u(h); - - s->rotate_on_auto_eoi = hvm_get_8u(h); - s->special_fully_nested_mode = hvm_get_8u(h); - s->special_mask_mode = hvm_get_8u(h); - - s->elcr = hvm_get_8u(h); - s->int_output = hvm_get_8u(h); - + hvm_get_struct(h, s); vpic_info(s); return 0; @@ -461,10 +427,10 @@ static int vpic_load(hvm_domain_context_ void vpic_init(struct domain *d) { - struct vpic *vpic; + struct hvm_hw_vpic *vpic; /* Master PIC. */ - vpic = &d->arch.hvm_domain.irq.vpic[0]; + vpic = &d->arch.hvm_domain.vpic[0]; memset(vpic, 0, sizeof(*vpic)); vpic->is_master = 1; vpic->elcr = 1 << 2; @@ -482,7 +448,7 @@ void vpic_init(struct domain *d) void vpic_irq_positive_edge(struct domain *d, int irq) { - struct vpic *vpic = &d->arch.hvm_domain.irq.vpic[irq >> 3]; + struct hvm_hw_vpic *vpic = &d->arch.hvm_domain.vpic[irq >> 3]; uint8_t mask = 1 << (irq & 7); ASSERT(irq <= 15); @@ -498,7 +464,7 @@ void vpic_irq_positive_edge(struct domai void vpic_irq_negative_edge(struct domain *d, int irq) { - struct vpic *vpic = &d->arch.hvm_domain.irq.vpic[irq >> 3]; + struct hvm_hw_vpic *vpic = &d->arch.hvm_domain.vpic[irq >> 3]; uint8_t mask = 1 << (irq & 7); ASSERT(irq <= 15); @@ -515,7 +481,7 @@ int cpu_get_pic_interrupt(struct vcpu *v int cpu_get_pic_interrupt(struct vcpu *v, int *type) { int irq, vector; - struct vpic *vpic = &v->domain->arch.hvm_domain.irq.vpic[0]; + struct hvm_hw_vpic *vpic = &v->domain->arch.hvm_domain.vpic[0]; if ( !vlapic_accept_pic_intr(v) || !vpic->int_output ) return -1; diff -r dccdc3ee0efc -r 2457741f4ec3 xen/include/asm-x86/hvm/domain.h --- a/xen/include/asm-x86/hvm/domain.h Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/include/asm-x86/hvm/domain.h Sat Jan 20 11:17:40 2007 +0000 @@ -26,6 +26,7 @@ #include <asm/hvm/vlapic.h> #include <asm/hvm/io.h> #include <public/hvm/params.h> +#include <public/hvm/save.h> typedef void SaveStateHandler(hvm_domain_context_t *h, void *opaque); typedef int LoadStateHandler(hvm_domain_context_t *h, void *opaque, int version_id); @@ -50,7 +51,11 @@ struct hvm_domain { struct hvm_io_handler io_handler; - struct hvm_irq irq; + /* Lock protects access to irq, vpic and vioapic. */ + spinlock_t irq_lock; + struct hvm_hw_irq irq; + struct hvm_hw_vpic vpic[2]; /* 0=master; 1=slave */ + struct hvm_hw_vioapic vioapic; /* hvm_print_line() logging. */ char pbuf[80]; diff -r dccdc3ee0efc -r 2457741f4ec3 xen/include/asm-x86/hvm/irq.h --- a/xen/include/asm-x86/hvm/irq.h Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/include/asm-x86/hvm/irq.h Sat Jan 20 11:17:40 2007 +0000 @@ -26,70 +26,7 @@ #include <xen/spinlock.h> #include <asm/hvm/vpic.h> #include <asm/hvm/vioapic.h> - -struct hvm_irq { - /* Lock protects access to all other fields. */ - spinlock_t lock; - - /* - * Virtual interrupt wires for a single PCI bus. - * Indexed by: device*4 + INTx#. - */ - DECLARE_BITMAP(pci_intx, 32*4); - - /* - * Virtual interrupt wires for ISA devices. - * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing). - */ - DECLARE_BITMAP(isa_irq, 16); - - /* Virtual interrupt and via-link for paravirtual platform driver. */ - unsigned int callback_via_asserted; - enum { - HVMIRQ_callback_none, - HVMIRQ_callback_gsi, - HVMIRQ_callback_pci_intx - } callback_via_type; - union { - unsigned int gsi; - struct { uint8_t dev, intx; } pci; - } callback_via; - - /* - * PCI-ISA interrupt router. - * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using - * the traditional 'barber's pole' mapping ((device + INTx#) & 3). - * The router provides a programmable mapping from each link to a GSI. - */ - u8 pci_link_route[4]; - - /* Number of INTx wires asserting each PCI-ISA link. */ - u8 pci_link_assert_count[4]; - - /* - * Number of wires asserting each GSI. - * - * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space - * except ISA IRQ 0, which is connected to GSI 2. - * PCI links map into this space via the PCI-ISA bridge. - * - * GSIs 16+ are used only be PCI devices. The mapping from PCI device to - * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16 - */ - u8 gsi_assert_count[VIOAPIC_NUM_PINS]; - - /* - * GSIs map onto PIC/IO-APIC in the usual way: - * 0-7: Master 8259 PIC, IO-APIC pins 0-7 - * 8-15: Slave 8259 PIC, IO-APIC pins 8-15 - * 16+ : IO-APIC pins 16+ - */ - struct vpic vpic[2]; /* 0=master; 1=slave */ - struct vioapic vioapic; - - /* Last VCPU that was delivered a LowestPrio interrupt. */ - u8 round_robin_prev_vcpu; -}; +#include <public/hvm/save.h> #define hvm_pci_intx_gsi(dev, intx) \ (((((dev)<<2) + ((dev)>>3) + (intx)) & 31) + 16) diff -r dccdc3ee0efc -r 2457741f4ec3 xen/include/asm-x86/hvm/vioapic.h --- a/xen/include/asm-x86/hvm/vioapic.h Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/include/asm-x86/hvm/vioapic.h Sat Jan 20 11:17:40 2007 +0000 @@ -28,13 +28,7 @@ #include <xen/config.h> #include <xen/types.h> #include <xen/smp.h> - -#ifdef __ia64__ -#define VIOAPIC_IS_IOSAPIC 1 -#define VIOAPIC_NUM_PINS 24 -#else -#define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */ -#endif +#include <public/hvm/save.h> #if !VIOAPIC_IS_IOSAPIC #define VIOAPIC_VERSION_ID 0x11 /* IOAPIC version */ @@ -58,38 +52,9 @@ #define VIOAPIC_REG_VERSION 0x01 #define VIOAPIC_REG_ARB_ID 0x02 /* x86 IOAPIC only */ -#define domain_vioapic(d) (&(d)->arch.hvm_domain.irq.vioapic) +#define domain_vioapic(d) (&(d)->arch.hvm_domain.vioapic) #define vioapic_domain(v) (container_of((v), struct domain, \ - arch.hvm_domain.irq.vioapic)) - -union vioapic_redir_entry -{ - uint64_t bits; - struct { - uint8_t vector; - uint8_t delivery_mode:3; - uint8_t dest_mode:1; - uint8_t delivery_status:1; - uint8_t polarity:1; - uint8_t remote_irr:1; - uint8_t trig_mode:1; - uint8_t mask:1; - uint8_t reserve:7; -#if !VIOAPIC_IS_IOSAPIC - uint8_t reserved[4]; - uint8_t dest_id; -#else - uint8_t reserved[3]; - uint16_t dest_id; -#endif - } fields; -}; - -struct vioapic { - uint32_t ioregsel, id; - unsigned long base_address; - union vioapic_redir_entry redirtbl[VIOAPIC_NUM_PINS]; -}; + arch.hvm_domain.vioapic)) void vioapic_init(struct domain *d); void vioapic_irq_positive_edge(struct domain *d, unsigned int irq); diff -r dccdc3ee0efc -r 2457741f4ec3 xen/include/asm-x86/hvm/vlapic.h --- a/xen/include/asm-x86/hvm/vlapic.h Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/include/asm-x86/hvm/vlapic.h Sat Jan 20 11:17:40 2007 +0000 @@ -44,31 +44,28 @@ */ #define VLAPIC_HW_DISABLED 0x1 #define VLAPIC_SW_DISABLED 0x2 -#define vlapic_sw_disabled(vlapic) ((vlapic)->disabled & VLAPIC_SW_DISABLED) -#define vlapic_hw_disabled(vlapic) ((vlapic)->disabled & VLAPIC_HW_DISABLED) -#define vlapic_disabled(vlapic) ((vlapic)->disabled) -#define vlapic_enabled(vlapic) (!vlapic_disabled(vlapic)) +#define vlapic_sw_disabled(vlapic) ((vlapic)->hw.disabled & VLAPIC_SW_DISABLED) +#define vlapic_hw_disabled(vlapic) ((vlapic)->hw.disabled & VLAPIC_HW_DISABLED) +#define vlapic_disabled(vlapic) ((vlapic)->hw.disabled) +#define vlapic_enabled(vlapic) (!vlapic_disabled(vlapic)) struct vlapic { - uint64_t apic_base_msr; - uint32_t disabled; /* VLAPIC_xx_DISABLED */ - uint32_t timer_divisor; - struct periodic_time pt; - int timer_pending_count; - s_time_t timer_last_update; - struct page_info *regs_page; - void *regs; + struct hvm_hw_lapic hw; + struct hvm_hw_lapic_regs *regs; + struct periodic_time pt; + s_time_t timer_last_update; + struct page_info *regs_page; }; static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg) { - return *((uint32_t *)(vlapic->regs + reg)); + return *((uint32_t *)(&vlapic->regs->data[reg])); } static inline void vlapic_set_reg( struct vlapic *vlapic, uint32_t reg, uint32_t val) { - *((uint32_t *)(vlapic->regs + reg)) = val; + *((uint32_t *)(&vlapic->regs->data[reg])) = val; } int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig); diff -r dccdc3ee0efc -r 2457741f4ec3 xen/include/asm-x86/hvm/vpic.h --- a/xen/include/asm-x86/hvm/vpic.h Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/include/asm-x86/hvm/vpic.h Sat Jan 20 11:17:40 2007 +0000 @@ -27,51 +27,7 @@ #ifndef __ASM_X86_HVM_VPIC_H__ #define __ASM_X86_HVM_VPIC_H__ -struct vpic { - /* IR line bitmasks. */ - uint8_t irr, imr, isr; - - /* Line IRx maps to IRQ irq_base+x */ - uint8_t irq_base; - - /* - * Where are we in ICW2-4 initialisation (0 means no init in progress)? - * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1). - * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence) - * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence) - */ - uint8_t init_state:4; - - /* IR line with highest priority. */ - uint8_t priority_add:4; - - /* Reads from A=0 obtain ISR or IRR? */ - uint8_t readsel_isr:1; - - /* Reads perform a polling read? */ - uint8_t poll:1; - - /* Automatically clear IRQs from the ISR during INTA? */ - uint8_t auto_eoi:1; - - /* Automatically rotate IRQ priorities during AEOI? */ - uint8_t rotate_on_auto_eoi:1; - - /* Exclude slave inputs when considering in-service IRQs? */ - uint8_t special_fully_nested_mode:1; - - /* Special mask mode excludes masked IRs from AEOI and priority checks. */ - uint8_t special_mask_mode:1; - - /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */ - uint8_t is_master:1; - - /* Edge/trigger selection. */ - uint8_t elcr; - - /* Virtual INT output. */ - uint8_t int_output; -}; +#include <public/hvm/save.h> void vpic_irq_positive_edge(struct domain *d, int irq); void vpic_irq_negative_edge(struct domain *d, int irq); diff -r dccdc3ee0efc -r 2457741f4ec3 xen/include/public/hvm/save.h --- a/xen/include/public/hvm/save.h Sat Jan 20 11:17:39 2007 +0000 +++ b/xen/include/public/hvm/save.h Sat Jan 20 11:17:40 2007 +0000 @@ -83,7 +83,6 @@ struct hvm_hw_cpu { uint64_t ldtr_base; uint64_t idtr_base; uint64_t gdtr_base; - uint32_t cs_arbytes; uint32_t ds_arbytes; @@ -137,5 +136,182 @@ struct hvm_hw_pit { }; +/* + * PIC + */ +#define HVM_SAVE_TYPE_PIC 3 +struct hvm_hw_vpic { + /* IR line bitmasks. */ + uint8_t irr; + uint8_t imr; + uint8_t isr; + + /* Line IRx maps to IRQ irq_base+x */ + uint8_t irq_base; + + /* + * Where are we in ICW2-4 initialisation (0 means no init in progress)? + * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1). + * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence) + * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence) + */ + uint8_t init_state:4; + + /* IR line with highest priority. */ + uint8_t priority_add:4; + + /* Reads from A=0 obtain ISR or IRR? */ + uint8_t readsel_isr:1; + + /* Reads perform a polling read? */ + uint8_t poll:1; + + /* Automatically clear IRQs from the ISR during INTA? */ + uint8_t auto_eoi:1; + + /* Automatically rotate IRQ priorities during AEOI? */ + uint8_t rotate_on_auto_eoi:1; + + /* Exclude slave inputs when considering in-service IRQs? */ + uint8_t special_fully_nested_mode:1; + + /* Special mask mode excludes masked IRs from AEOI and priority checks. */ + uint8_t special_mask_mode:1; + + /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */ + uint8_t is_master:1; + + /* Edge/trigger selection. */ + uint8_t elcr; + + /* Virtual INT output. */ + uint8_t int_output; +}; + + +/* + * IO-APIC + */ +#define HVM_SAVE_TYPE_IOAPIC 4 + +#ifdef __ia64__ +#define VIOAPIC_IS_IOSAPIC 1 +#define VIOAPIC_NUM_PINS 24 +#else +#define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */ +#endif + +struct hvm_hw_vioapic { + uint64_t base_address; + uint32_t ioregsel; + uint32_t id; + union vioapic_redir_entry + { + uint64_t bits; + struct { + uint8_t vector; + uint8_t delivery_mode:3; + uint8_t dest_mode:1; + uint8_t delivery_status:1; + uint8_t polarity:1; + uint8_t remote_irr:1; + uint8_t trig_mode:1; + uint8_t mask:1; + uint8_t reserve:7; +#if !VIOAPIC_IS_IOSAPIC + uint8_t reserved[4]; + uint8_t dest_id; +#else + uint8_t reserved[3]; + uint16_t dest_id; +#endif + } fields; + } redirtbl[VIOAPIC_NUM_PINS]; +}; + + +/* + * IRQ + */ +#define HVM_SAVE_TYPE_IRQ 5 +struct hvm_hw_irq { + /* + * Virtual interrupt wires for a single PCI bus. + * Indexed by: device*4 + INTx#. + */ + DECLARE_BITMAP(pci_intx, 32*4); + + /* + * Virtual interrupt wires for ISA devices. + * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing). + */ + DECLARE_BITMAP(isa_irq, 16); + + /* Virtual interrupt and via-link for paravirtual platform driver. */ + uint32_t callback_via_asserted; + union { + enum { + HVMIRQ_callback_none, + HVMIRQ_callback_gsi, + HVMIRQ_callback_pci_intx + } callback_via_type; + uint32_t pad; /* So the next field will be aligned */ + }; + union { + uint32_t gsi; + struct { uint8_t dev, intx; } pci; + } callback_via; + + /* + * PCI-ISA interrupt router. + * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using + * the traditional 'barber's pole' mapping ((device + INTx#) & 3). + * The router provides a programmable mapping from each link to a GSI. + */ + u8 pci_link_route[4]; + + /* Number of INTx wires asserting each PCI-ISA link. */ + u8 pci_link_assert_count[4]; + + /* + * Number of wires asserting each GSI. + * + * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space + * except ISA IRQ 0, which is connected to GSI 2. + * PCI links map into this space via the PCI-ISA bridge. + * + * GSIs 16+ are used only be PCI devices. The mapping from PCI device to + * GSI is as follows: ((device*4 + device/8 + INTx#) & 31) + 16 + */ + u8 gsi_assert_count[VIOAPIC_NUM_PINS]; + + /* + * GSIs map onto PIC/IO-APIC in the usual way: + * 0-7: Master 8259 PIC, IO-APIC pins 0-7 + * 8-15: Slave 8259 PIC, IO-APIC pins 8-15 + * 16+ : IO-APIC pins 16+ + */ + + /* Last VCPU that was delivered a LowestPrio interrupt. */ + u8 round_robin_prev_vcpu; +}; + + +/* + * LAPIC + */ +#define HVM_SAVE_TYPE_LAPIC 6 +struct hvm_hw_lapic { + uint64_t apic_base_msr; + uint32_t disabled; /* VLAPIC_xx_DISABLED */ + uint32_t timer_divisor; +}; + +#define HVM_SAVE_TYPE_LAPIC_REGS 7 + +struct hvm_hw_lapic_regs { + /* A 4k page of register state */ + uint8_t data[0x400]; +}; #endif /* __XEN_PUBLIC_HVM_SAVE_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |