From owner-freebsd-current@FreeBSD.ORG Fri Jun 24 19:28:50 2005 Return-Path: X-Original-To: freebsd-current@freebsd.org Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C6F0816A41C; Fri, 24 Jun 2005 19:28:50 +0000 (GMT) (envelope-from jhb@FreeBSD.org) Received: from mv.twc.weather.com (mv.twc.weather.com [65.212.71.225]) by mx1.FreeBSD.org (Postfix) with ESMTP id 79A5943D1D; Fri, 24 Jun 2005 19:28:50 +0000 (GMT) (envelope-from jhb@FreeBSD.org) Received: from [10.50.41.231] (Not Verified[65.202.103.25]) by mv.twc.weather.com with NetIQ MailMarshal (v6, 0, 3, 8) id ; Fri, 24 Jun 2005 15:42:26 -0400 From: John Baldwin To: freebsd-current@freebsd.org Date: Fri, 24 Jun 2005 15:28:42 -0400 User-Agent: KMail/1.8 References: <20050516113420.GA786@schweikhardt.net> <20050624165002.GA860@schweikhardt.net> <200506241353.52383.jhb@FreeBSD.org> In-Reply-To: <200506241353.52383.jhb@FreeBSD.org> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200506241528.44124.jhb@FreeBSD.org> Cc: phk@FreeBSD.org, Jens Schweikhardt Subject: Re: Timekeeping hosed by factor 3, high lapic[01] interrupt rates X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Jun 2005 19:28:50 -0000 On Friday 24 June 2005 01:53 pm, John Baldwin wrote: > On Friday 24 June 2005 12:50 pm, Jens Schweikhardt wrote: > > On Thu, Jun 23, 2005 at 05:14:39PM -0400, John Baldwin wrote: > > ... > > # Ok. What timecounter does your UP kernel use, and does your UP kernel > > break # if you change the timecounter to i8254? > > > > The UP uses the TSC: > > $ sysctl -a|grep timec > > kern.timecounter.stepwarnings: 0 > > kern.timecounter.nbinuptime: 136311 > > kern.timecounter.nnanouptime: 0 > > kern.timecounter.nmicrouptime: 664 > > kern.timecounter.nbintime: 1273 > > kern.timecounter.nnanotime: 36 > > kern.timecounter.nmicrotime: 1237 > > kern.timecounter.ngetbinuptime: 405 > > kern.timecounter.ngetnanouptime: 29 > > kern.timecounter.ngetmicrouptime: 2534 > > kern.timecounter.ngetbintime: 0 > > kern.timecounter.ngetnanotime: 0 > > kern.timecounter.ngetmicrotime: 5 > > kern.timecounter.nsetclock: 2 > > kern.timecounter.hardware: TSC > > kern.timecounter.choice: TSC(800) i8254(0) dummy(-1000000) > > kern.timecounter.tick: 1 > > kern.timecounter.smp_tsc: 0 > > > > When I do > > > > $ sysctl kern.timecounter.hardware=i8254 > > > > on the UP the time dilation by factor 3 starts and the lapic rate > > increases. So yes, that breaks the UP kernel. > > Ok. Can you try this untested patch? It's mostly from phk and I haven't > yet tested it locally to make sure it doesn't break things: Scratch that. I've reproduced this locally now on a testbox I have and had to add a bugfix from phk to get it to work. Here's the patch that works for me: --- //depot/vendor/freebsd/src/sys/i386/isa/clock.c 2005/05/14 09:10:26 +++ //depot/user/jhb/acpipci/i386/isa/clock.c 2005/06/24 19:19:38 @@ -136,6 +136,7 @@ static u_char timer2_state; static unsigned i8254_get_timecount(struct timecounter *tc); +static unsigned i8254_simple_get_timecount(struct timecounter *tc); static void set_timer_freq(u_int freq, int intr_freq); static struct timecounter i8254_timecounter = { @@ -532,10 +533,15 @@ { int new_timer0_max_count; + i8254_timecounter.tc_frequency = freq; mtx_lock_spin(&clock_lock); timer_freq = freq; new_timer0_max_count = hardclock_max_count = TIMER_DIV(intr_freq); - if (new_timer0_max_count != timer0_max_count) { + if (using_lapic_timer) { + outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); + outb(TIMER_CNTR0, 0); + outb(TIMER_CNTR0, 0); + } else if (new_timer0_max_count != timer0_max_count) { timer0_max_count = new_timer0_max_count; outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); outb(TIMER_CNTR0, timer0_max_count & 0xff); @@ -548,11 +554,7 @@ i8254_restore(void) { - mtx_lock_spin(&clock_lock); - outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); - outb(TIMER_CNTR0, timer0_max_count & 0xff); - outb(TIMER_CNTR0, timer0_max_count >> 8); - mtx_unlock_spin(&clock_lock); + set_timer_freq(timer_freq, hz); } static void @@ -627,7 +629,6 @@ } set_timer_freq(timer_freq, hz); - i8254_timecounter.tc_frequency = timer_freq; tc_init(&i8254_timecounter); init_TSC(); @@ -782,7 +783,8 @@ /* * If we aren't using the local APIC timer to drive the kernel * clocks, setup the interrupt handler for the 8254 timer 0 so - * that it can drive hardclock(). + * that it can drive hardclock(). Otherwise, change the 8254 + * timecounter to user a simpler algorithm. */ if (!using_lapic_timer) { intr_add_handler("clk", 0, (driver_intr_t *)clkintr, NULL, @@ -791,6 +793,11 @@ if (i8254_intsrc != NULL) i8254_pending = i8254_intsrc->is_pic->pic_source_pending; + } else { + i8254_timecounter.tc_get_timecount = + i8254_simple_get_timecount; + i8254_timecounter.tc_counter_mask = 0xffff; + set_timer_freq(timer_freq, hz); } /* Initialize RTC. */ @@ -858,10 +865,8 @@ */ freq = timer_freq; error = sysctl_handle_int(oidp, &freq, sizeof(freq), req); - if (error == 0 && req->newptr != NULL) { + if (error == 0 && req->newptr != NULL) set_timer_freq(freq, hz); - i8254_timecounter.tc_frequency = freq; - } return (error); } @@ -869,6 +874,24 @@ 0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", ""); static unsigned +i8254_simple_get_timecount(struct timecounter *tc) +{ + u_int count; + u_int high, low; + + mtx_lock_spin(&clock_lock); + + /* Select timer0 and latch counter value. */ + outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); + + low = inb(TIMER_CNTR0); + high = inb(TIMER_CNTR0); + count = 0xffff - ((high << 8) | low); + mtx_unlock_spin(&clock_lock); + return (count); +} + +static unsigned i8254_get_timecount(struct timecounter *tc) { u_int count; -- John Baldwin <>< http://www.FreeBSD.org/~jhb/ "Power Users Use the Power to Serve" = http://www.FreeBSD.org