ia64/xen-unstable

changeset 12042:7e52933a46b1

[XEN] HVM: Clean up and simplify vlapic device-model code.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Oct 30 13:53:09 2006 +0000 (2006-10-30)
parents 2b99c99f96e6
children c3b4fef4f751
files xen/arch/x86/hvm/vlapic.c xen/include/asm-x86/hvm/vlapic.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vlapic.c	Mon Oct 30 10:42:27 2006 +0000
     1.2 +++ b/xen/arch/x86/hvm/vlapic.c	Mon Oct 30 13:53:09 2006 +0000
     1.3 @@ -29,13 +29,15 @@
     1.4  #include <asm/hvm/hvm.h>
     1.5  #include <asm/hvm/io.h>
     1.6  #include <asm/hvm/support.h>
     1.7 -
     1.8  #include <xen/lib.h>
     1.9  #include <xen/sched.h>
    1.10  #include <asm/current.h>
    1.11  #include <public/hvm/ioreq.h>
    1.12  #include <public/hvm/params.h>
    1.13  
    1.14 +#define VLAPIC_VERSION                  0x00050014
    1.15 +#define VLAPIC_LVT_NUM                  6
    1.16 +
    1.17  /* XXX remove this definition after GFW enabled */
    1.18  #define VLAPIC_NO_BIOS
    1.19  
    1.20 @@ -43,6 +45,13 @@ extern u32 get_apic_bus_cycle(void);
    1.21  
    1.22  #define APIC_BUS_CYCLE_NS (((s_time_t)get_apic_bus_cycle()) / 1000)
    1.23  
    1.24 +#define LVT_MASK \
    1.25 +    APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
    1.26 +
    1.27 +#define LINT_MASK   \
    1.28 +    LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
    1.29 +    APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER
    1.30 +
    1.31  static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
    1.32  {
    1.33       /* LVTT */
    1.34 @@ -57,9 +66,70 @@ static unsigned int vlapic_lvt_mask[VLAP
    1.35       LVT_MASK
    1.36  };
    1.37  
    1.38 -int hvm_apic_support(struct domain *d)
    1.39 +/* Following could belong in apicdef.h */
    1.40 +#define APIC_SHORT_MASK                  0xc0000
    1.41 +#define APIC_DEST_NOSHORT                0x0
    1.42 +#define APIC_DEST_MASK                   0x800
    1.43 +
    1.44 +#define vlapic_lvt_enabled(vlapic, lvt_type)    \
    1.45 +    (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
    1.46 +
    1.47 +#define vlapic_lvt_vector(vlapic, lvt_type)     \
    1.48 +    (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
    1.49 +
    1.50 +#define vlapic_lvt_dm(vlapic, lvt_type)           \
    1.51 +    (vlapic_get_reg(vlapic, lvt_type) & APIC_MODE_MASK)
    1.52 +
    1.53 +#define vlapic_lvtt_period(vlapic)     \
    1.54 +    (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC)
    1.55 +
    1.56 +/*
    1.57 + * Generic APIC bitmap vector update & search routines.
    1.58 + */
    1.59 +
    1.60 +#define VEC_POS(v) ((v)%32)
    1.61 +#define REG_POS(v) (((v)/32)* 0x10)
    1.62 +#define vlapic_test_and_set_vector(vec, bitmap)                 \
    1.63 +    test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    1.64 +#define vlapic_test_and_clear_vector(vec, bitmap)               \
    1.65 +    test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    1.66 +#define vlapic_set_vector(vec, bitmap)                          \
    1.67 +    set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    1.68 +#define vlapic_clear_vector(vec, bitmap)                        \
    1.69 +    clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    1.70 +
    1.71 +static int vlapic_find_highest_vector(u32 *bitmap)
    1.72  {
    1.73 -    return d->arch.hvm_domain.params[HVM_PARAM_APIC_ENABLED];
    1.74 +    int word_offset = MAX_VECTOR / 32;
    1.75 +
    1.76 +    /* Work backwards through the bitmap (first 32-bit word in every four). */
    1.77 +    while ( (word_offset != 0) && (bitmap[(--word_offset)*4] == 0) )
    1.78 +        continue;
    1.79 +
    1.80 +    return (fls(bitmap[word_offset*4]) - 1) + (word_offset * 32);
    1.81 +}
    1.82 +
    1.83 +
    1.84 +/*
    1.85 + * IRR-specific bitmap update & search routines.
    1.86 + */
    1.87 +
    1.88 +static int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic)
    1.89 +{
    1.90 +    vlapic->flush_tpr_threshold = 1;
    1.91 +    return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
    1.92 +}
    1.93 +
    1.94 +static void vlapic_set_irr(int vector, struct vlapic *vlapic)
    1.95 +{
    1.96 +    vlapic->flush_tpr_threshold = 1;
    1.97 +    vlapic_set_vector(vector, vlapic->regs + APIC_IRR);
    1.98 +}
    1.99 +
   1.100 +static void vlapic_clear_irr(int vector, struct vlapic *vlapic)
   1.101 +{
   1.102 +    vlapic->flush_tpr_threshold = 1;
   1.103 +    vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
   1.104  }
   1.105  
   1.106  int vlapic_find_highest_irr(struct vlapic *vlapic)
   1.107 @@ -72,6 +142,24 @@ int vlapic_find_highest_irr(struct vlapi
   1.108      return result;
   1.109  }
   1.110  
   1.111 +
   1.112 +int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig)
   1.113 +{
   1.114 +    int ret;
   1.115 +
   1.116 +    ret = vlapic_test_and_set_irr(vec, vlapic);
   1.117 +    if ( trig )
   1.118 +        vlapic_set_vector(vec, vlapic->regs + APIC_TMR);
   1.119 +
   1.120 +    /* We may need to wake up target vcpu, besides set pending bit here */
   1.121 +    return ret;
   1.122 +}
   1.123 +
   1.124 +int hvm_apic_support(struct domain *d)
   1.125 +{
   1.126 +    return d->arch.hvm_domain.params[HVM_PARAM_APIC_ENABLED];
   1.127 +}
   1.128 +
   1.129  s_time_t get_apictime_scheduled(struct vcpu *v)
   1.130  {
   1.131      struct vlapic *vlapic = VLAPIC(v);
   1.132 @@ -139,11 +227,13 @@ static int vlapic_match_dest(struct vcpu
   1.133            (delivery_mode != APIC_DM_NMI)) )
   1.134      {
   1.135          HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "uninitialized target vcpu %p, "
   1.136 -                    "delivery_mode 0x%x, dest 0x%x.\n", v, delivery_mode, dest);
   1.137 +                    "delivery_mode 0x%x, dest 0x%x.\n",
   1.138 +                    v, delivery_mode, dest);
   1.139          return result;
   1.140      }
   1.141  
   1.142 -    switch ( short_hand ) {
   1.143 +    switch ( short_hand )
   1.144 +    {
   1.145      case APIC_DEST_NOSHORT:             /* no shorthand */
   1.146          if ( !dest_mode )   /* Physical */
   1.147          {
   1.148 @@ -159,7 +249,7 @@ static int vlapic_match_dest(struct vcpu
   1.149              ldr = vlapic_get_reg(target, APIC_LDR);
   1.150              
   1.151              /* Flat mode */
   1.152 -            if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT)
   1.153 +            if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT )
   1.154              {
   1.155                  result = GET_APIC_LOGICAL_ID(ldr) & dest;
   1.156              }
   1.157 @@ -173,8 +263,8 @@ static int vlapic_match_dest(struct vcpu
   1.158                             "delivery mode\n");
   1.159                      domain_crash_synchronous();
   1.160                  }
   1.161 -                result = (GET_APIC_LOGICAL_ID(ldr) == (dest & 0xf)) ?
   1.162 -                         (GET_APIC_LOGICAL_ID(ldr) >> 4) & (dest >> 4) : 0;
   1.163 +                result = ((GET_APIC_LOGICAL_ID(ldr) == (dest & 0xf)) ?
   1.164 +                          (GET_APIC_LOGICAL_ID(ldr) >> 4) & (dest >> 4) : 0);
   1.165              }
   1.166          }
   1.167          break;
   1.168 @@ -220,14 +310,14 @@ static int vlapic_accept_irq(struct vcpu
   1.169          if ( vlapic_test_and_set_irr(vector, vlapic) && trig_mode )
   1.170          {
   1.171              HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
   1.172 -                  "level trig mode repeatedly for vector %d\n", vector);
   1.173 +                        "level trig mode repeatedly for vector %d\n", vector);
   1.174              break;
   1.175          }
   1.176  
   1.177          if ( trig_mode )
   1.178          {
   1.179              HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
   1.180 -              "level trig mode for vector %d\n", vector);
   1.181 +                        "level trig mode for vector %d\n", vector);
   1.182              vlapic_set_vector(vector, vlapic->regs + APIC_TMR);
   1.183          }
   1.184  
   1.185 @@ -247,29 +337,27 @@ static int vlapic_accept_irq(struct vcpu
   1.186          break;
   1.187  
   1.188      case APIC_DM_INIT:
   1.189 -        if ( trig_mode && !(level & APIC_INT_ASSERT) )     //Deassert
   1.190 -            printk("This hvm_vlapic is for P4, no work for De-assert init\n");
   1.191 -        else
   1.192 +        /* No work on INIT de-assert for P4-type APIC. */
   1.193 +        if ( trig_mode && !(level & APIC_INT_ASSERT) )
   1.194 +            break;
   1.195 +        /* FIXME How to check the situation after vcpu reset? */
   1.196 +        if ( test_and_clear_bit(_VCPUF_initialised, &v->vcpu_flags) )
   1.197          {
   1.198 -            /* FIXME How to check the situation after vcpu reset? */
   1.199 -            if ( test_and_clear_bit(_VCPUF_initialised, &v->vcpu_flags) )
   1.200 -            {
   1.201 -                printk("Reset hvm vcpu not supported yet\n");
   1.202 -                domain_crash_synchronous();
   1.203 -            }
   1.204 -            v->arch.hvm_vcpu.init_sipi_sipi_state =
   1.205 -                HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
   1.206 -            result = 1;
   1.207 +            gdprintk(XENLOG_ERR, "Reset hvm vcpu not supported yet\n");
   1.208 +            domain_crash_synchronous();
   1.209          }
   1.210 +        v->arch.hvm_vcpu.init_sipi_sipi_state =
   1.211 +            HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
   1.212 +        result = 1;
   1.213          break;
   1.214  
   1.215      case APIC_DM_STARTUP:
   1.216          if ( v->arch.hvm_vcpu.init_sipi_sipi_state ==
   1.217 -                HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM )
   1.218 +             HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM )
   1.219              break;
   1.220  
   1.221          v->arch.hvm_vcpu.init_sipi_sipi_state =
   1.222 -                HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM;
   1.223 +            HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM;
   1.224  
   1.225          if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
   1.226          {
   1.227 @@ -302,7 +390,7 @@ struct vlapic *apic_round_robin(struct d
   1.228      int next, old;
   1.229      struct vlapic* target = NULL;
   1.230  
   1.231 -    if ( dest_mode == 0 )   //Physical mode
   1.232 +    if ( dest_mode == 0 ) /* Physical mode */
   1.233      {
   1.234          printk("<apic_round_robin> lowest priority for physical mode.\n");
   1.235          return NULL;
   1.236 @@ -362,21 +450,6 @@ void vlapic_EOI_set(struct vlapic *vlapi
   1.237          ioapic_update_EOI(vlapic->domain, vector);
   1.238  }
   1.239  
   1.240 -static int vlapic_check_vector(struct vlapic *vlapic,
   1.241 -                        uint32_t dm, uint32_t vector)
   1.242 -{
   1.243 -    if ( (dm == APIC_DM_FIXED) && (vector < 16) )
   1.244 -    {
   1.245 -        vlapic->err_status |= 0x40;
   1.246 -        vlapic_accept_irq(vlapic->vcpu, APIC_DM_FIXED,
   1.247 -                          vlapic_lvt_vector(vlapic, APIC_LVTERR), 0, 0);
   1.248 -        printk("<vlapic_check_vector>: check failed "
   1.249 -               " dm %x vector %x\n", dm, vector);
   1.250 -        return 0;
   1.251 -    }
   1.252 -    return 1;
   1.253 -}
   1.254 -
   1.255  static void vlapic_ipi(struct vlapic *vlapic)
   1.256  {
   1.257      uint32_t icr_low = vlapic_get_reg(vlapic, APIC_ICR);
   1.258 @@ -450,7 +523,7 @@ static uint32_t vlapic_get_tmcct(struct 
   1.259          if ( unlikely(!vlapic_lvtt_period(vlapic)) )
   1.260          {
   1.261              tmcct =  0;
   1.262 -            // FIXME: should we add interrupt here?
   1.263 +            /* FIXME: should we add interrupt here? */
   1.264          }
   1.265          else
   1.266          {
   1.267 @@ -490,15 +563,10 @@ static void vlapic_read_aligned(struct v
   1.268          printk("access local APIC ARBPRI register which is for P6\n");
   1.269          break;
   1.270  
   1.271 -    case APIC_TMCCT:        //Timer CCR
   1.272 +    case APIC_TMCCT: /* Timer CCR */
   1.273          *result = vlapic_get_tmcct(vlapic);
   1.274          break;
   1.275  
   1.276 -    case APIC_ESR:
   1.277 -        vlapic->err_write_count = 0;
   1.278 -        *result = vlapic_get_reg(vlapic, offset);
   1.279 -        break;
   1.280 -
   1.281      default:
   1.282          *result = vlapic_get_reg(vlapic, offset);
   1.283          break;
   1.284 @@ -565,31 +633,31 @@ static void vlapic_write(struct vcpu *v,
   1.285                      offset, len, val);
   1.286  
   1.287      /*
   1.288 -     * According to IA 32 Manual, all resgiters should be accessed with
   1.289 -     * 32 bits alignment.
   1.290 +     * According to the IA32 Manual, all accesses should be 32 bits.
   1.291 +     * Some OSes do 8- or 16-byte accesses, however.
   1.292       */
   1.293      if ( len != 4 )
   1.294      {
   1.295          unsigned int tmp;
   1.296          unsigned char alignment;
   1.297  
   1.298 -        /* Some kernels do will access with byte/word alignment */
   1.299 -        printk("Notice: Local APIC write with len = %lx\n",len);
   1.300 +        gdprintk(XENLOG_INFO, "Notice: Local APIC write with len = %lx\n",len);
   1.301 +
   1.302          alignment = offset & 0x3;
   1.303          tmp = vlapic_read(v, offset & ~0x3, 4);
   1.304 -        switch ( len ) {
   1.305 +
   1.306 +        switch ( len )
   1.307 +        {
   1.308          case 1:
   1.309 -            /* XXX the saddr is a tmp variable from caller, so should be ok
   1.310 -               But we should still change the following ref to val to
   1.311 -               local variable later */
   1.312              val = (tmp & ~(0xff << (8*alignment))) |
   1.313                    ((val & 0xff) << (8*alignment));
   1.314              break;
   1.315  
   1.316          case 2:
   1.317 -            if ( alignment != 0x0 && alignment != 0x2 )
   1.318 +            if ( alignment & 1 )
   1.319              {
   1.320 -                printk("alignment error for vlapic with len == 2\n");
   1.321 +                gdprintk(XENLOG_ERR, "Uneven alignment error for "
   1.322 +                         "2-byte vlapic access\n");
   1.323                  domain_crash_synchronous();
   1.324              }
   1.325  
   1.326 @@ -597,14 +665,9 @@ static void vlapic_write(struct vcpu *v,
   1.327                    ((val & 0xffff) << (8*alignment));
   1.328              break;
   1.329  
   1.330 -        case 3:
   1.331 -            /* will it happen? */
   1.332 -            printk("vlapic_write with len = 3 !!!\n");
   1.333 -            domain_crash_synchronous();
   1.334 -            break;
   1.335 -
   1.336          default:
   1.337 -            printk("Local APIC write with len = %lx, should be 4 instead\n", len);
   1.338 +            gdprintk(XENLOG_ERR, "Local APIC write with len = %lx, "
   1.339 +                     "should be 4 instead\n", len);
   1.340              domain_crash_synchronous();
   1.341              break;
   1.342          }
   1.343 @@ -612,7 +675,8 @@ static void vlapic_write(struct vcpu *v,
   1.344  
   1.345      offset &= 0xff0;
   1.346  
   1.347 -    switch ( offset ) {
   1.348 +    switch ( offset )
   1.349 +    {
   1.350      case APIC_ID:   /* Local APIC ID */
   1.351          vlapic_set_reg(vlapic, APIC_ID, val);
   1.352          break;
   1.353 @@ -638,7 +702,7 @@ static void vlapic_write(struct vcpu *v,
   1.354      case APIC_SPIV:
   1.355          vlapic_set_reg(vlapic, APIC_SPIV, val & 0x3ff);
   1.356  
   1.357 -        if ( !( val & APIC_SPIV_APIC_ENABLED) )
   1.358 +        if ( !(val & APIC_SPIV_APIC_ENABLED) )
   1.359          {
   1.360              int i;
   1.361              uint32_t lvt_val;
   1.362 @@ -666,9 +730,7 @@ static void vlapic_write(struct vcpu *v,
   1.363          break;
   1.364  
   1.365      case APIC_ESR:
   1.366 -        vlapic->err_write_count = !vlapic->err_write_count;
   1.367 -        if ( !vlapic->err_write_count )
   1.368 -            vlapic->err_status = 0;
   1.369 +        /* Nothing to do. */
   1.370          break;
   1.371  
   1.372      case APIC_ICR:
   1.373 @@ -681,78 +743,72 @@ static void vlapic_write(struct vcpu *v,
   1.374          vlapic_set_reg(vlapic, APIC_ICR2, val & 0xff000000);
   1.375          break;
   1.376  
   1.377 -    case APIC_LVTT:         // LVT Timer Reg
   1.378 -    case APIC_LVTTHMR:      // LVT Thermal Monitor
   1.379 -    case APIC_LVTPC:        // LVT Performance Counter
   1.380 -    case APIC_LVT0:         // LVT LINT0 Reg
   1.381 -    case APIC_LVT1:         // LVT Lint1 Reg
   1.382 -    case APIC_LVTERR:       // LVT Error Reg
   1.383 -        {
   1.384 -            if ( vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK )
   1.385 -                val |= APIC_LVT_MASKED;
   1.386 -
   1.387 -            val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
   1.388 -
   1.389 -            vlapic_set_reg(vlapic, offset, val);
   1.390 +    case APIC_LVTT:         /* LVT Timer Reg */
   1.391 +    case APIC_LVTTHMR:      /* LVT Thermal Monitor */
   1.392 +    case APIC_LVTPC:        /* LVT Performance Counter */
   1.393 +    case APIC_LVT0:         /* LVT LINT0 Reg */
   1.394 +    case APIC_LVT1:         /* LVT Lint1 Reg */
   1.395 +    case APIC_LVTERR:       /* LVT Error Reg */
   1.396 +    {
   1.397 +        if ( vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK )
   1.398 +            val |= APIC_LVT_MASKED;
   1.399  
   1.400 -            /* On hardware, when write vector less than 0x20 will error */
   1.401 -            if ( !(val & APIC_LVT_MASKED) )
   1.402 -                vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic, offset),
   1.403 -                                    vlapic_lvt_vector(vlapic, offset));
   1.404 +        val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
   1.405  
   1.406 -            if ( !vlapic->vcpu_id && (offset == APIC_LVT0) )
   1.407 -            {
   1.408 -                if ( (val & APIC_MODE_MASK) == APIC_DM_EXTINT )
   1.409 -                    if ( val & APIC_LVT_MASKED)
   1.410 -                        clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
   1.411 -                    else
   1.412 -                        set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
   1.413 +        vlapic_set_reg(vlapic, offset, val);
   1.414 +
   1.415 +        if ( !vlapic->vcpu->vcpu_id && (offset == APIC_LVT0) )
   1.416 +        {
   1.417 +            if ( (val & APIC_MODE_MASK) == APIC_DM_EXTINT )
   1.418 +                if ( val & APIC_LVT_MASKED)
   1.419 +                    clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
   1.420                  else
   1.421 -                    clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
   1.422 -            }
   1.423 -
   1.424 +                    set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
   1.425 +            else
   1.426 +                clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
   1.427          }
   1.428 -        break;
   1.429 +    }
   1.430 +    break;
   1.431  
   1.432      case APIC_TMICT:
   1.433 -        {
   1.434 -            s_time_t now = NOW(), offset;
   1.435 -
   1.436 -            stop_timer(&vlapic->vlapic_timer);
   1.437 -
   1.438 -            vlapic_set_reg(vlapic, APIC_TMICT, val);
   1.439 -            vlapic_set_reg(vlapic, APIC_TMCCT, val);
   1.440 -            vlapic->timer_last_update = now;
   1.441 +    {
   1.442 +        s_time_t now = NOW(), offset;
   1.443  
   1.444 -            offset = APIC_BUS_CYCLE_NS *
   1.445 -                     vlapic->timer_divide_count * val;
   1.446 -
   1.447 -            set_timer(&vlapic->vlapic_timer, now + offset);
   1.448 +        stop_timer(&vlapic->vlapic_timer);
   1.449  
   1.450 -            HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
   1.451 -                        "bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
   1.452 -                        "timer initial count 0x%x, offset 0x%016"PRIx64", "
   1.453 -                        "expire @ 0x%016"PRIx64".",
   1.454 -                        APIC_BUS_CYCLE_NS, now,
   1.455 -                        vlapic_get_reg(vlapic, APIC_TMICT),
   1.456 -                        offset, now + offset);
   1.457 -        }
   1.458 -        break;
   1.459 +        vlapic_set_reg(vlapic, APIC_TMICT, val);
   1.460 +        vlapic_set_reg(vlapic, APIC_TMCCT, val);
   1.461 +        vlapic->timer_last_update = now;
   1.462 +
   1.463 +        offset = APIC_BUS_CYCLE_NS *
   1.464 +            vlapic->timer_divide_count * val;
   1.465 +
   1.466 +        set_timer(&vlapic->vlapic_timer, now + offset);
   1.467 +
   1.468 +        HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
   1.469 +                    "bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
   1.470 +                    "timer initial count 0x%x, offset 0x%016"PRIx64", "
   1.471 +                    "expire @ 0x%016"PRIx64".",
   1.472 +                    APIC_BUS_CYCLE_NS, now,
   1.473 +                    vlapic_get_reg(vlapic, APIC_TMICT),
   1.474 +                    offset, now + offset);
   1.475 +    }
   1.476 +    break;
   1.477  
   1.478      case APIC_TDCR:
   1.479 -        {
   1.480 -            unsigned int tmp1, tmp2;
   1.481 +    {
   1.482 +        unsigned int tmp1, tmp2;
   1.483  
   1.484 -            tmp1 = val & 0xf;
   1.485 -            tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
   1.486 -            vlapic->timer_divide_count = 0x1 << (tmp2 & 0x7);
   1.487 +        tmp1 = val & 0xf;
   1.488 +        tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
   1.489 +        vlapic->timer_divide_count = 0x1 << (tmp2 & 0x7);
   1.490  
   1.491 -            vlapic_set_reg(vlapic, APIC_TDCR, val);
   1.492 +        vlapic_set_reg(vlapic, APIC_TDCR, val);
   1.493  
   1.494 -            HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divide count is 0x%x",
   1.495 -                        vlapic->timer_divide_count);
   1.496 -        }
   1.497 -        break;
   1.498 +        HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, "timer divide count is 0x%x",
   1.499 +                    vlapic->timer_divide_count);
   1.500 +    }
   1.501 +    break;
   1.502  
   1.503      default:
   1.504          printk("Local APIC Write to read-only register\n");
   1.505 @@ -764,12 +820,9 @@ static int vlapic_range(struct vcpu *v, 
   1.506  {
   1.507      struct vlapic *vlapic = VLAPIC(v);
   1.508  
   1.509 -    if ( vlapic_global_enabled(vlapic) &&
   1.510 -         (addr >= vlapic->base_address) &&
   1.511 -         (addr < vlapic->base_address + VLOCAL_APIC_MEM_LENGTH) )
   1.512 -        return 1;
   1.513 -
   1.514 -    return 0;
   1.515 +    return (vlapic_global_enabled(vlapic) &&
   1.516 +            (addr >= vlapic->base_address) &&
   1.517 +            (addr < vlapic->base_address + PAGE_SIZE));
   1.518  }
   1.519  
   1.520  struct hvm_mmio_handler vlapic_mmio_handler = {
   1.521 @@ -780,18 +833,15 @@ struct hvm_mmio_handler vlapic_mmio_hand
   1.522  
   1.523  void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
   1.524  {
   1.525 -    /* When apic disabled */
   1.526      if ( vlapic == NULL )
   1.527          return;
   1.528  
   1.529 -    if ( vlapic->vcpu_id )
   1.530 +    if ( vlapic->vcpu->vcpu_id )
   1.531          value &= ~MSR_IA32_APICBASE_BSP;
   1.532  
   1.533      vlapic->apic_base_msr = value;
   1.534 -    vlapic->base_address = vlapic->apic_base_msr &
   1.535 -                           MSR_IA32_APICBASE_BASE;
   1.536 +    vlapic->base_address  = vlapic->apic_base_msr & MSR_IA32_APICBASE_BASE;
   1.537  
   1.538 -    /* with FSB delivery interrupt, we can restart APIC functionality */
   1.539      if ( !(value & MSR_IA32_APICBASE_ENABLE) )
   1.540          set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status );
   1.541      else
   1.542 @@ -820,7 +870,7 @@ void vlapic_timer_fn(void *data)
   1.543      vlapic->timer_last_update = now;
   1.544  
   1.545      if ( vlapic_test_and_set_irr(timer_vector, vlapic) )
   1.546 -        vlapic->intr_pending_count[timer_vector]++;
   1.547 +        vlapic->timer_pending_count++;
   1.548  
   1.549      if ( vlapic_lvtt_period(vlapic) )
   1.550      {
   1.551 @@ -837,13 +887,6 @@ void vlapic_timer_fn(void *data)
   1.552      else
   1.553          vlapic_set_reg(vlapic, APIC_TMCCT, 0);
   1.554  
   1.555 -#if 0
   1.556 -    if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
   1.557 -    {
   1.558 -        /* TODO: add guest time handling here */
   1.559 -    }
   1.560 -#endif
   1.561 -
   1.562      HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
   1.563                  "now 0x%016"PRIx64", expire @ 0x%016"PRIx64", "
   1.564                  "timer initial count 0x%x, timer current count 0x%x.",
   1.565 @@ -852,22 +895,6 @@ void vlapic_timer_fn(void *data)
   1.566                  vlapic_get_reg(vlapic, APIC_TMCCT));
   1.567  }
   1.568  
   1.569 -#if 0
   1.570 -static int
   1.571 -vlapic_check_direct_intr(struct vcpu *v, int * mode)
   1.572 -{
   1.573 -    struct vlapic *vlapic = VLAPIC(v);
   1.574 -    int type;
   1.575 -
   1.576 -    type = fls(vlapic->direct_intr.deliver_mode) - 1;
   1.577 -    if ( type == -1 )
   1.578 -        return -1;
   1.579 -
   1.580 -    *mode = type;
   1.581 -    return 0;
   1.582 -}
   1.583 -#endif
   1.584 -
   1.585  int vlapic_accept_pic_intr(struct vcpu *v)
   1.586  {
   1.587      struct vlapic *vlapic = VLAPIC(v);
   1.588 @@ -878,60 +905,33 @@ int vlapic_accept_pic_intr(struct vcpu *
   1.589  int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
   1.590  {
   1.591      struct vlapic *vlapic = VLAPIC(v);
   1.592 -
   1.593 -    if ( vlapic && vlapic_enabled(vlapic) )
   1.594 -    {
   1.595 -        int highest_irr = vlapic_find_highest_irr(vlapic);
   1.596 -
   1.597 -        if ( highest_irr != -1 &&
   1.598 -             ( (highest_irr & 0xF0) > vlapic_get_reg(vlapic, APIC_PROCPRI) ) )
   1.599 -        {
   1.600 -            if ( highest_irr < 0x10 )
   1.601 -            {
   1.602 -                uint32_t err_vector;
   1.603 -
   1.604 -                vlapic->err_status |= 0x20;
   1.605 -                err_vector = vlapic_lvt_vector(vlapic, APIC_LVTERR);
   1.606 -
   1.607 -                HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
   1.608 -                            "Sending an illegal vector 0x%x.", highest_irr);
   1.609 +    int highest_irr;
   1.610  
   1.611 -                vlapic_set_irr(err_vector, vlapic);
   1.612 -                highest_irr = err_vector;
   1.613 -            }
   1.614 -
   1.615 -            *mode = APIC_DM_FIXED;
   1.616 -            return highest_irr;
   1.617 -        }
   1.618 -    }
   1.619 -    return -1;
   1.620 -}
   1.621 +    if ( !vlapic || !vlapic_enabled(vlapic) )
   1.622 +        return -1;
   1.623  
   1.624 -int cpu_has_apic_interrupt(struct vcpu* v)
   1.625 -{
   1.626 -    struct vlapic *vlapic = VLAPIC(v);
   1.627 +    highest_irr = vlapic_find_highest_irr(vlapic);
   1.628 +    if ( (highest_irr == -1) ||
   1.629 +         ((highest_irr & 0xF0) <= vlapic_get_reg(vlapic, APIC_PROCPRI)) )
   1.630 +        return -1;
   1.631  
   1.632 -    if (vlapic && vlapic_enabled(vlapic)) {
   1.633 -        int highest_irr = vlapic_find_highest_irr(vlapic);
   1.634 -
   1.635 -        if ( highest_irr != -1 &&
   1.636 -             ( (highest_irr & 0xF0) > vlapic_get_reg(vlapic, APIC_PROCPRI) ) ) {
   1.637 -            return 1;
   1.638 -        }
   1.639 -    }
   1.640 -    return 0;
   1.641 +    *mode = APIC_DM_FIXED;
   1.642 +    return highest_irr;
   1.643  }
   1.644  
   1.645  /* check to see if there is pending interrupt  */
   1.646  int cpu_has_pending_irq(struct vcpu *v)
   1.647  {
   1.648      struct hvm_domain *plat = &v->domain->arch.hvm_domain;
   1.649 +    int dummy;
   1.650  
   1.651      /* APIC */
   1.652 -    if ( cpu_has_apic_interrupt(v) ) return 1;
   1.653 -    
   1.654 +    if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
   1.655 +        return 1;
   1.656 +
   1.657      /* PIC */
   1.658 -    if ( !vlapic_accept_pic_intr(v) ) return 0;
   1.659 +    if ( !vlapic_accept_pic_intr(v) )
   1.660 +        return 0;
   1.661  
   1.662      return plat->interrupt_request;
   1.663  }
   1.664 @@ -943,20 +943,18 @@ void vlapic_post_injection(struct vcpu *
   1.665      if ( unlikely(vlapic == NULL) )
   1.666          return;
   1.667  
   1.668 -    switch ( deliver_mode ) {
   1.669 +    switch ( deliver_mode )
   1.670 +    {
   1.671      case APIC_DM_FIXED:
   1.672      case APIC_DM_LOWEST:
   1.673          vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
   1.674          vlapic_clear_irr(vector, vlapic);
   1.675          vlapic_update_ppr(vlapic);
   1.676 -
   1.677 -        if ( vector == vlapic_lvt_vector(vlapic, APIC_LVTT) )
   1.678 +        if ( (vector == vlapic_lvt_vector(vlapic, APIC_LVTT)) &&
   1.679 +             (vlapic->timer_pending_count != 0) )
   1.680          {
   1.681 -            if ( vlapic->intr_pending_count[vector] > 0 )
   1.682 -            {
   1.683 -                vlapic->intr_pending_count[vector]--;
   1.684 -                vlapic_set_irr(vector, vlapic);
   1.685 -            }
   1.686 +            vlapic->timer_pending_count--;
   1.687 +            vlapic_set_irr(vector, vlapic);
   1.688          }
   1.689          break;
   1.690  
   1.691 @@ -969,7 +967,6 @@ void vlapic_post_injection(struct vcpu *
   1.692      case APIC_DM_NMI:
   1.693      case APIC_DM_INIT:
   1.694      case APIC_DM_STARTUP:
   1.695 -        vlapic->direct_intr.deliver_mode &= (1 << (deliver_mode >> 8));
   1.696          break;
   1.697  
   1.698      default:
   1.699 @@ -980,19 +977,11 @@ void vlapic_post_injection(struct vcpu *
   1.700  
   1.701  static int vlapic_reset(struct vlapic *vlapic)
   1.702  {
   1.703 -    struct vcpu *v;
   1.704 +    struct vcpu *v = vlapic->vcpu;
   1.705      int i;
   1.706  
   1.707 -    ASSERT( vlapic != NULL );
   1.708 -
   1.709 -    v = vlapic->vcpu;
   1.710 -
   1.711 -    ASSERT( v != NULL );
   1.712 -
   1.713      vlapic->domain = v->domain;
   1.714  
   1.715 -    vlapic->vcpu_id = v->vcpu_id;
   1.716 -
   1.717      vlapic_set_reg(vlapic, APIC_ID, v->vcpu_id << 24);
   1.718  
   1.719      vlapic_set_reg(vlapic, APIC_LVR, VLAPIC_VERSION);
   1.720 @@ -1045,8 +1034,6 @@ int vlapic_init(struct vcpu *v)
   1.721  {
   1.722      struct vlapic *vlapic = NULL;
   1.723  
   1.724 -    ASSERT( v != NULL );
   1.725 -
   1.726      HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id);
   1.727  
   1.728      vlapic = xmalloc_bytes(sizeof(struct vlapic));
   1.729 @@ -1067,11 +1054,9 @@ int vlapic_init(struct vcpu *v)
   1.730      }
   1.731  
   1.732      vlapic->regs = map_domain_page_global(page_to_mfn(vlapic->regs_page));
   1.733 -
   1.734      memset(vlapic->regs, 0, PAGE_SIZE);
   1.735  
   1.736      VLAPIC(v) = vlapic;
   1.737 -
   1.738      vlapic->vcpu = v;
   1.739  
   1.740      vlapic_reset(vlapic);
     2.1 --- a/xen/include/asm-x86/hvm/vlapic.h	Mon Oct 30 10:42:27 2006 +0000
     2.2 +++ b/xen/include/asm-x86/hvm/vlapic.h	Mon Oct 30 13:53:09 2006 +0000
     2.3 @@ -25,56 +25,11 @@
     2.4  
     2.5  #define MAX_VECTOR      256
     2.6  
     2.7 -#define VEC_POS(v) ((v)%32)
     2.8 -#define REG_POS(v) (((v)/32)* 0x10)
     2.9 -#define vlapic_test_and_set_vector(vec, bitmap)                 \
    2.10 -    test_and_set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    2.11 -#define vlapic_test_and_clear_vector(vec, bitmap)               \
    2.12 -    test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    2.13 -#define vlapic_set_vector(vec, bitmap)                          \
    2.14 -    set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    2.15 -#define vlapic_clear_vector(vec, bitmap)                        \
    2.16 -    clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec))
    2.17 -
    2.18 -static inline int vlapic_find_highest_vector(u32 *bitmap)
    2.19 -{
    2.20 -    int word_offset = MAX_VECTOR / 32;
    2.21 -
    2.22 -    /* Work backwards through the bitmap (first 32-bit word in every four). */
    2.23 -    while ( (word_offset != 0) && (bitmap[(--word_offset)*4] == 0) )
    2.24 -        continue;
    2.25 -
    2.26 -    return (fls(bitmap[word_offset*4]) - 1) + (word_offset * 32);
    2.27 -}
    2.28 -
    2.29  #define VLAPIC(v)                       (v->arch.hvm_vcpu.vlapic)
    2.30  
    2.31 -#define VLAPIC_VERSION                  0x00050014
    2.32 -
    2.33 -#define VLOCAL_APIC_MEM_LENGTH          (1 << 12)
    2.34 -
    2.35 -#define VLAPIC_LVT_NUM                  6
    2.36 -
    2.37  #define VLAPIC_ID(vlapic)   \
    2.38      (GET_APIC_ID(vlapic_get_reg(vlapic, APIC_ID)))
    2.39  
    2.40 -/* followed define is not in apicdef.h */
    2.41 -#define APIC_SHORT_MASK                  0xc0000
    2.42 -#define APIC_DEST_NOSHORT                0x0
    2.43 -#define APIC_DEST_MASK                  0x800
    2.44 -
    2.45 -#define vlapic_lvt_enabled(vlapic, lvt_type)    \
    2.46 -    (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
    2.47 -
    2.48 -#define vlapic_lvt_vector(vlapic, lvt_type)     \
    2.49 -    (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
    2.50 -
    2.51 -#define vlapic_lvt_dm(vlapic, lvt_type)           \
    2.52 -    (vlapic_get_reg(vlapic, lvt_type) & APIC_MODE_MASK)
    2.53 -
    2.54 -#define vlapic_lvtt_period(vlapic)     \
    2.55 -    (vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC)
    2.56 -
    2.57  #define _VLAPIC_GLOB_DISABLE            0x0
    2.58  #define VLAPIC_GLOB_DISABLE_MASK        0x1
    2.59  #define VLAPIC_SOFTWARE_DISABLE_MASK    0x2
    2.60 @@ -87,96 +42,50 @@ static inline int vlapic_find_highest_ve
    2.61  #define vlapic_global_enabled(vlapic)       \
    2.62      (!(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status)))
    2.63  
    2.64 -#define LVT_MASK \
    2.65 -    APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
    2.66 -
    2.67 -#define LINT_MASK   \
    2.68 -    LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\
    2.69 -    APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER
    2.70 -
    2.71 -typedef struct direct_intr_info {
    2.72 -    int deliver_mode;
    2.73 -    int source[6];
    2.74 -} direct_intr_info_t;
    2.75 -
    2.76  struct vlapic {
    2.77      uint32_t           status;
    2.78 -    uint32_t           vcpu_id;
    2.79      uint64_t           apic_base_msr;
    2.80      unsigned long      base_address;
    2.81      uint32_t           timer_divide_count;
    2.82      struct timer       vlapic_timer;
    2.83 -    int                intr_pending_count[MAX_VECTOR];
    2.84 +    int                timer_pending_count;
    2.85      int                flush_tpr_threshold;
    2.86      s_time_t           timer_last_update;
    2.87 -    direct_intr_info_t direct_intr;
    2.88 -    uint32_t           err_status;
    2.89 -    uint32_t           err_write_count;
    2.90      struct vcpu        *vcpu;
    2.91      struct domain      *domain;
    2.92      struct page_info   *regs_page;
    2.93      void               *regs;
    2.94  };
    2.95  
    2.96 -static inline int vlapic_test_and_set_irr(int vector, struct vlapic *vlapic)
    2.97 -{
    2.98 -    vlapic->flush_tpr_threshold = 1;
    2.99 -    return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
   2.100 -}
   2.101 -
   2.102 -static inline void vlapic_set_irr(int vector, struct vlapic *vlapic)
   2.103 +static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
   2.104  {
   2.105 -    vlapic->flush_tpr_threshold = 1;
   2.106 -    vlapic_set_vector(vector, vlapic->regs + APIC_IRR);
   2.107 -}
   2.108 -
   2.109 -static inline void vlapic_clear_irr(int vector, struct vlapic *vlapic)
   2.110 -{
   2.111 -    vlapic->flush_tpr_threshold = 1;
   2.112 -    vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
   2.113 +    return *((uint32_t *)(vlapic->regs + reg));
   2.114  }
   2.115  
   2.116 -static inline int vlapic_set_irq(struct vlapic *vlapic,
   2.117 -                                 uint8_t vec, uint8_t trig)
   2.118 -{
   2.119 -    int ret;
   2.120 -
   2.121 -    ret = vlapic_test_and_set_irr(vec, vlapic);
   2.122 -    if ( trig )
   2.123 -        vlapic_set_vector(vec, vlapic->regs + APIC_TMR);
   2.124 -
   2.125 -    /* We may need to wake up target vcpu, besides set pending bit here */
   2.126 -    return ret;
   2.127 -}
   2.128 -
   2.129 -static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
   2.130 -{
   2.131 -    return  *( (uint32_t *)(vlapic->regs + reg));
   2.132 -}
   2.133 -
   2.134 -static inline void vlapic_set_reg(struct vlapic *vlapic,
   2.135 -  uint32_t reg, uint32_t val)
   2.136 +static inline void vlapic_set_reg(
   2.137 +    struct vlapic *vlapic, uint32_t reg, uint32_t val)
   2.138  {
   2.139      *((uint32_t *)(vlapic->regs + reg)) = val;
   2.140  }
   2.141  
   2.142  
   2.143 -void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode);
   2.144 -
   2.145 -extern int vlapic_find_highest_irr(struct vlapic *vlapic);
   2.146 +int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig);
   2.147  
   2.148 -int cpu_has_apic_interrupt(struct vcpu* v);
   2.149 -int cpu_get_apic_interrupt(struct vcpu* v, int *mode);
   2.150 +void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode);
   2.151  
   2.152 -extern int vlapic_init(struct vcpu *vc);
   2.153 +int vlapic_find_highest_irr(struct vlapic *vlapic);
   2.154  
   2.155 -extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
   2.156 +int cpu_get_apic_interrupt(struct vcpu *v, int *mode);
   2.157  
   2.158 -extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
   2.159 +int vlapic_init(struct vcpu *vc);
   2.160 +
   2.161 +void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
   2.162 +
   2.163 +uint32_t vlapic_update_ppr(struct vlapic *vlapic);
   2.164  
   2.165  int vlapic_accept_pic_intr(struct vcpu *v);
   2.166  
   2.167 -struct vlapic* apic_round_robin(struct domain *d,
   2.168 +struct vlapic *apic_round_robin(struct domain *d,
   2.169                                  uint8_t dest_mode,
   2.170                                  uint8_t vector,
   2.171                                  uint32_t bitmap);