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>
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();