# 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
|