ia64/xen-unstable

changeset 11075:f393ced88d14

[HVM] Fix some IOAPIC and LAPIC device model bugs.

Fix some boundary checking errors.
Fix the confusion using variables 'level' and 'trig_mode'.
Also fix some other misc mistakes and do some cleanup.

Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
author kfraser@localhost.localdomain
date Thu Aug 10 10:47:37 2006 +0100 (2006-08-10)
parents 713b0878da2f
children 108c05a9f706
files xen/arch/x86/hvm/vioapic.c xen/arch/x86/hvm/vlapic.c xen/include/asm-x86/hvm/vioapic.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vioapic.c	Thu Aug 10 10:45:10 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/vioapic.c	Thu Aug 10 10:47:37 2006 +0100
     1.3 @@ -79,7 +79,7 @@ static unsigned long hvm_vioapic_read_in
     1.4      switch (s->ioregsel) {
     1.5      case IOAPIC_REG_VERSION:
     1.6          result = ((((IOAPIC_NUM_PINS-1) & 0xff) << 16)
     1.7 -                  | (IOAPIC_VERSION_ID & 0x0f));
     1.8 +                  | (IOAPIC_VERSION_ID & 0xff));
     1.9          break;
    1.10  
    1.11  #ifndef __ia64__
    1.12 @@ -89,7 +89,7 @@ static unsigned long hvm_vioapic_read_in
    1.13  
    1.14      case IOAPIC_REG_ARB_ID:
    1.15          /* XXX how arb_id used on p4? */
    1.16 -        result = ((s->id & 0xf) << 24);
    1.17 +        result = ((s->arb_id & 0xf) << 24);
    1.18          break;
    1.19  #endif
    1.20  
    1.21 @@ -107,7 +107,7 @@ static unsigned long hvm_vioapic_read_in
    1.22                             (redir_content >> 32) & 0xffffffff :
    1.23                             redir_content & 0xffffffff;
    1.24              } else {
    1.25 -                printk("upic_mem_readl:undefined ioregsel %x\n",
    1.26 +                printk("apic_mem_readl:undefined ioregsel %x\n",
    1.27                          s->ioregsel);
    1.28                  domain_crash_synchronous();
    1.29              }
    1.30 @@ -244,7 +244,7 @@ static int hvm_vioapic_range(struct vcpu
    1.31  
    1.32      if ((s->flags & IOAPIC_ENABLE_FLAG) &&
    1.33          (addr >= s->base_address &&
    1.34 -        (addr <= s->base_address + IOAPIC_MEM_LENGTH)))
    1.35 +        (addr < s->base_address + IOAPIC_MEM_LENGTH)))
    1.36          return 1;
    1.37      else
    1.38          return 0;
    1.39 @@ -427,7 +427,7 @@ static void ioapic_deliver(hvm_vioapic_t
    1.40          else
    1.41              HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
    1.42                "null round robin mask %x vector %x delivery_mode %x\n",
    1.43 -              deliver_bitmask, vector, deliver_bitmask);
    1.44 +              deliver_bitmask, vector, dest_LowestPrio);
    1.45          break;
    1.46      }
    1.47  
    1.48 @@ -568,7 +568,7 @@ static int get_redir_num(hvm_vioapic_t *
    1.49  
    1.50      ASSERT(s);
    1.51  
    1.52 -    for(i = 0; i < IOAPIC_NUM_PINS - 1; i++) {
    1.53 +    for(i = 0; i < IOAPIC_NUM_PINS; i++) {
    1.54          if (s->redirtbl[i].RedirForm.vector == vector)
    1.55              return i;
    1.56      }
     2.1 --- a/xen/arch/x86/hvm/vlapic.c	Thu Aug 10 10:45:10 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/vlapic.c	Thu Aug 10 10:47:37 2006 +0100
     2.3 @@ -68,7 +68,7 @@ int vlapic_find_highest_irr(struct vlapi
     2.4       result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_IRR),
     2.5                                 MAX_VECTOR);
     2.6  
     2.7 -     ASSERT( result == -1 || result > 16);
     2.8 +     ASSERT( result == -1 || result >= 16);
     2.9  
    2.10       return result;
    2.11  }
    2.12 @@ -91,7 +91,7 @@ int vlapic_find_highest_isr(struct vlapi
    2.13      result = find_highest_bit((unsigned long *)(vlapic->regs + APIC_ISR),
    2.14                                 MAX_VECTOR);
    2.15  
    2.16 -    ASSERT( result == -1 || result > 16);
    2.17 +    ASSERT( result == -1 || result >= 16);
    2.18  
    2.19      return result;
    2.20  }
    2.21 @@ -156,10 +156,11 @@ static int vlapic_match_dest(struct vcpu
    2.22          }
    2.23          else                /* Logical */
    2.24          {
    2.25 -            uint32_t ldr = vlapic_get_reg(target, APIC_LDR);
    2.26 -
    2.27 +            uint32_t ldr;
    2.28              if ( target == NULL )
    2.29                  break;
    2.30 +            ldr = vlapic_get_reg(target, APIC_LDR);
    2.31 +            
    2.32              /* Flat mode */
    2.33              if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT)
    2.34              {
    2.35 @@ -219,14 +220,14 @@ static int vlapic_accept_irq(struct vcpu
    2.36          if ( unlikely(vlapic == NULL || !vlapic_enabled(vlapic)) )
    2.37              break;
    2.38  
    2.39 -        if ( test_and_set_bit(vector, vlapic->regs + APIC_IRR) )
    2.40 +        if ( test_and_set_bit(vector, vlapic->regs + APIC_IRR) && trig_mode)
    2.41          {
    2.42              HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
    2.43 -              "level trig mode repeatedly for vector %d\n", vector);
    2.44 +                  "level trig mode repeatedly for vector %d\n", vector);
    2.45              break;
    2.46          }
    2.47  
    2.48 -        if ( level )
    2.49 +        if ( trig_mode )
    2.50          {
    2.51              HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
    2.52                "level trig mode for vector %d\n", vector);
    2.53 @@ -248,7 +249,7 @@ static int vlapic_accept_irq(struct vcpu
    2.54          break;
    2.55  
    2.56      case APIC_DM_INIT:
    2.57 -        if ( level && !(trig_mode & APIC_INT_ASSERT) )     //Deassert
    2.58 +        if ( trig_mode && !(level & APIC_INT_ASSERT) )     //Deassert
    2.59              printk("This hvm_vlapic is for P4, no work for De-assert init\n");
    2.60          else
    2.61          {
    2.62 @@ -290,11 +291,12 @@ static int vlapic_accept_irq(struct vcpu
    2.63  
    2.64      return result;
    2.65  }
    2.66 +
    2.67  /*
    2.68 -    This function is used by both ioapic and local APIC
    2.69 -    The bitmap is for vcpu_id
    2.70 + * This function is used by both ioapic and local APIC
    2.71 + * The bitmap is for vcpu_id
    2.72   */
    2.73 -struct vlapic* apic_round_robin(struct domain *d,
    2.74 +struct vlapic *apic_round_robin(struct domain *d,
    2.75                                  uint8_t dest_mode,
    2.76                                  uint8_t vector,
    2.77                                  uint32_t bitmap)
    2.78 @@ -321,11 +323,11 @@ struct vlapic* apic_round_robin(struct d
    2.79      /* the vcpu array is arranged according to vcpu_id */
    2.80      do
    2.81      {
    2.82 -        next++;
    2.83 -        if ( !d->vcpu[next] ||
    2.84 -             !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) ||
    2.85 -             next == MAX_VIRT_CPUS )
    2.86 +        if ( ++next == MAX_VIRT_CPUS ) 
    2.87              next = 0;
    2.88 +        if ( d->vcpu[next] == NULL ||
    2.89 +             !test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) )
    2.90 +            continue;
    2.91  
    2.92          if ( test_bit(next, &bitmap) )
    2.93          {
    2.94 @@ -384,15 +386,15 @@ static void vlapic_ipi(struct vlapic *vl
    2.95  
    2.96      unsigned int dest =         GET_APIC_DEST_FIELD(icr_high);
    2.97      unsigned int short_hand =   icr_low & APIC_SHORT_MASK;
    2.98 -    unsigned int trig_mode =    icr_low & APIC_INT_ASSERT;
    2.99 -    unsigned int level =        icr_low & APIC_INT_LEVELTRIG;
   2.100 +    unsigned int trig_mode =    icr_low & APIC_INT_LEVELTRIG;
   2.101 +    unsigned int level =        icr_low & APIC_INT_ASSERT;
   2.102      unsigned int dest_mode =    icr_low & APIC_DEST_MASK;
   2.103      unsigned int delivery_mode =    icr_low & APIC_MODE_MASK;
   2.104      unsigned int vector =       icr_low & APIC_VECTOR_MASK;
   2.105  
   2.106      struct vlapic *target;
   2.107      struct vcpu *v = NULL;
   2.108 -    uint32_t lpr_map;
   2.109 +    uint32_t lpr_map=0;
   2.110  
   2.111      HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "icr_high 0x%x, icr_low 0x%x, "
   2.112                  "short_hand 0x%x, dest 0x%x, trig_mode 0x%x, level 0x%x, "
   2.113 @@ -456,7 +458,7 @@ static uint32_t vlapic_get_tmcct(struct 
   2.114          {
   2.115              do {
   2.116                  tmcct += vlapic_get_reg(vlapic, APIC_TMICT);
   2.117 -            } while ( tmcct < 0 );
   2.118 +            } while ( tmcct <= 0 );
   2.119          }
   2.120      }
   2.121  
   2.122 @@ -489,6 +491,11 @@ static void vlapic_read_aligned(struct v
   2.123          *result = vlapic_get_tmcct(vlapic);
   2.124          break;
   2.125  
   2.126 +    case APIC_ESR:
   2.127 +        vlapic->err_write_count = 0;
   2.128 +        *result = vlapic_get_reg(vlapic, offset); 
   2.129 +        break;
   2.130 +
   2.131      default:
   2.132          *result = vlapic_get_reg(vlapic, offset);
   2.133          break;
   2.134 @@ -522,10 +529,12 @@ static unsigned long vlapic_read(struct 
   2.135          break;
   2.136  
   2.137      case 2:
   2.138 +        ASSERT( alignment != 3 );
   2.139          result = *(unsigned short *)((unsigned char *)&tmp + alignment);
   2.140          break;
   2.141  
   2.142      case 4:
   2.143 +        ASSERT( alignment == 0 );
   2.144          result = *(unsigned int *)((unsigned char *)&tmp + alignment);
   2.145          break;
   2.146  
   2.147 @@ -561,7 +570,7 @@ static void vlapic_write(struct vcpu *v,
   2.148          unsigned int tmp;
   2.149          unsigned char alignment;
   2.150  
   2.151 -        /* Some kernel do will access with byte/word alignment*/
   2.152 +        /* Some kernels do will access with byte/word alignment */
   2.153          printk("Notice: Local APIC write with len = %lx\n",len);
   2.154          alignment = offset & 0x3;
   2.155          tmp = vlapic_read(v, offset & ~0x3, 4);
   2.156 @@ -570,8 +579,8 @@ static void vlapic_write(struct vcpu *v,
   2.157              /* XXX the saddr is a tmp variable from caller, so should be ok
   2.158                 But we should still change the following ref to val to
   2.159                 local variable later */
   2.160 -            val = (tmp & ~(0xff << alignment)) |
   2.161 -                  ((val & 0xff) << alignment);
   2.162 +            val = (tmp & ~(0xff << (8*alignment))) |
   2.163 +                  ((val & 0xff) << (8*alignment));
   2.164              break;
   2.165  
   2.166          case 2:
   2.167 @@ -581,8 +590,8 @@ static void vlapic_write(struct vcpu *v,
   2.168                  domain_crash_synchronous();
   2.169              }
   2.170  
   2.171 -            val = (tmp & ~(0xffff << alignment)) |
   2.172 -                  ((val & 0xffff) << alignment);
   2.173 +            val = (tmp & ~(0xffff << (8*alignment))) |
   2.174 +                  ((val & 0xffff) << (8*alignment));
   2.175              break;
   2.176  
   2.177          case 3:
   2.178 @@ -619,11 +628,11 @@ static void vlapic_write(struct vcpu *v,
   2.179          break;
   2.180  
   2.181      case APIC_DFR:
   2.182 -        vlapic_set_reg(vlapic, APIC_DFR, val);
   2.183 +        vlapic_set_reg(vlapic, APIC_DFR, val | 0x0FFFFFFF);
   2.184          break;
   2.185  
   2.186      case APIC_SPIV:
   2.187 -        vlapic_set_reg(vlapic, APIC_SPIV, val & 0x1ff);
   2.188 +        vlapic_set_reg(vlapic, APIC_SPIV, val & 0x3ff);
   2.189  
   2.190          if ( !( val & APIC_SPIV_APIC_ENABLED) )
   2.191          {
   2.192 @@ -634,7 +643,7 @@ static void vlapic_write(struct vcpu *v,
   2.193  
   2.194              for ( i = 0; i < VLAPIC_LVT_NUM; i++ )
   2.195              {
   2.196 -                lvt_val = vlapic_get_reg(vlapic, APIC_LVT1 + 0x10 * i);
   2.197 +                lvt_val = vlapic_get_reg(vlapic, APIC_LVTT + 0x10 * i);
   2.198                  vlapic_set_reg(vlapic, APIC_LVTT + 0x10 * i,
   2.199                                 lvt_val | APIC_LVT_MASKED);
   2.200              }
   2.201 @@ -753,7 +762,7 @@ static int vlapic_range(struct vcpu *v, 
   2.202  
   2.203      if ( vlapic_global_enabled(vlapic) &&
   2.204           (addr >= vlapic->base_address) &&
   2.205 -         (addr <= vlapic->base_address + VLOCAL_APIC_MEM_LENGTH) )
   2.206 +         (addr < vlapic->base_address + VLOCAL_APIC_MEM_LENGTH) )
   2.207          return 1;
   2.208  
   2.209      return 0;
   2.210 @@ -940,7 +949,7 @@ void vlapic_post_injection(struct vcpu *
   2.211      case APIC_DM_NMI:
   2.212      case APIC_DM_INIT:
   2.213      case APIC_DM_STARTUP:
   2.214 -        vlapic->direct_intr.deliver_mode &= deliver_mode;
   2.215 +        vlapic->direct_intr.deliver_mode &= (1 << (deliver_mode >> 8));
   2.216          break;
   2.217  
   2.218      default:
     3.1 --- a/xen/include/asm-x86/hvm/vioapic.h	Thu Aug 10 10:45:10 2006 +0100
     3.2 +++ b/xen/include/asm-x86/hvm/vioapic.h	Thu Aug 10 10:47:37 2006 +0100
     3.3 @@ -86,11 +86,6 @@ typedef union RedirStatus
     3.4      } RedirForm;
     3.5  } RedirStatus;
     3.6  
     3.7 -#define IOAPIC_MEM_LENGTH    0x100
     3.8 -#define IOAPIC_ENABLE_MASK   0x0
     3.9 -#define IOAPIC_ENABLE_FLAG   (1 << IOAPIC_ENABLE_MASK)
    3.10 -#define MAX_LAPIC_NUM        32
    3.11 -
    3.12  typedef struct hvm_vioapic {
    3.13      uint32_t irr;
    3.14      uint32_t isr;           /* This is used for level trigger */