aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hvm/vioapic.c37
-rw-r--r--xen/arch/x86/hvm/vlapic.c94
-rw-r--r--xen/include/asm-x86/hvm/vlapic.h2
3 files changed, 45 insertions, 88 deletions
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index dc7f29d820..c32ece46e3 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -35,6 +35,7 @@
#include <public/hvm/ioreq.h>
#include <asm/hvm/io.h>
#include <asm/hvm/vpic.h>
+#include <asm/hvm/vlapic.h>
#include <asm/hvm/support.h>
#include <asm/current.h>
#include <asm/event.h>
@@ -285,42 +286,6 @@ static int ioapic_inj_irq(struct vioapic *vioapic,
return result;
}
-#ifndef __ia64__
-static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t dest)
-{
- int result = 0;
- uint32_t logical_dest;
-
- HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vlapic_match_logical_addr "
- "vcpu=%d vlapic_id=%x dest=%x\n",
- vlapic_vcpu(vlapic)->vcpu_id, VLAPIC_ID(vlapic), dest);
-
- logical_dest = vlapic_get_reg(vlapic, APIC_LDR);
-
- switch ( vlapic_get_reg(vlapic, APIC_DFR) )
- {
- case APIC_DFR_FLAT:
- result = ((dest & GET_APIC_LOGICAL_ID(logical_dest)) != 0);
- break;
- case APIC_DFR_CLUSTER:
- /* Should we support flat cluster mode ?*/
- if ( (GET_APIC_LOGICAL_ID(logical_dest) >> 4
- == ((dest >> 0x4) & 0xf)) &&
- (logical_dest & (dest & 0xf)) )
- result = 1;
- break;
- default:
- gdprintk(XENLOG_WARNING, "error DFR value for lapic of vcpu %d\n",
- vlapic_vcpu(vlapic)->vcpu_id);
- break;
- }
-
- return result;
-}
-#else
-extern int vlapic_match_logical_addr(struct vlapic *vlapic, uint16_t dest);
-#endif
-
static uint32_t ioapic_get_delivery_bitmask(struct vioapic *vioapic,
uint16_t dest,
uint8_t dest_mode,
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 3209416157..bc8a9736d8 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -196,63 +196,56 @@ uint32_t vlapic_get_ppr(struct vlapic *vlapic)
return ppr;
}
-/* This only for fixed delivery mode */
-static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
- int short_hand, int dest, int dest_mode,
- int delivery_mode)
+int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
{
int result = 0;
- struct vlapic *target = vcpu_vlapic(v);
+ uint8_t logical_id;
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest 0x%x, "
- "dest_mode 0x%x, short_hand 0x%x, delivery_mode 0x%x.",
- target, source, dest, dest_mode, short_hand, delivery_mode);
+ logical_id = GET_APIC_LOGICAL_ID(vlapic_get_reg(vlapic, APIC_LDR));
- if ( unlikely(target == NULL) &&
- ((delivery_mode != APIC_DM_INIT) &&
- (delivery_mode != APIC_DM_STARTUP) &&
- (delivery_mode != APIC_DM_NMI)) )
+ switch ( vlapic_get_reg(vlapic, APIC_DFR) )
{
- HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "uninitialized target vcpu %p, "
- "delivery_mode 0x%x, dest 0x%x.\n",
- v, delivery_mode, dest);
- return result;
+ case APIC_DFR_FLAT:
+ if ( logical_id & mda )
+ result = 1;
+ break;
+ case APIC_DFR_CLUSTER:
+ if ( ((logical_id >> 4) == (mda >> 0x4)) && (logical_id & mda & 0xf) )
+ result = 1;
+ break;
+ default:
+ gdprintk(XENLOG_WARNING, "Bad DFR value for lapic of vcpu %d\n",
+ vlapic_vcpu(vlapic)->vcpu_id);
+ break;
}
+ return result;
+}
+
+static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
+ int short_hand, int dest, int dest_mode)
+{
+ int result = 0;
+ struct vlapic *target = vcpu_vlapic(v);
+
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest 0x%x, "
+ "dest_mode 0x%x, short_hand 0x%x\n",
+ target, source, dest, dest_mode, short_hand);
+
switch ( short_hand )
{
- case APIC_DEST_NOSHORT: /* no shorthand */
- if ( !dest_mode ) /* Physical */
+ case APIC_DEST_NOSHORT:
+ if ( dest_mode == 0 )
{
- result = ( ((target != NULL) ?
- GET_APIC_ID(vlapic_get_reg(target, APIC_ID)):
- v->vcpu_id)) == dest;
+ /* Physical mode. */
+ if ( (dest == 0xFF) || /* broadcast? */
+ (GET_APIC_ID(vlapic_get_reg(target, APIC_ID)) == dest) )
+ result = 1;
}
- else /* Logical */
+ else
{
- 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 )
- {
- result = GET_APIC_LOGICAL_ID(ldr) & dest;
- }
- else
- {
- if ( (delivery_mode == APIC_DM_LOWEST) &&
- (dest == 0xff) )
- {
- /* What shall we do now? */
- gdprintk(XENLOG_ERR, "Broadcast IPI with lowest priority "
- "delivery mode\n");
- domain_crash_synchronous();
- }
- result = ((GET_APIC_LOGICAL_ID(ldr) == (dest & 0xf)) ?
- (GET_APIC_LOGICAL_ID(ldr) >> 4) & (dest >> 4) : 0);
- }
+ /* Logical mode. */
+ result = vlapic_match_logical_addr(target, dest);
}
break;
@@ -271,16 +264,14 @@ static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
break;
default:
+ gdprintk(XENLOG_WARNING, "Bad dest shorthand value %x\n", short_hand);
break;
}
return result;
}
-/*
- * Add a pending IRQ into lapic.
- * Return 1 if successfully added and 0 if discarded.
- */
+/* Add a pending IRQ into lapic. */
static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
int vector, int level, int trig_mode)
{
@@ -440,10 +431,9 @@ static void vlapic_ipi(struct vlapic *vlapic)
for_each_vcpu ( vlapic_domain(vlapic), v )
{
- if ( vlapic_match_dest(v, vlapic, short_hand,
- dest, dest_mode, delivery_mode) )
+ if ( vlapic_match_dest(v, vlapic, short_hand, dest, dest_mode) )
{
- if ( delivery_mode == APIC_DM_LOWEST)
+ if ( delivery_mode == APIC_DM_LOWEST )
set_bit(v->vcpu_id, &lpr_map);
else
vlapic_accept_irq(v, delivery_mode,
diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h
index c327f5ef3f..807d17e379 100644
--- a/xen/include/asm-x86/hvm/vlapic.h
+++ b/xen/include/asm-x86/hvm/vlapic.h
@@ -90,4 +90,6 @@ struct vlapic *apic_round_robin(
s_time_t get_apictime_scheduled(struct vcpu *v);
+int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
+
#endif /* __ASM_X86_HVM_VLAPIC_H__ */