[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] Add a timer mode that disables pending missed ticks
I'm going to apply Haitao's no_missed_ticks_fix.patch. If you think fixes are needed apart from that, please provide a unified diff. -- Keir On 30/10/07 21:16, "Dave Winchell" <dwinchell@xxxxxxxxxxxxxxx> wrote: > Keir, > > Here are my comments on your change. > I've attached an updated vpt.c with the changes. > > 1. For the no_missed_tick_accounting method, we still need the update > to pt->scheduled taking into account the time that has elapsed when > missed ticks are calculated. missed_ticks (pt_process_missed_ticks) > is called from pt_restore_timer() and pt_timer_fn() and, thus, its > easiest to put the check for no_missed_tick_accounting method in > missed_ticks() itself. > > 2. In pt_timer_fn you don't want to increment pending_intr_nr beyond 1 > for no_missed_tick_accounting option. > > thanks, > Dave > > > Keir Fraser wrote: > >> >> Applied as c/s 16274. Please take a look and make sure the mode works >> as you expect. >> >> -- Keir >> >> On 30/10/07 14:28, "Shan, Haitao" <haitao.shan@xxxxxxxxx> wrote: >> >> Hi, Keir, >> >> This patch adds a new timer mode, in which no missed ticks is >> calculated. This can be used with latest x86_64 linux guest, since >> it can pick up missed ticks themselves. >> >> <<no_missed_ticks.patch>> >> >> Best Regards >> Haitao Shan >> >> ------------------------------------------------------------------------ >> _______________________________________________ >> Xen-devel mailing list >> Xen-devel@xxxxxxxxxxxxxxxxxxx >> http://lists.xensource.com/xen-devel >> >> > > *** vpt.c.new.c 2007-10-30 16:45:26.000000000 -0400 > --- vpt.c 2007-10-30 15:30:57.000000000 -0400 > *************** > *** 57,73 **** > return; > > missed_ticks = missed_ticks / (s_time_t) pt->period + 1; > ! > ! if( !mode_is(pt->vcpu->domain, no_missed_tick_accounting) ) { > ! if ( missed_ticks > 1000 ) > ! { > ! /* TODO: Adjust guest time together */ > ! pt->pending_intr_nr++; > ! } > ! else > ! { > ! pt->pending_intr_nr += missed_ticks; > ! } > } > > pt->scheduled += missed_ticks * pt->period; > --- 57,70 ---- > return; > > missed_ticks = missed_ticks / (s_time_t) pt->period + 1; > ! if ( missed_ticks > 1000 ) > ! { > ! /* TODO: Adjust guest time together */ > ! pt->pending_intr_nr++; > ! } > ! else > ! { > ! pt->pending_intr_nr += missed_ticks; > } > > pt->scheduled += missed_ticks * pt->period; > *************** > *** 120,126 **** > > list_for_each_entry ( pt, head, list ) > { > ! pt_process_missed_ticks(pt); > set_timer(&pt->timer, pt->scheduled); > } > > --- 117,124 ---- > > list_for_each_entry ( pt, head, list ) > { > ! if ( !mode_is(v->domain, no_missed_tick_accounting) ) > ! pt_process_missed_ticks(pt); > set_timer(&pt->timer, pt->scheduled); > } > > *************** > *** 135,151 **** > > pt_lock(pt); > > ! if (mode_is(pt->vcpu->domain, no_missed_tick_accounting)) { > ! if(!pt->pending_intr_nr) > ! pt->pending_intr_nr++; > ! } > ! else > ! pt->pending_intr_nr++; > > if ( !pt->one_shot ) > { > pt->scheduled += pt->period; > ! pt_process_missed_ticks(pt); > set_timer(&pt->timer, pt->scheduled); > } > > --- 133,152 ---- > > pt_lock(pt); > > ! pt->pending_intr_nr++; > > if ( !pt->one_shot ) > { > pt->scheduled += pt->period; > ! if ( !mode_is(pt->vcpu->domain, no_missed_tick_accounting) ) > ! { > ! pt_process_missed_ticks(pt); > ! } > ! else if ( (NOW() - pt->scheduled) >= 0 ) > ! { > ! pt->pending_intr_nr++; > ! pt->scheduled = NOW() + pt->period; > ! } > set_timer(&pt->timer, pt->scheduled); > } > > /* > * vpt.c: Virtual Platform Timer > * > * Copyright (c) 2006, Xiaowei Yang, Intel Corporation. > * > * This program is free software; you can redistribute it and/or modify it > * under the terms and conditions of the GNU General Public License, > * version 2, as published by the Free Software Foundation. > * > * This program is distributed in the hope it will be useful, but WITHOUT > * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for > * more details. > * > * You should have received a copy of the GNU General Public License along > with > * this program; if not, write to the Free Software Foundation, Inc., 59 > Temple > * Place - Suite 330, Boston, MA 02111-1307 USA. > * > */ > > #include <xen/time.h> > #include <asm/hvm/support.h> > #include <asm/hvm/vpt.h> > #include <asm/event.h> > > #define mode_is(d, name) \ > ((d)->arch.hvm_domain.params[HVM_PARAM_TIMER_MODE] == HVMPTM_##name) > > static void pt_lock(struct periodic_time *pt) > { > struct vcpu *v; > > for ( ; ; ) > { > v = pt->vcpu; > spin_lock(&v->arch.hvm_vcpu.tm_lock); > if ( likely(pt->vcpu == v) ) > break; > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > } > } > > static void pt_unlock(struct periodic_time *pt) > { > spin_unlock(&pt->vcpu->arch.hvm_vcpu.tm_lock); > } > > static void pt_process_missed_ticks(struct periodic_time *pt) > { > s_time_t missed_ticks; > > if ( pt->one_shot ) > return; > > missed_ticks = NOW() - pt->scheduled; > if ( missed_ticks <= 0 ) > return; > > missed_ticks = missed_ticks / (s_time_t) pt->period + 1; > > if( !mode_is(pt->vcpu->domain, no_missed_tick_accounting) ) { > if ( missed_ticks > 1000 ) > { > /* TODO: Adjust guest time together */ > pt->pending_intr_nr++; > } > else > { > pt->pending_intr_nr += missed_ticks; > } > } > > pt->scheduled += missed_ticks * pt->period; > } > > static void pt_freeze_time(struct vcpu *v) > { > if ( !mode_is(v->domain, delay_for_missed_ticks) ) > return; > > v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v); > } > > static void pt_thaw_time(struct vcpu *v) > { > if ( !mode_is(v->domain, delay_for_missed_ticks) ) > return; > > if ( v->arch.hvm_vcpu.guest_time == 0 ) > return; > > hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time); > v->arch.hvm_vcpu.guest_time = 0; > } > > void pt_save_timer(struct vcpu *v) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > struct periodic_time *pt; > > if ( test_bit(_VPF_blocked, &v->pause_flags) ) > return; > > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > list_for_each_entry ( pt, head, list ) > stop_timer(&pt->timer); > > pt_freeze_time(v); > > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > } > > void pt_restore_timer(struct vcpu *v) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > struct periodic_time *pt; > > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > list_for_each_entry ( pt, head, list ) > { > pt_process_missed_ticks(pt); > set_timer(&pt->timer, pt->scheduled); > } > > pt_thaw_time(v); > > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > } > > static void pt_timer_fn(void *data) > { > struct periodic_time *pt = data; > > pt_lock(pt); > > if (mode_is(pt->vcpu->domain, no_missed_tick_accounting)) { > if(!pt->pending_intr_nr) > pt->pending_intr_nr++; > } > else > pt->pending_intr_nr++; > > if ( !pt->one_shot ) > { > pt->scheduled += pt->period; > pt_process_missed_ticks(pt); > set_timer(&pt->timer, pt->scheduled); > } > > vcpu_kick(pt->vcpu); > > pt_unlock(pt); > } > > void pt_update_irq(struct vcpu *v) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > struct periodic_time *pt; > uint64_t max_lag = -1ULL; > int irq = -1; > > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > list_for_each_entry ( pt, head, list ) > { > if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr && > ((pt->last_plt_gtime + pt->period_cycles) < max_lag) ) > { > max_lag = pt->last_plt_gtime + pt->period_cycles; > irq = pt->irq; > } > } > > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > > if ( is_lvtt(v, irq) ) > { > vlapic_set_irq(vcpu_vlapic(v), irq, 0); > } > else if ( irq >= 0 ) > { > hvm_isa_irq_deassert(v->domain, irq); > hvm_isa_irq_assert(v->domain, irq); > } > } > > static struct periodic_time *is_pt_irq( > struct vcpu *v, struct hvm_intack intack) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > struct periodic_time *pt; > struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc; > int vector; > > list_for_each_entry ( pt, head, list ) > { > if ( !pt->pending_intr_nr ) > continue; > > if ( is_lvtt(v, pt->irq) ) > { > if ( pt->irq != intack.vector ) > continue; > return pt; > } > > vector = get_isa_irq_vector(v, pt->irq, intack.source); > > /* RTC irq need special care */ > if ( (intack.vector != vector) || > ((pt->irq == 8) && !is_rtc_periodic_irq(rtc)) ) > continue; > > return pt; > } > > return NULL; > } > > void pt_intr_post(struct vcpu *v, struct hvm_intack intack) > { > struct periodic_time *pt; > time_cb *cb; > void *cb_priv; > > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > pt = is_pt_irq(v, intack); > if ( pt == NULL ) > { > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > return; > } > > if ( pt->one_shot ) > { > pt->enabled = 0; > list_del(&pt->list); > } > else > { > pt->pending_intr_nr--; > if ( mode_is(v->domain, no_missed_tick_accounting) ) > pt->last_plt_gtime = hvm_get_guest_time(v); > else > pt->last_plt_gtime += pt->period_cycles; > } > > if ( mode_is(v->domain, delay_for_missed_ticks) && > (hvm_get_guest_time(v) < pt->last_plt_gtime) ) > hvm_set_guest_time(v, pt->last_plt_gtime); > > cb = pt->cb; > cb_priv = pt->priv; > > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > > if ( cb != NULL ) > cb(v, cb_priv); > } > > void pt_reset(struct vcpu *v) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > struct periodic_time *pt; > > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > list_for_each_entry ( pt, head, list ) > { > pt->pending_intr_nr = 0; > pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu); > pt->scheduled = NOW() + pt->period; > set_timer(&pt->timer, pt->scheduled); > } > > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > } > > void pt_migrate(struct vcpu *v) > { > struct list_head *head = &v->arch.hvm_vcpu.tm_list; > struct periodic_time *pt; > > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > list_for_each_entry ( pt, head, list ) > migrate_timer(&pt->timer, v->processor); > > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > } > > void create_periodic_time( > struct vcpu *v, struct periodic_time *pt, uint64_t period, > uint8_t irq, char one_shot, time_cb *cb, void *data) > { > destroy_periodic_time(pt); > > spin_lock(&v->arch.hvm_vcpu.tm_lock); > > pt->enabled = 1; > pt->pending_intr_nr = 0; > > /* Periodic timer must be at least 0.9ms. */ > if ( (period < 900000) && !one_shot ) > { > gdprintk(XENLOG_WARNING, > "HVM_PlatformTime: program too small period %"PRIu64"\n", > period); > period = 900000; > } > > pt->period = period; > pt->vcpu = v; > pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu); > pt->irq = irq; > pt->period_cycles = (u64)period * cpu_khz / 1000000L; > pt->one_shot = one_shot; > pt->scheduled = NOW() + period; > /* > * Offset LAPIC ticks from other timer ticks. Otherwise guests which use > * LAPIC ticks for process accounting can see long sequences of process > * ticks incorrectly accounted to interrupt processing. > */ > if ( is_lvtt(v, irq) ) > pt->scheduled += period >> 1; > pt->cb = cb; > pt->priv = data; > > list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); > > init_timer(&pt->timer, pt_timer_fn, pt, v->processor); > set_timer(&pt->timer, pt->scheduled); > > spin_unlock(&v->arch.hvm_vcpu.tm_lock); > } > > void destroy_periodic_time(struct periodic_time *pt) > { > if ( !pt->enabled ) > return; > > pt_lock(pt); > pt->enabled = 0; > list_del(&pt->list); > pt_unlock(pt); > > /* > * pt_timer_fn() can run until this kill_timer() returns. We must do this > * outside pt_lock() otherwise we can deadlock with pt_timer_fn(). > */ > kill_timer(&pt->timer); > } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |