aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/vlapic.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-08-31 10:54:32 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-08-31 10:54:32 +0100
commitdc7a191f9d359ae1b27c2f2f65b805fbe8c8e1fa (patch)
tree8e8c4a9a123e193bc3857296c1262498ab3107d4 /xen/arch/x86/hvm/vlapic.c
parentd3904eaa46578003806719879cea53268f4f8643 (diff)
downloadxen-dc7a191f9d359ae1b27c2f2f65b805fbe8c8e1fa.tar.gz
xen-dc7a191f9d359ae1b27c2f2f65b805fbe8c8e1fa.tar.bz2
xen-dc7a191f9d359ae1b27c2f2f65b805fbe8c8e1fa.zip
x86 hvm: Clean up VLAPIC interfaces a little, and fix vlapic_ipi().
A boolean flag was overflowing a uint8_t. Thanks to Dongxiao Xu at Intel for tracking down the bug. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/arch/x86/hvm/vlapic.c')
-rw-r--r--xen/arch/x86/hvm/vlapic.c61
1 files changed, 17 insertions, 44 deletions
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index cc50cbca41..b915609d36 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -296,35 +296,19 @@ static int vlapic_accept_sipi(struct vcpu *v, int trampoline_vector)
}
/* Add a pending IRQ into lapic. */
-static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
- int vector, int level, int trig_mode)
+static int vlapic_accept_irq(struct vcpu *v, uint32_t icr_low)
{
struct vlapic *vlapic = vcpu_vlapic(v);
+ uint8_t vector = (uint8_t)icr_low;
int rc = X86EMUL_OKAY;
- switch ( delivery_mode )
+ switch ( icr_low & APIC_MODE_MASK )
{
case APIC_DM_FIXED:
case APIC_DM_LOWEST:
- /* FIXME add logic for vcpu on reset */
- if ( unlikely(!vlapic_enabled(vlapic)) )
- break;
-
- if ( vlapic_test_and_set_irr(vector, vlapic) && trig_mode )
- {
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
- "level trig mode repeatedly for vector %d", vector);
- break;
- }
-
- if ( trig_mode )
- {
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
- "level trig mode for vector %d", vector);
- vlapic_set_vector(vector, &vlapic->regs->data[APIC_TMR]);
- }
-
- vcpu_kick(v);
+ if ( vlapic_enabled(vlapic) &&
+ !vlapic_test_and_set_irr(vector, vlapic) )
+ vcpu_kick(v);
break;
case APIC_DM_REMRD:
@@ -342,7 +326,8 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
case APIC_DM_INIT:
/* No work on INIT de-assert for P4-type APIC. */
- if ( trig_mode && !(level & APIC_INT_ASSERT) )
+ if ( (icr_low & (APIC_INT_LEVELTRIG | APIC_INT_ASSERT)) ==
+ APIC_INT_LEVELTRIG )
break;
rc = vlapic_accept_init(v);
break;
@@ -352,8 +337,8 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
break;
default:
- gdprintk(XENLOG_ERR, "TODO: unsupported delivery mode %x\n",
- delivery_mode);
+ gdprintk(XENLOG_ERR, "TODO: unsupported delivery mode in ICR %x\n",
+ icr_low);
domain_crash(v->domain);
}
@@ -410,31 +395,21 @@ void vlapic_EOI_set(struct vlapic *vlapic)
int vlapic_ipi(
struct vlapic *vlapic, uint32_t icr_low, uint32_t icr_high)
{
- unsigned int dest = GET_xAPIC_DEST_FIELD(icr_high);
- unsigned int short_hand = icr_low & APIC_SHORT_MASK;
- 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;
-
+ unsigned int dest = GET_xAPIC_DEST_FIELD(icr_high);
+ unsigned int short_hand = icr_low & APIC_SHORT_MASK;
+ unsigned int dest_mode = !!(icr_low & APIC_DEST_MASK);
struct vlapic *target;
struct vcpu *v;
int rc = X86EMUL_OKAY;
- 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, "
- "dest_mode 0x%x, delivery_mode 0x%x, vector 0x%x",
- icr_high, icr_low, short_hand, dest,
- trig_mode, level, dest_mode, delivery_mode, vector);
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr = 0x%08x:%08x", icr_high, icr_low);
- if ( delivery_mode == APIC_DM_LOWEST )
+ if ( (icr_low & APIC_MODE_MASK) == APIC_DM_LOWEST )
{
target = vlapic_lowest_prio(vlapic_domain(vlapic), vlapic,
short_hand, dest, dest_mode);
if ( target != NULL )
- rc = vlapic_accept_irq(vlapic_vcpu(target), delivery_mode,
- vector, level, trig_mode);
+ rc = vlapic_accept_irq(vlapic_vcpu(target), icr_low);
return rc;
}
@@ -442,9 +417,7 @@ int vlapic_ipi(
{
if ( vlapic_match_dest(vcpu_vlapic(v), vlapic,
short_hand, dest, dest_mode) )
- rc = vlapic_accept_irq(v, delivery_mode,
- vector, level, trig_mode);
-
+ rc = vlapic_accept_irq(v, icr_low);
if ( rc != X86EMUL_OKAY )
break;
}