ia64/xen-unstable
changeset 7764:bee09e2200ab
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@intel.com>
Signed-off-by: Xin Li <xin.b.li@intel.com>
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@intel.com>
Signed-off-by: Xin Li <xin.b.li@intel.com>
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Thu Nov 10 12:11:39 2005 +0100 (2005-11-10) |
parents | de41f5e24cf1 |
children | c405c0d1b49b |
files | xen/arch/x86/vmx_vlapic.c |
line diff
1.1 --- a/xen/arch/x86/vmx_vlapic.c Thu Nov 10 12:09:17 2005 +0100 1.2 +++ b/xen/arch/x86/vmx_vlapic.c Thu Nov 10 12:11:39 2005 +0100 1.3 @@ -119,22 +119,35 @@ uint32_t vlapic_update_ppr(struct vlapic 1.4 } 1.5 1.6 /* This only for fixed delivery mode */ 1.7 -int vlapic_match_dest(struct vlapic *target, struct vlapic *source, 1.8 - int short_hand, int dest, int dest_mode, 1.9 - int delivery_mode) 1.10 +static int vlapic_match_dest(struct vcpu *v, struct vlapic *source, 1.11 + int short_hand, int dest, int dest_mode, 1.12 + int delivery_mode) 1.13 { 1.14 int result = 0; 1.15 + struct vlapic *target = VLAPIC(v); 1.16 1.17 VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: " 1.18 "target %p source %p dest %x dest_mode %x short_hand %x " 1.19 "delivery_mode %x", 1.20 target, source, dest, dest_mode, short_hand, delivery_mode); 1.21 1.22 + if ( unlikely(!target) && 1.23 + ( (delivery_mode != VLAPIC_DELIV_MODE_INIT) && 1.24 + (delivery_mode != VLAPIC_DELIV_MODE_STARTUP) && 1.25 + (delivery_mode != VLAPIC_DELIV_MODE_NMI) )) { 1.26 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest " 1.27 + "uninitialized target v %p delivery_mode %x dest %x\n", 1.28 + v, delivery_mode, dest); 1.29 + return result; 1.30 + } 1.31 + 1.32 switch (short_hand) { 1.33 case VLAPIC_NO_SHORTHAND: 1.34 if (!dest_mode) { /* Physical */ 1.35 - result = (target->id == dest); 1.36 + result = ((target ? target->id : v->vcpu_id ) == dest); 1.37 } else { /* Logical */ 1.38 + if (!target) 1.39 + break; 1.40 if (((target->dest_format >> 28) & 0xf) == 0xf) { /* Flat mode */ 1.41 result = (target->logical_dest >> 24) & dest; 1.42 } else { 1.43 @@ -176,17 +189,18 @@ int vlapic_match_dest(struct vlapic *tar 1.44 * Add a pending IRQ into lapic. 1.45 * Return 1 if successfully added and 0 if discarded. 1.46 */ 1.47 -int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode, 1.48 - int vector, int level, int trig_mode) 1.49 +static int vlapic_accept_irq(struct vcpu *v, int delivery_mode, 1.50 + int vector, int level, int trig_mode) 1.51 { 1.52 - int result = 1; 1.53 + int result = 0; 1.54 + struct vlapic *vlapic = VLAPIC(v); 1.55 1.56 switch (delivery_mode) { 1.57 case VLAPIC_DELIV_MODE_FIXED: 1.58 case VLAPIC_DELIV_MODE_LPRI: 1.59 /* FIXME add logic for vcpu on reset */ 1.60 - if (!vlapic->vcpu || !vlapic_enabled(vlapic)) 1.61 - return 0; 1.62 + if (unlikely(!vlapic || !vlapic_enabled(vlapic))) 1.63 + return result; 1.64 1.65 if (test_and_set_bit(vector, &vlapic->irr[0])) { 1.66 printk("<vlapic_accept_irq>" 1.67 @@ -199,6 +213,7 @@ int vlapic_accept_irq(struct vlapic *vla 1.68 } 1.69 } 1.70 evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain)); 1.71 + result = 1; 1.72 break; 1.73 1.74 case VLAPIC_DELIV_MODE_RESERVED: 1.75 @@ -269,15 +284,12 @@ struct vlapic* apic_round_robin(struct d 1.76 1.77 old = next = d->arch.vmx_platform.round_info[vector]; 1.78 1.79 - next++; 1.80 - if (next == MAX_VIRT_CPUS || !d->vcpu[next]) 1.81 - next = 0; 1.82 - 1.83 do { 1.84 /* the vcpu array is arranged according to vcpu_id */ 1.85 if (test_bit(next, &bitmap)) { 1.86 target = d->vcpu[next]->arch.arch_vmx.vlapic; 1.87 - if (!vlapic_enabled(target)) { 1.88 + 1.89 + if (!target || !vlapic_enabled(target)) { 1.90 printk("warning: targe round robin local apic disabled\n"); 1.91 /* XXX should we domain crash?? Or should we return NULL */ 1.92 } 1.93 @@ -285,7 +297,9 @@ struct vlapic* apic_round_robin(struct d 1.94 } 1.95 1.96 next ++; 1.97 - if (next == MAX_VIRT_CPUS || !d->vcpu[next]) 1.98 + if (!d->vcpu[next] || 1.99 + !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) || 1.100 + next == MAX_VIRT_CPUS) 1.101 next = 0; 1.102 }while(next != old); 1.103 1.104 @@ -319,7 +333,7 @@ int vlapic_check_vector(struct vlapic *v 1.105 { 1.106 if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) { 1.107 vlapic->err_status |= 0x40; 1.108 - vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED, 1.109 + vlapic_accept_irq(vlapic->vcpu, VLAPIC_DELIV_MODE_FIXED, 1.110 vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0); 1.111 printk("<vlapic_check_vector>: check fail\n"); 1.112 return 0; 1.113 @@ -340,7 +354,6 @@ void vlapic_ipi(struct vlapic *vlapic) 1.114 1.115 struct vlapic *target; 1.116 struct vcpu *v = NULL; 1.117 - int result = 0; 1.118 uint32_t lpr_map; 1.119 1.120 VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: " 1.121 @@ -352,32 +365,27 @@ void vlapic_ipi(struct vlapic *vlapic) 1.122 delivery_mode, vector); 1.123 1.124 for_each_vcpu ( vlapic->domain, v ) { 1.125 - target = VLAPIC(v); 1.126 - if (vlapic_match_dest(target, vlapic, short_hand, 1.127 + if (vlapic_match_dest(v, vlapic, short_hand, 1.128 dest, dest_mode, delivery_mode)) { 1.129 if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) { 1.130 set_bit(v->vcpu_id, &lpr_map); 1.131 - }else 1.132 - result = vlapic_accept_irq(target, delivery_mode, 1.133 - vector, level, trig_mode); 1.134 + } else 1.135 + vlapic_accept_irq(v, delivery_mode, 1.136 + vector, level, trig_mode); 1.137 } 1.138 } 1.139 1.140 if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) { 1.141 - extern struct vlapic* 1.142 - apic_round_robin(struct domain *d, 1.143 - uint8_t dest_mode, uint8_t vector, uint32_t bitmap); 1.144 - 1.145 v = vlapic->vcpu; 1.146 target = apic_round_robin(v->domain, dest_mode, vector, lpr_map); 1.147 1.148 if (target) 1.149 - vlapic_accept_irq(target, delivery_mode, 1.150 - vector, level, trig_mode); 1.151 + vlapic_accept_irq(target->vcpu, delivery_mode, 1.152 + vector, level, trig_mode); 1.153 } 1.154 } 1.155 1.156 -void vlapic_begin_timer(struct vlapic *vlapic) 1.157 +static void vlapic_begin_timer(struct vlapic *vlapic) 1.158 { 1.159 s_time_t cur = NOW(), offset; 1.160 1.161 @@ -737,12 +745,13 @@ static void vlapic_write(struct vcpu *v, 1.162 vlapic->timer_current = val; 1.163 vlapic->timer_current_update = NOW(); 1.164 1.165 + vlapic_begin_timer(vlapic); 1.166 + 1.167 VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "timer_init %x timer_current %x" 1.168 "timer_current_update %08x%08x", 1.169 vlapic->timer_initial, vlapic->timer_current, 1.170 (uint32_t)(vlapic->timer_current_update >> 32), 1.171 (uint32_t)vlapic->timer_current_update); 1.172 - vlapic_begin_timer(vlapic); 1.173 break; 1.174 1.175 case APIC_TDCR: 1.176 @@ -827,6 +836,7 @@ void vlapic_timer_fn(void *data) 1.177 } 1.178 else 1.179 vlapic->intr_pending_count[vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)]++; 1.180 + evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain)); 1.181 } 1.182 1.183 vlapic->timer_current_update = NOW();