ia64/xen-unstable
changeset 16603:4553bc1087d9
hvm: Reduce vpt.c dependencies on external timer details.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
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