[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Fix some IOAPIC and LAPIC device model bugs.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID f393ced88d1482868e32689282102b757ddf641c # Parent 713b0878da2f863d449a7b4628403f3dd82fa56f [HVM] Fix some IOAPIC and LAPIC device model bugs. Fix some boundary checking errors. Fix the confusion using variables 'level' and 'trig_mode'. Also fix some other misc mistakes and do some cleanup. Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx> --- xen/arch/x86/hvm/vioapic.c | 12 +++--- xen/arch/x86/hvm/vlapic.c | 67 +++++++++++++++++++++----------------- xen/include/asm-x86/hvm/vioapic.h | 5 -- 3 files changed, 44 insertions(+), 40 deletions(-) diff -r 713b0878da2f -r f393ced88d14 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Thu Aug 10 10:45:10 2006 +0100 +++ b/xen/arch/x86/hvm/vioapic.c Thu Aug 10 10:47:37 2006 +0100 @@ -79,7 +79,7 @@ static unsigned long hvm_vioapic_read_in switch (s->ioregsel) { case IOAPIC_REG_VERSION: result = ((((IOAPIC_NUM_PINS-1) & 0xff) << 16) - | (IOAPIC_VERSION_ID & 0x0f)); + | (IOAPIC_VERSION_ID & 0xff)); break; #ifndef __ia64__ @@ -89,7 +89,7 @@ static unsigned long hvm_vioapic_read_in case IOAPIC_REG_ARB_ID: /* XXX how arb_id used on p4? */ - result = ((s->id & 0xf) << 24); + result = ((s->arb_id & 0xf) << 24); break; #endif @@ -107,7 +107,7 @@ static unsigned long hvm_vioapic_read_in (redir_content >> 32) & 0xffffffff : redir_content & 0xffffffff; } else { - printk("upic_mem_readl:undefined ioregsel %x\n", + printk("apic_mem_readl:undefined ioregsel %x\n", s->ioregsel); domain_crash_synchronous(); } @@ -244,7 +244,7 @@ static int hvm_vioapic_range(struct vcpu if ((s->flags & IOAPIC_ENABLE_FLAG) && (addr >= s->base_address && - (addr <= s->base_address + IOAPIC_MEM_LENGTH))) + (addr < s->base_address + IOAPIC_MEM_LENGTH))) return 1; else return 0; @@ -427,7 +427,7 @@ static void ioapic_deliver(hvm_vioapic_t else HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "null round robin mask %x vector %x delivery_mode %x\n", - deliver_bitmask, vector, deliver_bitmask); + deliver_bitmask, vector, dest_LowestPrio); break; } @@ -568,7 +568,7 @@ static int get_redir_num(hvm_vioapic_t * ASSERT(s); - for(i = 0; i < IOAPIC_NUM_PINS - 1; i++) { + for(i = 0; i < IOAPIC_NUM_PINS; i++) { if (s->redirtbl[i].RedirForm.vector == vector) return i; } diff -r 713b0878da2f -r f393ced88d14 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Thu Aug 10 10:45:10 2006 +0100 +++ b/xen/arch/x86/hvm/vlapic.c Thu Aug 10 10:47:37 2006 +0100 @@ -68,7 +68,7 @@ int vlapic_find_highest_irr(struct vlapi result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_IRR), MAX_VECTOR); - ASSERT( result == -1 || result > 16); + ASSERT( result == -1 || result >= 16); return result; } @@ -91,7 +91,7 @@ int vlapic_find_highest_isr(struct vlapi result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_ISR), MAX_VECTOR); - ASSERT( result == -1 || result > 16); + ASSERT( result == -1 || result >= 16); return result; } @@ -156,10 +156,11 @@ static int vlapic_match_dest(struct vcpu } else /* Logical */ { - uint32_t ldr = vlapic_get_reg(target, APIC_LDR); - + uint32_t ldr; if ( target == NULL ) break; + ldr = vlapic_get_reg(target, APIC_LDR); + /* Flat mode */ if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT) { @@ -219,14 +220,14 @@ static int vlapic_accept_irq(struct vcpu if ( unlikely(vlapic == NULL || !vlapic_enabled(vlapic)) ) break; - if ( test_and_set_bit(vector, vlapic->regs + APIC_IRR) ) + if ( test_and_set_bit(vector, vlapic->regs + APIC_IRR) && trig_mode) { HVM_DBG_LOG(DBG_LEVEL_VLAPIC, - "level trig mode repeatedly for vector %d\n", vector); + "level trig mode repeatedly for vector %d\n", vector); break; } - if ( level ) + if ( trig_mode ) { HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "level trig mode for vector %d\n", vector); @@ -248,7 +249,7 @@ static int vlapic_accept_irq(struct vcpu break; case APIC_DM_INIT: - if ( level && !(trig_mode & APIC_INT_ASSERT) ) //Deassert + if ( trig_mode && !(level & APIC_INT_ASSERT) ) //Deassert printk("This hvm_vlapic is for P4, no work for De-assert init\n"); else { @@ -290,11 +291,12 @@ static int vlapic_accept_irq(struct vcpu return result; } + /* - This function is used by both ioapic and local APIC - The bitmap is for vcpu_id + * This function is used by both ioapic and local APIC + * The bitmap is for vcpu_id */ -struct vlapic* apic_round_robin(struct domain *d, +struct vlapic *apic_round_robin(struct domain *d, uint8_t dest_mode, uint8_t vector, uint32_t bitmap) @@ -321,11 +323,11 @@ struct vlapic* apic_round_robin(struct d /* the vcpu array is arranged according to vcpu_id */ do { - next++; - if ( !d->vcpu[next] || - !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) || - next == MAX_VIRT_CPUS ) + if ( ++next == MAX_VIRT_CPUS ) next = 0; + if ( d->vcpu[next] == NULL || + !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) ) + continue; if ( test_bit(next, &bitmap) ) { @@ -384,15 +386,15 @@ static void vlapic_ipi(struct vlapic *vl unsigned int dest = GET_APIC_DEST_FIELD(icr_high); unsigned int short_hand = icr_low & APIC_SHORT_MASK; - unsigned int trig_mode = icr_low & APIC_INT_ASSERT; - unsigned int level = icr_low & APIC_INT_LEVELTRIG; + unsigned int trig_mode = icr_low & APIC_INT_LEVELTRIG; + unsigned int level = icr_low & APIC_INT_ASSERT; unsigned int dest_mode = icr_low & APIC_DEST_MASK; unsigned int delivery_mode = icr_low & APIC_MODE_MASK; unsigned int vector = icr_low & APIC_VECTOR_MASK; struct vlapic *target; struct vcpu *v = NULL; - uint32_t lpr_map; + uint32_t lpr_map=0; HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr_high 0x%x, icr_low 0x%x, " "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, " @@ -456,7 +458,7 @@ static uint32_t vlapic_get_tmcct(struct { do { tmcct += vlapic_get_reg(vlapic, APIC_TMICT); - } while ( tmcct < 0 ); + } while ( tmcct <= 0 ); } } @@ -489,6 +491,11 @@ static void vlapic_read_aligned(struct v *result = vlapic_get_tmcct(vlapic); break; + case APIC_ESR: + vlapic->err_write_count = 0; + *result = vlapic_get_reg(vlapic, offset); + break; + default: *result = vlapic_get_reg(vlapic, offset); break; @@ -522,10 +529,12 @@ static unsigned long vlapic_read(struct break; case 2: + ASSERT( alignment != 3 ); result = *(unsigned short *)((unsigned char *)&tmp + alignment); break; case 4: + ASSERT( alignment == 0 ); result = *(unsigned int *)((unsigned char *)&tmp + alignment); break; @@ -561,7 +570,7 @@ static void vlapic_write(struct vcpu *v, unsigned int tmp; unsigned char alignment; - /* Some kernel do will access with byte/word alignment*/ + /* Some kernels do will access with byte/word alignment */ printk("Notice: Local APIC write with len = %lx\n",len); alignment = offset & 0x3; tmp = vlapic_read(v, offset & ~0x3, 4); @@ -570,8 +579,8 @@ static void vlapic_write(struct vcpu *v, /* XXX the saddr is a tmp variable from caller, so should be ok But we should still change the following ref to val to local variable later */ - val = (tmp & ~(0xff << alignment)) | - ((val & 0xff) << alignment); + val = (tmp & ~(0xff << (8*alignment))) | + ((val & 0xff) << (8*alignment)); break; case 2: @@ -581,8 +590,8 @@ static void vlapic_write(struct vcpu *v, domain_crash_synchronous(); } - val = (tmp & ~(0xffff << alignment)) | - ((val & 0xffff) << alignment); + val = (tmp & ~(0xffff << (8*alignment))) | + ((val & 0xffff) << (8*alignment)); break; case 3: @@ -619,11 +628,11 @@ static void vlapic_write(struct vcpu *v, break; case APIC_DFR: - vlapic_set_reg(vlapic, APIC_DFR, val); + vlapic_set_reg(vlapic, APIC_DFR, val | 0x0FFFFFFF); break; case APIC_SPIV: - vlapic_set_reg(vlapic, APIC_SPIV, val & 0x1ff); + vlapic_set_reg(vlapic, APIC_SPIV, val & 0x3ff); if ( !( val & APIC_SPIV_APIC_ENABLED) ) { @@ -634,7 +643,7 @@ static void vlapic_write(struct vcpu *v, for ( i = 0; i < VLAPIC_LVT_NUM; i++ ) { - lvt_val = vlapic_get_reg(vlapic, APIC_LVT1 + 0x10 * i); + lvt_val = vlapic_get_reg(vlapic, APIC_LVTT + 0x10 * i); vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i, lvt_val | APIC_LVT_MASKED); } @@ -753,7 +762,7 @@ static int vlapic_range(struct vcpu *v, if ( vlapic_global_enabled(vlapic) && (addr >= vlapic->base_address) && - (addr <= vlapic->base_address + VLOCAL_APIC_MEM_LENGTH) ) + (addr < vlapic->base_address + VLOCAL_APIC_MEM_LENGTH) ) return 1; return 0; @@ -940,7 +949,7 @@ void vlapic_post_injection(struct vcpu * case APIC_DM_NMI: case APIC_DM_INIT: case APIC_DM_STARTUP: - vlapic->direct_intr.deliver_mode &= deliver_mode; + vlapic->direct_intr.deliver_mode &= (1 << (deliver_mode >> 8)); break; default: diff -r 713b0878da2f -r f393ced88d14 xen/include/asm-x86/hvm/vioapic.h --- a/xen/include/asm-x86/hvm/vioapic.h Thu Aug 10 10:45:10 2006 +0100 +++ b/xen/include/asm-x86/hvm/vioapic.h Thu Aug 10 10:47:37 2006 +0100 @@ -86,11 +86,6 @@ typedef union RedirStatus } RedirForm; } RedirStatus; -#define IOAPIC_MEM_LENGTH 0x100 -#define IOAPIC_ENABLE_MASK 0x0 -#define IOAPIC_ENABLE_FLAG (1 << IOAPIC_ENABLE_MASK) -#define MAX_LAPIC_NUM 32 - typedef struct hvm_vioapic { uint32_t irr; uint32_t isr; /* This is used for level trigger */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |