ia64/xen-unstable

changeset 16603:4553bc1087d9

hvm: Reduce vpt.c dependencies on external timer details.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 12 15:41:20 2007 +0000 (2007-12-12)
parents 20898120c8f9
children d90dbf72049c 2ebced8f8baf
files xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/irq.c xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpt.c xen/include/asm-x86/hvm/irq.h xen/include/asm-x86/hvm/vlapic.h xen/include/asm-x86/hvm/vpt.h
line diff
     1.1 --- a/xen/arch/x86/hvm/i8254.c	Wed Dec 12 12:02:01 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/i8254.c	Wed Dec 12 15:41:20 2007 +0000
     1.3 @@ -501,6 +501,8 @@ void pit_init(struct vcpu *v, unsigned l
     1.4      /* Some sub-functions assert that they are called with the lock held. */
     1.5      spin_lock(&pit->lock);
     1.6  
     1.7 +    pit->pt0.source = PTSRC_isa;
     1.8 +
     1.9      register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
    1.10      register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
    1.11      ticks_per_sec(v) = cpu_khz * (int64_t)1000;
     2.1 --- a/xen/arch/x86/hvm/irq.c	Wed Dec 12 12:02:01 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/irq.c	Wed Dec 12 15:41:20 2007 +0000
     2.3 @@ -347,31 +347,6 @@ struct hvm_intack hvm_vcpu_ack_pending_i
     2.4      return intack;
     2.5  }
     2.6  
     2.7 -int get_isa_irq_vector(struct vcpu *v, int isa_irq, enum hvm_intsrc src)
     2.8 -{
     2.9 -    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
    2.10 -
    2.11 -    if ( src == hvm_intsrc_pic )
    2.12 -        return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
    2.13 -                + (isa_irq & 7));
    2.14 -
    2.15 -    ASSERT(src == hvm_intsrc_lapic);
    2.16 -    return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
    2.17 -}
    2.18 -
    2.19 -int is_isa_irq_masked(struct vcpu *v, int isa_irq)
    2.20 -{
    2.21 -    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
    2.22 -    uint8_t pic_imr;
    2.23 -
    2.24 -    if ( is_lvtt(v, isa_irq) )
    2.25 -        return !is_lvtt_enabled(v);
    2.26 -
    2.27 -    pic_imr = v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr;
    2.28 -    return (((pic_imr & (1 << (isa_irq & 7))) || !vlapic_accept_pic_intr(v)) &&
    2.29 -            domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
    2.30 -}
    2.31 -
    2.32  int hvm_local_events_need_delivery(struct vcpu *v)
    2.33  {
    2.34      struct hvm_intack intack;
     3.1 --- a/xen/arch/x86/hvm/rtc.c	Wed Dec 12 12:02:01 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/rtc.c	Wed Dec 12 15:41:20 2007 +0000
     3.3 @@ -42,14 +42,6 @@ static void rtc_periodic_cb(struct vcpu 
     3.4      spin_unlock(&s->lock);
     3.5  }
     3.6  
     3.7 -int is_rtc_periodic_irq(void *opaque)
     3.8 -{
     3.9 -    RTCState *s = opaque;
    3.10 -
    3.11 -    return !(s->hw.cmos_data[RTC_REG_C] & RTC_AF || 
    3.12 -             s->hw.cmos_data[RTC_REG_C] & RTC_UF);
    3.13 -}
    3.14 -
    3.15  /* Enable/configure/disable the periodic timer based on the RTC_PIE and
    3.16   * RTC_RATE_SELECT settings */
    3.17  static void rtc_timer_update(RTCState *s)
    3.18 @@ -488,6 +480,8 @@ void rtc_init(struct vcpu *v, int base)
    3.19  
    3.20      spin_lock_init(&s->lock);
    3.21  
    3.22 +    s->pt.source = PTSRC_isa;
    3.23 +
    3.24      s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
    3.25      s->hw.cmos_data[RTC_REG_B] = RTC_24H;
    3.26      s->hw.cmos_data[RTC_REG_C] = 0;
     4.1 --- a/xen/arch/x86/hvm/vlapic.c	Wed Dec 12 12:02:01 2007 +0000
     4.2 +++ b/xen/arch/x86/hvm/vlapic.c	Wed Dec 12 15:41:20 2007 +0000
     4.3 @@ -68,9 +68,6 @@ static unsigned int vlapic_lvt_mask[VLAP
     4.4  #define APIC_DEST_NOSHORT                0x0
     4.5  #define APIC_DEST_MASK                   0x800
     4.6  
     4.7 -#define vlapic_lvt_enabled(vlapic, lvt_type)                    \
     4.8 -    (!(vlapic_get_reg(vlapic, lvt_type) & APIC_LVT_MASKED))
     4.9 -
    4.10  #define vlapic_lvt_vector(vlapic, lvt_type)                     \
    4.11      (vlapic_get_reg(vlapic, lvt_type) & APIC_VECTOR_MASK)
    4.12  
    4.13 @@ -932,6 +929,8 @@ int vlapic_init(struct vcpu *v)
    4.14  
    4.15      HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "%d", v->vcpu_id);
    4.16  
    4.17 +    vlapic->pt.source = PTSRC_lapic;
    4.18 +
    4.19  #ifdef __i386__
    4.20      /* 32-bit VMX may be limited to 32-bit physical addresses. */
    4.21      if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
    4.22 @@ -974,15 +973,3 @@ void vlapic_destroy(struct vcpu *v)
    4.23      unmap_domain_page_global(vlapic->regs);
    4.24      free_domheap_page(vlapic->regs_page);
    4.25  }
    4.26 -
    4.27 -int is_lvtt(struct vcpu *v, int vector)
    4.28 -{
    4.29 -    return (pt_active(&vcpu_vlapic(v)->pt) &&
    4.30 -            (vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT)));
    4.31 -}
    4.32 -
    4.33 -int is_lvtt_enabled(struct vcpu *v)
    4.34 -{
    4.35 -    return (vlapic_enabled(vcpu_vlapic(v)) &&
    4.36 -            vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT));
    4.37 -}
     5.1 --- a/xen/arch/x86/hvm/vpt.c	Wed Dec 12 12:02:01 2007 +0000
     5.2 +++ b/xen/arch/x86/hvm/vpt.c	Wed Dec 12 15:41:20 2007 +0000
     5.3 @@ -15,7 +15,6 @@
     5.4   * You should have received a copy of the GNU General Public License along with
     5.5   * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
     5.6   * Place - Suite 330, Boston, MA 02111-1307 USA.
     5.7 - *
     5.8   */
     5.9  
    5.10  #include <xen/time.h>
    5.11 @@ -26,6 +25,46 @@
    5.12  #define mode_is(d, name) \
    5.13      ((d)->arch.hvm_domain.params[HVM_PARAM_TIMER_MODE] == HVMPTM_##name)
    5.14  
    5.15 +static int pt_irq_vector(struct periodic_time *pt, enum hvm_intsrc src)
    5.16 +{
    5.17 +    struct vcpu *v = pt->vcpu;
    5.18 +    unsigned int gsi, isa_irq;
    5.19 +
    5.20 +    if ( pt->source == PTSRC_lapic )
    5.21 +        return pt->irq;
    5.22 +
    5.23 +    isa_irq = pt->irq;
    5.24 +    gsi = hvm_isa_irq_to_gsi(isa_irq);
    5.25 +
    5.26 +    if ( src == hvm_intsrc_pic )
    5.27 +        return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base
    5.28 +                + (isa_irq & 7));
    5.29 +
    5.30 +    ASSERT(src == hvm_intsrc_lapic);
    5.31 +    return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
    5.32 +}
    5.33 +
    5.34 +static int pt_irq_masked(struct periodic_time *pt)
    5.35 +{
    5.36 +    struct vcpu *v = pt->vcpu;
    5.37 +    unsigned int gsi, isa_irq;
    5.38 +    uint8_t pic_imr;
    5.39 +
    5.40 +    if ( pt->source == PTSRC_lapic )
    5.41 +    {
    5.42 +        struct vlapic *vlapic = vcpu_vlapic(v);
    5.43 +        return (vlapic_enabled(vlapic) &&
    5.44 +                !(vlapic_get_reg(vlapic, APIC_LVTT) & APIC_LVT_MASKED));
    5.45 +    }
    5.46 +
    5.47 +    isa_irq = pt->irq;
    5.48 +    gsi = hvm_isa_irq_to_gsi(isa_irq);
    5.49 +    pic_imr = v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr;
    5.50 +
    5.51 +    return (((pic_imr & (1 << (isa_irq & 7))) || !vlapic_accept_pic_intr(v)) &&
    5.52 +            domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
    5.53 +}
    5.54 +
    5.55  static void pt_lock(struct periodic_time *pt)
    5.56  {
    5.57      struct vcpu *v;
    5.58 @@ -144,29 +183,39 @@ static void pt_timer_fn(void *data)
    5.59  void pt_update_irq(struct vcpu *v)
    5.60  {
    5.61      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
    5.62 -    struct periodic_time *pt;
    5.63 +    struct periodic_time *pt, *earliest_pt = NULL;
    5.64      uint64_t max_lag = -1ULL;
    5.65 -    int irq = -1;
    5.66 +    int irq, is_lapic;
    5.67  
    5.68      spin_lock(&v->arch.hvm_vcpu.tm_lock);
    5.69  
    5.70      list_for_each_entry ( pt, head, list )
    5.71      {
    5.72 -        if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr &&
    5.73 +        if ( !pt_irq_masked(pt) && pt->pending_intr_nr &&
    5.74               ((pt->last_plt_gtime + pt->period_cycles) < max_lag) )
    5.75          {
    5.76              max_lag = pt->last_plt_gtime + pt->period_cycles;
    5.77 -            irq = pt->irq;
    5.78 +            earliest_pt = pt;
    5.79          }
    5.80      }
    5.81  
    5.82 +    if ( earliest_pt == NULL )
    5.83 +    {
    5.84 +        spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    5.85 +        return;
    5.86 +    }
    5.87 +
    5.88 +    earliest_pt->irq_issued = 1;
    5.89 +    irq = earliest_pt->irq;
    5.90 +    is_lapic = (earliest_pt->source == PTSRC_lapic);
    5.91 +
    5.92      spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    5.93  
    5.94 -    if ( is_lvtt(v, irq) )
    5.95 +    if ( is_lapic )
    5.96      {
    5.97          vlapic_set_irq(vcpu_vlapic(v), irq, 0);
    5.98      }
    5.99 -    else if ( irq >= 0 )
   5.100 +    else
   5.101      {
   5.102          hvm_isa_irq_deassert(v->domain, irq);
   5.103          hvm_isa_irq_assert(v->domain, irq);
   5.104 @@ -178,29 +227,12 @@ static struct periodic_time *is_pt_irq(
   5.105  {
   5.106      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
   5.107      struct periodic_time *pt;
   5.108 -    struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
   5.109 -    int vector;
   5.110  
   5.111      list_for_each_entry ( pt, head, list )
   5.112      {
   5.113 -        if ( !pt->pending_intr_nr )
   5.114 -            continue;
   5.115 -
   5.116 -        if ( is_lvtt(v, pt->irq) )
   5.117 -        {
   5.118 -            if ( pt->irq != intack.vector )
   5.119 -                continue;
   5.120 +        if ( pt->pending_intr_nr && pt->irq_issued &&
   5.121 +             (intack.vector == pt_irq_vector(pt, intack.source)) )
   5.122              return pt;
   5.123 -        }
   5.124 -
   5.125 -        vector = get_isa_irq_vector(v, pt->irq, intack.source);
   5.126 -
   5.127 -        /* RTC irq need special care */
   5.128 -        if ( (intack.vector != vector) ||
   5.129 -             ((pt->irq == 8) && !is_rtc_periodic_irq(rtc)) )
   5.130 -            continue;
   5.131 -
   5.132 -        return pt;
   5.133      }
   5.134  
   5.135      return NULL;
   5.136 @@ -222,6 +254,7 @@ void pt_intr_post(struct vcpu *v, struct
   5.137      }
   5.138  
   5.139      pt->do_not_freeze = 0;
   5.140 +    pt->irq_issued = 0;
   5.141  
   5.142      if ( pt->one_shot )
   5.143      {
   5.144 @@ -291,12 +324,15 @@ void create_periodic_time(
   5.145      struct vcpu *v, struct periodic_time *pt, uint64_t period,
   5.146      uint8_t irq, char one_shot, time_cb *cb, void *data)
   5.147  {
   5.148 +    ASSERT(pt->source != 0);
   5.149 +
   5.150      destroy_periodic_time(pt);
   5.151  
   5.152      spin_lock(&v->arch.hvm_vcpu.tm_lock);
   5.153  
   5.154      pt->pending_intr_nr = 0;
   5.155      pt->do_not_freeze = 0;
   5.156 +    pt->irq_issued = 0;
   5.157  
   5.158      /* Periodic timer must be at least 0.9ms. */
   5.159      if ( (period < 900000) && !one_shot )
   5.160 @@ -319,7 +355,7 @@ void create_periodic_time(
   5.161       * LAPIC ticks for process accounting can see long sequences of process
   5.162       * ticks incorrectly accounted to interrupt processing.
   5.163       */
   5.164 -    if ( is_lvtt(v, irq) )
   5.165 +    if ( pt->source == PTSRC_lapic )
   5.166          pt->scheduled += period >> 1;
   5.167      pt->cb = cb;
   5.168      pt->priv = data;
     6.1 --- a/xen/include/asm-x86/hvm/irq.h	Wed Dec 12 12:02:01 2007 +0000
     6.2 +++ b/xen/include/asm-x86/hvm/irq.h	Wed Dec 12 15:41:20 2007 +0000
     6.3 @@ -160,7 +160,4 @@ struct hvm_intack hvm_vcpu_has_pending_i
     6.4  struct hvm_intack hvm_vcpu_ack_pending_irq(struct vcpu *v,
     6.5                                             struct hvm_intack intack);
     6.6  
     6.7 -int get_isa_irq_vector(struct vcpu *vcpu, int irq, enum hvm_intsrc src);
     6.8 -int is_isa_irq_masked(struct vcpu *v, int isa_irq);
     6.9 -
    6.10  #endif /* __ASM_X86_HVM_IRQ_H__ */
     7.1 --- a/xen/include/asm-x86/hvm/vlapic.h	Wed Dec 12 12:02:01 2007 +0000
     7.2 +++ b/xen/include/asm-x86/hvm/vlapic.h	Wed Dec 12 15:41:20 2007 +0000
     7.3 @@ -92,7 +92,4 @@ struct vlapic *apic_round_robin(
     7.4  
     7.5  int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
     7.6  
     7.7 -int is_lvtt(struct vcpu *v, int vector);
     7.8 -int is_lvtt_enabled(struct vcpu *v);
     7.9 -
    7.10  #endif /* __ASM_X86_HVM_VLAPIC_H__ */
     8.1 --- a/xen/include/asm-x86/hvm/vpt.h	Wed Dec 12 12:02:01 2007 +0000
     8.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Wed Dec 12 15:41:20 2007 +0000
     8.3 @@ -75,6 +75,10 @@ struct periodic_time {
     8.4      bool_t on_list;
     8.5      bool_t one_shot;
     8.6      bool_t do_not_freeze;
     8.7 +    bool_t irq_issued;
     8.8 +#define PTSRC_isa    1 /* ISA time source */
     8.9 +#define PTSRC_lapic  2 /* LAPIC time source */
    8.10 +    u8 source;                  /* PTSRC_ */
    8.11      u8 irq;
    8.12      struct vcpu *vcpu;          /* vcpu timer interrupt delivers to */
    8.13      u32 pending_intr_nr;        /* pending timer interrupts */
    8.14 @@ -146,8 +150,10 @@ void pt_migrate(struct vcpu *v);
    8.15  
    8.16  /*
    8.17   * Create/destroy a periodic (or one-shot!) timer.
    8.18 - * The given periodic timer structure must be initialised with zero bytes or
    8.19 - * have been initialised by a previous invocation of create_periodic_time().
    8.20 + * The given periodic timer structure must be initialised with zero bytes,
    8.21 + * except for the 'source' field which must be initialised with the
    8.22 + * correct PTSRC_ value. The initialised timer structure can then be passed
    8.23 + * to {create,destroy}_periodic_time() and number of times and in any order.
    8.24   * Note that, for a given periodic timer, invocations of these functions MUST
    8.25   * be serialised.
    8.26   */
    8.27 @@ -163,7 +169,6 @@ void pit_deinit(struct domain *d);
    8.28  void rtc_init(struct vcpu *v, int base);
    8.29  void rtc_migrate_timers(struct vcpu *v);
    8.30  void rtc_deinit(struct domain *d);
    8.31 -int is_rtc_periodic_irq(void *opaque);
    8.32  void pmtimer_init(struct vcpu *v);
    8.33  void pmtimer_deinit(struct domain *d);
    8.34