# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID bee09e2200ab0386437e8824c152ad2ae7541f68
# Parent de41f5e24cf1b39a57ad343c84e2221ad62b9afa
Fix IPI handling before vcpu launched
When sending IPI, the target vcpu may not be launched (like
INIT/Start-Up IPI), and the local apic is not initialized. Fix handling
on such case.
Also fix one bug in apic_round_robin function.
Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx>
diff -r de41f5e24cf1 -r bee09e2200ab xen/arch/x86/vmx_vlapic.c
--- a/xen/arch/x86/vmx_vlapic.c Thu Nov 10 11:09:17 2005
+++ b/xen/arch/x86/vmx_vlapic.c Thu Nov 10 11:11:39 2005
@@ -119,22 +119,35 @@
}
/* This only for fixed delivery mode */
-int vlapic_match_dest(struct vlapic *target, struct vlapic *source,
- int short_hand, int dest, int dest_mode,
- int 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 result = 0;
+ struct vlapic *target = VLAPIC(v);
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
"target %p source %p dest %x dest_mode %x short_hand %x "
"delivery_mode %x",
target, source, dest, dest_mode, short_hand, delivery_mode);
+ if ( unlikely(!target) &&
+ ( (delivery_mode != VLAPIC_DELIV_MODE_INIT) &&
+ (delivery_mode != VLAPIC_DELIV_MODE_STARTUP) &&
+ (delivery_mode != VLAPIC_DELIV_MODE_NMI) )) {
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest "
+ "uninitialized target v %p delivery_mode %x dest %x\n",
+ v, delivery_mode, dest);
+ return result;
+ }
+
switch (short_hand) {
case VLAPIC_NO_SHORTHAND:
if (!dest_mode) { /* Physical */
- result = (target->id == dest);
+ result = ((target ? target->id : v->vcpu_id ) == dest);
} else { /* Logical */
+ if (!target)
+ break;
if (((target->dest_format >> 28) & 0xf) == 0xf) { /* Flat mode */
result = (target->logical_dest >> 24) & dest;
} else {
@@ -176,17 +189,18 @@
* Add a pending IRQ into lapic.
* Return 1 if successfully added and 0 if discarded.
*/
-int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode,
- int vector, int level, int trig_mode)
-{
- int result = 1;
+static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
+ int vector, int level, int trig_mode)
+{
+ int result = 0;
+ struct vlapic *vlapic = VLAPIC(v);
switch (delivery_mode) {
case VLAPIC_DELIV_MODE_FIXED:
case VLAPIC_DELIV_MODE_LPRI:
/* FIXME add logic for vcpu on reset */
- if (!vlapic->vcpu || !vlapic_enabled(vlapic))
- return 0;
+ if (unlikely(!vlapic || !vlapic_enabled(vlapic)))
+ return result;
if (test_and_set_bit(vector, &vlapic->irr[0])) {
printk("<vlapic_accept_irq>"
@@ -199,6 +213,7 @@
}
}
evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
+ result = 1;
break;
case VLAPIC_DELIV_MODE_RESERVED:
@@ -269,15 +284,12 @@
old = next = d->arch.vmx_platform.round_info[vector];
- next++;
- if (next == MAX_VIRT_CPUS || !d->vcpu[next])
- next = 0;
-
do {
/* the vcpu array is arranged according to vcpu_id */
if (test_bit(next, &bitmap)) {
target = d->vcpu[next]->arch.arch_vmx.vlapic;
- if (!vlapic_enabled(target)) {
+
+ if (!target || !vlapic_enabled(target)) {
printk("warning: targe round robin local apic disabled\n");
/* XXX should we domain crash?? Or should we return NULL */
}
@@ -285,7 +297,9 @@
}
next ++;
- if (next == MAX_VIRT_CPUS || !d->vcpu[next])
+ if (!d->vcpu[next] ||
+ !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) ||
+ next == MAX_VIRT_CPUS)
next = 0;
}while(next != old);
@@ -319,7 +333,7 @@
{
if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) {
vlapic->err_status |= 0x40;
- vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED,
+ vlapic_accept_irq(vlapic->vcpu, VLAPIC_DELIV_MODE_FIXED,
vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0);
printk("<vlapic_check_vector>: check fail\n");
return 0;
@@ -340,7 +354,6 @@
struct vlapic *target;
struct vcpu *v = NULL;
- int result = 0;
uint32_t lpr_map;
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
@@ -352,32 +365,27 @@
delivery_mode, vector);
for_each_vcpu ( vlapic->domain, v ) {
- target = VLAPIC(v);
- if (vlapic_match_dest(target, vlapic, short_hand,
+ if (vlapic_match_dest(v, vlapic, short_hand,
dest, dest_mode, delivery_mode)) {
if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
set_bit(v->vcpu_id, &lpr_map);
- }else
- result = vlapic_accept_irq(target, delivery_mode,
- vector, level, trig_mode);
+ } else
+ vlapic_accept_irq(v, delivery_mode,
+ vector, level, trig_mode);
}
}
if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
- extern struct vlapic*
- apic_round_robin(struct domain *d,
- uint8_t dest_mode, uint8_t vector, uint32_t bitmap);
-
v = vlapic->vcpu;
target = apic_round_robin(v->domain, dest_mode, vector, lpr_map);
if (target)
- vlapic_accept_irq(target, delivery_mode,
- vector, level, trig_mode);
- }
-}
-
-void vlapic_begin_timer(struct vlapic *vlapic)
+ vlapic_accept_irq(target->vcpu, delivery_mode,
+ vector, level, trig_mode);
+ }
+}
+
+static void vlapic_begin_timer(struct vlapic *vlapic)
{
s_time_t cur = NOW(), offset;
@@ -737,12 +745,13 @@
vlapic->timer_current = val;
vlapic->timer_current_update = NOW();
+ vlapic_begin_timer(vlapic);
+
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "timer_init %x timer_current %x"
"timer_current_update %08x%08x",
vlapic->timer_initial, vlapic->timer_current,
(uint32_t)(vlapic->timer_current_update >> 32),
(uint32_t)vlapic->timer_current_update);
- vlapic_begin_timer(vlapic);
break;
case APIC_TDCR:
@@ -827,6 +836,7 @@
}
else
vlapic->intr_pending_count[vlapic_lvt_vector(vlapic,
VLAPIC_LVT_TIMER)]++;
+ evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
}
vlapic->timer_current_update = NOW();
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|