[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 11/12] x86/vpt: remove vPT timers per-vCPU lists
No longer add vPT timers to lists on specific vCPUs, since there's no need anymore to check if timer interrupts have been injected on return to HVM guest. Such change allows to get rid of virtual timers vCPU migration, and also cleanup some of the virtual timers fields that are no longer required. The model is also slightly different now in that timers are not stopped when a vCPU is de-scheduled. Such timers will continue running, and when triggered the function will try to inject the corresponding interrupt to the guest (which might be different than the currently running one). Note that the timer triggering when the guest is no longer running can only happen once, as the timer callback will not reset the interrupt to fire again. Such resetting if required will be done by the EOI callback. Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> --- Changes since v3: - Remove stale commit log paragrpah. Changes since v2: - Remove pt_{save/restore}_timer and instead use pt_{freeze/thaw}_time. - Remove the introduction of the 'masked' field, it's not needed. - Rework pt_active to use timer_is_active. Changes since v1: - New in this version. --- xen/arch/x86/domain.c | 4 +- xen/arch/x86/hvm/hvm.c | 4 +- xen/arch/x86/hvm/vlapic.c | 1 - xen/arch/x86/hvm/vpt.c | 192 ++++----------------------------- xen/include/asm-x86/hvm/vcpu.h | 3 +- xen/include/asm-x86/hvm/vpt.h | 12 +-- 6 files changed, 25 insertions(+), 191 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 4dc27f798e7..b6cd715dce9 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -2039,8 +2039,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next) vpmu_switch_from(prev); np2m_schedule(NP2M_SCHEDLE_OUT); - if ( is_hvm_domain(prevd) && !list_empty(&prev->arch.hvm.tm_list) ) - pt_save_timer(prev); + if ( is_hvm_domain(prevd) ) + pt_freeze_time(prev); local_irq_disable(); diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 2c4dd1b86f2..ec4ab1f5199 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -489,7 +489,6 @@ void hvm_set_info_guest(struct vcpu *v) void hvm_migrate_timers(struct vcpu *v) { rtc_migrate_timers(v); - pt_migrate(v); } void hvm_migrate_pirq(struct hvm_pirq_dpci *pirq_dpci, const struct vcpu *v) @@ -544,7 +543,7 @@ void hvm_do_resume(struct vcpu *v) { check_wakeup_from_wait(); - pt_restore_timer(v); + pt_thaw_time(v); if ( !vcpu_ioreq_handle_completion(v) ) return; @@ -1559,7 +1558,6 @@ int hvm_vcpu_initialise(struct vcpu *v) hvm_asid_flush_vcpu(v); spin_lock_init(&v->arch.hvm.tm_lock); - INIT_LIST_HEAD(&v->arch.hvm.tm_list); rc = hvm_vcpu_cacheattr_init(v); /* teardown: vcpu_cacheattr_destroy */ if ( rc != 0 ) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 8f3a0a2e8f7..2af24989dd5 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -1342,7 +1342,6 @@ void vlapic_adjust_i8259_target(struct domain *d) if ( d->arch.hvm.i8259_target == v ) return; d->arch.hvm.i8259_target = v; - pt_adjust_global_vcpu_target(v); } int vlapic_has_pending_irq(struct vcpu *v) diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c index 639e45c520e..6a8d216c7b5 100644 --- a/xen/arch/x86/hvm/vpt.c +++ b/xen/arch/x86/hvm/vpt.c @@ -125,24 +125,6 @@ static int pt_irq_masked(struct periodic_time *pt) return 1; } -/* - * Functions which read (maybe write) all periodic_time instances - * attached to a particular vCPU use pt_vcpu_{un}lock locking helpers. - * - * Such users are explicitly forbidden from changing the value of the - * pt->vcpu field, because another thread holding the pt_migrate lock - * may already be spinning waiting for your vcpu lock. - */ -static void pt_vcpu_lock(struct vcpu *v) -{ - spin_lock(&v->arch.hvm.tm_lock); -} - -static void pt_vcpu_unlock(struct vcpu *v) -{ - spin_unlock(&v->arch.hvm.tm_lock); -} - /* * Functions which want to modify a particular periodic_time object * use pt_{un}lock locking helpers. @@ -176,14 +158,12 @@ static void pt_process_missed_ticks(struct periodic_time *pt) return; missed_ticks = missed_ticks / (s_time_t) pt->period + 1; - if ( mode_is(pt->vcpu->domain, no_missed_ticks_pending) ) - pt->do_not_freeze = !pt->pending_intr_nr; - else + if ( !mode_is(pt->vcpu->domain, no_missed_ticks_pending) ) pt->pending_intr_nr += missed_ticks; pt->scheduled += missed_ticks * pt->period; } -static void pt_freeze_time(struct vcpu *v) +void pt_freeze_time(struct vcpu *v) { if ( !mode_is(v->domain, delay_for_missed_ticks) ) return; @@ -191,7 +171,7 @@ static void pt_freeze_time(struct vcpu *v) v->arch.hvm.guest_time = hvm_get_guest_time(v); } -static void pt_thaw_time(struct vcpu *v) +void pt_thaw_time(struct vcpu *v) { if ( !mode_is(v->domain, delay_for_missed_ticks) ) return; @@ -203,52 +183,11 @@ static void pt_thaw_time(struct vcpu *v) v->arch.hvm.guest_time = 0; } -void pt_save_timer(struct vcpu *v) -{ - struct list_head *head = &v->arch.hvm.tm_list; - struct periodic_time *pt; - - if ( v->pause_flags & VPF_blocked ) - return; - - pt_vcpu_lock(v); - - list_for_each_entry ( pt, head, list ) - if ( !pt->do_not_freeze ) - stop_timer(&pt->timer); - - pt_freeze_time(v); - - pt_vcpu_unlock(v); -} - -void pt_restore_timer(struct vcpu *v) -{ - struct list_head *head = &v->arch.hvm.tm_list; - struct periodic_time *pt; - - pt_vcpu_lock(v); - - list_for_each_entry ( pt, head, list ) - if ( pt->pending_intr_nr == 0 ) - set_timer(&pt->timer, pt->scheduled); - - pt_thaw_time(v); - - pt_vcpu_unlock(v); -} - static void irq_eoi(struct periodic_time *pt) { - pt->irq_issued = false; - if ( pt->one_shot ) { - if ( pt->on_list ) - list_del(&pt->list); - pt->on_list = false; pt->pending_intr_nr = 0; - return; } @@ -266,7 +205,11 @@ static void irq_eoi(struct periodic_time *pt) } if ( !pt->pending_intr_nr ) + { + /* Make sure timer follows vCPU. */ + migrate_timer(&pt->timer, current->processor); set_timer(&pt->timer, pt->scheduled); + } } static void pt_timer_fn(void *data) @@ -282,21 +225,15 @@ static void pt_timer_fn(void *data) v = pt->vcpu; irq = pt->irq; - if ( inject_interrupt(pt) ) + pt->scheduled += pt->period; + + if ( !inject_interrupt(pt) ) + pt->pending_intr_nr++; + else { - pt->scheduled += pt->period; - pt->do_not_freeze = 0; cb = pt->cb; cb_priv = pt->priv; } - else - { - /* Masked. */ - if ( pt->on_list ) - list_del(&pt->list); - pt->on_list = false; - pt->pending_intr_nr++; - } pt_unlock(pt); @@ -313,22 +250,12 @@ static void eoi_callback(struct periodic_time *pt) pt_lock(pt); irq_eoi(pt); - if ( pt->pending_intr_nr ) + if ( pt->pending_intr_nr && inject_interrupt(pt) ) { - if ( inject_interrupt(pt) ) - { - pt->pending_intr_nr--; - cb = pt->cb; - cb_priv = pt->priv; - v = pt->vcpu; - } - else - { - /* Masked. */ - if ( pt->on_list ) - list_del(&pt->list); - pt->on_list = false; - } + pt->pending_intr_nr--; + cb = pt->cb; + cb_priv = pt->priv; + v = pt->vcpu; } pt_unlock(pt); @@ -397,19 +324,6 @@ static bool inject_interrupt(struct periodic_time *pt) return true; } -void pt_migrate(struct vcpu *v) -{ - struct list_head *head = &v->arch.hvm.tm_list; - struct periodic_time *pt; - - pt_vcpu_lock(v); - - list_for_each_entry ( pt, head, list ) - migrate_timer(&pt->timer, v->processor); - - pt_vcpu_unlock(v); -} - void create_periodic_time( struct vcpu *v, struct periodic_time *pt, uint64_t delta, uint64_t period, uint8_t irq, time_cb *cb, void *data, bool level) @@ -429,8 +343,6 @@ void create_periodic_time( write_lock(&v->domain->arch.hvm.pl_time->pt_migrate); pt->pending_intr_nr = 0; - pt->do_not_freeze = 0; - pt->irq_issued = 0; /* Periodic timer must be at least 0.1ms. */ if ( (period < 100000) && period ) @@ -488,11 +400,6 @@ void create_periodic_time( break; } - pt_vcpu_lock(v); - pt->on_list = 1; - list_add(&pt->list, &v->arch.hvm.tm_list); - pt_vcpu_unlock(v); - init_timer(&pt->timer, pt_timer_fn, pt, v->processor); set_timer(&pt->timer, pt->scheduled); @@ -508,9 +415,6 @@ void destroy_periodic_time(struct periodic_time *pt) return; pt_lock(pt); - if ( pt->on_list ) - list_del(&pt->list); - pt->on_list = 0; pt->pending_intr_nr = 0; gsi = pt->irq; @@ -532,64 +436,6 @@ void destroy_periodic_time(struct periodic_time *pt) kill_timer(&pt->timer); } -static void pt_adjust_vcpu(struct periodic_time *pt, struct vcpu *v) -{ - ASSERT(pt->source == PTSRC_isa || pt->source == PTSRC_ioapic); - - if ( pt->vcpu == NULL ) - return; - - write_lock(&v->domain->arch.hvm.pl_time->pt_migrate); - - if ( pt->vcpu == v ) - goto out; - - pt_vcpu_lock(pt->vcpu); - if ( pt->on_list ) - list_del(&pt->list); - pt_vcpu_unlock(pt->vcpu); - - pt->vcpu = v; - - pt_vcpu_lock(v); - if ( pt->on_list ) - { - list_add(&pt->list, &v->arch.hvm.tm_list); - migrate_timer(&pt->timer, v->processor); - } - pt_vcpu_unlock(v); - - out: - write_unlock(&v->domain->arch.hvm.pl_time->pt_migrate); -} - -void pt_adjust_global_vcpu_target(struct vcpu *v) -{ - struct PITState *vpit; - struct pl_time *pl_time; - int i; - - if ( !v || !has_vpit(v->domain) ) - return; - - vpit = &v->domain->arch.vpit; - - spin_lock(&vpit->lock); - pt_adjust_vcpu(&vpit->pt0, v); - spin_unlock(&vpit->lock); - - pl_time = v->domain->arch.hvm.pl_time; - - spin_lock(&pl_time->vrtc.lock); - pt_adjust_vcpu(&pl_time->vrtc.pt, v); - spin_unlock(&pl_time->vrtc.lock); - - write_lock(&pl_time->vhpet.lock); - for ( i = 0; i < HPET_TIMER_NUM; i++ ) - pt_adjust_vcpu(&pl_time->vhpet.pt[i], v); - write_unlock(&pl_time->vhpet.lock); -} - static void pt_resume(struct periodic_time *pt) { struct vcpu *v; @@ -600,14 +446,12 @@ static void pt_resume(struct periodic_time *pt) return; pt_lock(pt); - if ( pt->pending_intr_nr && !pt->on_list && inject_interrupt(pt) ) + if ( pt->pending_intr_nr && inject_interrupt(pt) ) { pt->pending_intr_nr--; cb = pt->cb; cb_priv = pt->priv; v = pt->vcpu; - pt->on_list = 1; - list_add(&pt->list, &pt->vcpu->arch.hvm.tm_list); } pt_unlock(pt); diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h index 8adf4555c2a..9a756964fb0 100644 --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -148,9 +148,8 @@ struct hvm_vcpu { s64 cache_tsc_offset; u64 guest_time; - /* Lock and list for virtual platform timers. */ + /* Lock for virtual platform timers. */ spinlock_t tm_lock; - struct list_head tm_list; bool flag_dr_dirty; bool debug_state_latch; diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index 384d2e02039..323afa605e7 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -31,11 +31,7 @@ typedef void time_cb(struct vcpu *v, void *opaque); struct periodic_time { - struct list_head list; - bool on_list; bool one_shot; - bool do_not_freeze; - bool irq_issued; bool warned_timeout_too_short; bool level; #define PTSRC_isa 1 /* ISA time source */ @@ -151,11 +147,9 @@ struct pl_time { /* platform time */ struct domain *domain; }; -void pt_save_timer(struct vcpu *v); -void pt_restore_timer(struct vcpu *v); -void pt_migrate(struct vcpu *v); +void pt_freeze_time(struct vcpu *v); +void pt_thaw_time(struct vcpu *v); -void pt_adjust_global_vcpu_target(struct vcpu *v); #define pt_global_vcpu_target(d) \ (is_hvm_domain(d) && (d)->arch.hvm.i8259_target ? \ (d)->arch.hvm.i8259_target : \ @@ -164,7 +158,7 @@ void pt_adjust_global_vcpu_target(struct vcpu *v); void pt_may_unmask_irq(struct domain *d, struct periodic_time *vlapic_pt); /* Is given periodic timer active? */ -#define pt_active(pt) ((pt)->on_list || (pt)->pending_intr_nr) +#define pt_active(pt) ((pt)->pending_intr_nr || timer_is_active(&(pt)->timer)) /* * Create/destroy a periodic (or one-shot!) timer. -- 2.30.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |