diff options
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 3 | ||||
-rw-r--r-- | sys/arch/i386/i386/apm.c | 6 | ||||
-rw-r--r-- | sys/arch/i386/i386/lapic.c | 12 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 10 | ||||
-rw-r--r-- | sys/arch/i386/include/_types.h | 3 | ||||
-rw-r--r-- | sys/arch/i386/include/cpu.h | 21 | ||||
-rw-r--r-- | sys/arch/i386/isa/clock.c | 154 |
7 files changed, 139 insertions, 70 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index 9a344bbbac5..54a34506343 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $OpenBSD: files.i386,v 1.155 2007/03/19 03:02:09 marco Exp $ +# $OpenBSD: files.i386,v 1.156 2007/03/19 09:29:33 art Exp $ # # new style config file for i386 architecture # @@ -30,7 +30,6 @@ file arch/i386/i386/longrun.c !small_kernel & i586_cpu file arch/i386/i386/mem.c file arch/i386/i386/i686_mem.c mtrr file arch/i386/i386/k6_mem.c mtrr -file arch/i386/i386/microtime.s file arch/i386/i386/p4tcc.c !small_kernel & i686_cpu file arch/i386/i386/pmap.c file arch/i386/i386/powernow.c !small_kernel & i586_cpu diff --git a/sys/arch/i386/i386/apm.c b/sys/arch/i386/i386/apm.c index aca6a6a1443..404c19d0204 100644 --- a/sys/arch/i386/i386/apm.c +++ b/sys/arch/i386/i386/apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apm.c,v 1.73 2007/02/27 15:16:30 marco Exp $ */ +/* $OpenBSD: apm.c,v 1.74 2007/03/19 09:29:33 art Exp $ */ /*- * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. @@ -351,7 +351,7 @@ apm_resume(struct apm_softc *sc, struct apmregs *regs) /* they say that some machines may require reinitializing the clock */ initrtclock(); - inittodr(time.tv_sec); + inittodr(time_second); /* lower bit in cx means pccard was powered down */ dopowerhooks(PWR_RESUME); apm_record_event(sc, regs->bx); @@ -464,7 +464,7 @@ apm_handle_event(struct apm_softc *sc, struct apmregs *regs) break; case APM_UPDATE_TIME: DPRINTF(("update time, please\n")); - inittodr(time.tv_sec); + inittodr(time_second); apm_record_event(sc, regs->bx); break; case APM_CRIT_SUSPEND_REQ: diff --git a/sys/arch/i386/i386/lapic.c b/sys/arch/i386/i386/lapic.c index bd74f8d5f10..3c05f8f3aec 100644 --- a/sys/arch/i386/i386/lapic.c +++ b/sys/arch/i386/i386/lapic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lapic.c,v 1.13 2007/02/20 21:15:01 tom Exp $ */ +/* $OpenBSD: lapic.c,v 1.14 2007/03/19 09:29:33 art Exp $ */ /* $NetBSD: lapic.c,v 1.1.2.8 2000/02/23 06:10:50 sommerfeld Exp $ */ /*- @@ -44,6 +44,7 @@ #include <sys/user.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/timetc.h> #include <uvm/uvm_extern.h> @@ -259,8 +260,7 @@ extern void (*initclock_func)(void); /* XXX put in header file */ * We're actually using the IRQ0 timer. Hmm. */ void -lapic_calibrate_timer(ci) - struct cpu_info *ci; +lapic_calibrate_timer(struct cpu_info *ci) { unsigned int starttick, tick1, tick2, endtick; unsigned int startapic, apic1, apic2, endapic; @@ -386,7 +386,6 @@ lapic_calibrate_timer(ci) * for all our timing needs.. */ delay_func = lapic_delay; - microtime_func = lapic_microtime; initclock_func = lapic_initclocks; } } @@ -396,8 +395,7 @@ lapic_calibrate_timer(ci) */ void -lapic_delay(usec) - int usec; +lapic_delay(int usec) { int32_t tick, otick; int64_t deltat; /* XXX may want to be 64bit */ @@ -432,6 +430,7 @@ i386_ipi_microset(struct cpu_info *ci) ci->ci_tscbase = rdtsc(); } +#if 0 /* * XXX need to make work correctly on other than cpu 0. */ @@ -457,6 +456,7 @@ lapic_microtime(tv) *tv = now; } +#endif /* * XXX the following belong mostly or partly elsewhere.. diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 9a144fb849e..3343744a8ca 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.379 2007/02/21 19:34:25 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.380 2007/03/19 09:29:33 art Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -256,7 +256,6 @@ void (*setperf_setup)(struct cpu_info *); int setperf_prio = 0; /* for concurrent handlers */ void (*delay_func)(int) = i8254_delay; -void (*microtime_func)(struct timeval *) = i8254_microtime; void (*initclock_func)(void) = i8254_initclocks; void (*update_cpuspeed)(void) = NULL; @@ -3288,9 +3287,14 @@ cpu_reset() } void -cpu_initclocks() +cpu_initclocks(void) { (*initclock_func)(); + + if (initclock_func == i8254_initclocks) + i8254_inittimecounter(); + else + i8254_inittimecounter_simple(); } void diff --git a/sys/arch/i386/include/_types.h b/sys/arch/i386/include/_types.h index cef2a372f29..52cbef65faa 100644 --- a/sys/arch/i386/include/_types.h +++ b/sys/arch/i386/include/_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: _types.h,v 1.4 2007/02/20 21:15:01 tom Exp $ */ +/* $OpenBSD: _types.h,v 1.5 2007/03/19 09:29:33 art Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -117,5 +117,6 @@ typedef void * __wctype_t; /* Feature test macros */ #define __HAVE_CPUINFO #define __HAVE_MUTEX +#define __HAVE_TIMECOUNTER #endif /* _I386__TYPES_H_ */ diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h index a066cbea0bb..faebea52539 100644 --- a/sys/arch/i386/include/cpu.h +++ b/sys/arch/i386/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.88 2007/03/15 10:22:29 art Exp $ */ +/* $OpenBSD: cpu.h,v 1.89 2007/03/19 09:29:33 art Exp $ */ /* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ /*- @@ -237,30 +237,15 @@ extern void need_resched(struct cpu_info *); */ extern void (*delay_func)(int); struct timeval; -extern void (*microtime_func)(struct timeval *); #define DELAY(x) (*delay_func)(x) #define delay(x) (*delay_func)(x) -#define microtime(tv) (*microtime_func)(tv) #if defined(I586_CPU) || defined(I686_CPU) /* * High resolution clock support (Pentium only) */ void calibrate_cyclecounter(void); -#ifndef HZ -extern u_quad_t pentium_base_tsc; -#define CPU_CLOCKUPDATE() \ - do { \ - if (cpuspeed) { \ - __asm __volatile("cli\n" \ - "rdtsc\n" \ - : "=A" (pentium_base_tsc) \ - : ); \ - __asm __volatile("sti"); \ - } \ - } while (0) -#endif #endif /* @@ -357,8 +342,10 @@ void initrtclock(void); void startrtclock(void); void rtcdrain(void *); void i8254_delay(int); -void i8254_microtime(struct timeval *); void i8254_initclocks(void); +void i8254_inittimecounter(void); +void i8254_inittimecounter_simple(void); + /* est.c */ #if !defined(SMALL_KERNEL) && defined(I686_CPU) diff --git a/sys/arch/i386/isa/clock.c b/sys/arch/i386/isa/clock.c index 0fd1090e682..f3b34498b3a 100644 --- a/sys/arch/i386/isa/clock.c +++ b/sys/arch/i386/isa/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.38 2006/12/20 17:50:40 gwk Exp $ */ +/* $OpenBSD: clock.c,v 1.39 2007/03/19 09:29:33 art Exp $ */ /* $NetBSD: clock.c,v 1.39 1996/05/12 23:11:54 mycroft Exp $ */ /*- @@ -92,6 +92,8 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include <sys/kernel.h> #include <sys/device.h> #include <sys/timeout.h> +#include <sys/timetc.h> +#include <sys/mutex.h> #include <machine/cpu.h> #include <machine/intr.h> @@ -105,7 +107,6 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include <i386/isa/timerreg.h> void spinwait(int); -void findcpuspeed(void); int clockintr(void *); int gettick(void); int rtcget(mc_todregs *); @@ -125,6 +126,19 @@ int cpuspeed; int clock_broken_latch; #endif +/* Timecounter on the i8254 */ +uint32_t i8254_lastcount; +uint32_t i8254_offset; +int i8254_ticked; +u_int i8254_get_timecount(struct timecounter *tc); +u_int i8254_simple_get_timecount(struct timecounter *tc); + +static struct timecounter i8254_timecounter = { + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL +}; +struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH); +u_long rtclock_tval; + #define SECMIN ((unsigned)60) /* seconds per minute */ #define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */ @@ -161,8 +175,6 @@ startrtclock(void) { int s; - findcpuspeed(); /* use the clock (while it's free) - to find the cpu speed */ initrtclock(); /* Check diagnostic status */ @@ -190,12 +202,17 @@ rtcdrain(void *v) void initrtclock(void) { + mtx_enter(&timer_mutex); + /* initialize 8253 clock */ outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); /* Correct rounding will buy us a better precision in timekeeping */ outb(IO_TIMER1, TIMER_DIV(hz) % 256); outb(IO_TIMER1, TIMER_DIV(hz) / 256); + + rtclock_tval = TIMER_DIV(hz); + mtx_leave(&timer_mutex); } int @@ -203,6 +220,15 @@ clockintr(void *arg) { struct clockframe *frame = arg; /* not strictly necessary */ + if (timecounter->tc_get_timecount == i8254_get_timecount) { + if (i8254_ticked) { + i8254_ticked = 0; + } else { + i8254_offset += rtclock_tval; + i8254_lastcount = 0; + } + } + hardclock(frame); return (1); } @@ -233,6 +259,11 @@ gettick(void) int v1, v2, v3; int w1, w2, w3; + /* + * Don't lock the mutex in this case, clock_broken_latch + * CPUs don't do MP anyway. + */ + disable_intr(); v1 = inb(TIMER_CNTR0); @@ -279,14 +310,18 @@ gettick(void) #endif { u_char lo, hi; + u_long ef; + mtx_enter(&timer_mutex); + ef = read_eflags(); disable_intr(); /* Select counter 0 and latch it. */ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); lo = inb(TIMER_CNTR0); hi = inb(TIMER_CNTR0); - enable_intr(); + write_eflags(ef); + mtx_leave(&timer_mutex); return ((hi << 8) | lo); } } @@ -350,31 +385,6 @@ i8254_delay(int n) } } -unsigned int delaycount; /* calibrated loop variable (1 millisecond) */ - -#define FIRST_GUESS 0x2000 - -void -findcpuspeed(void) -{ - int i; - int remainder; - - /* Put counter in count down mode */ - outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN); - outb(TIMER_CNTR0, 0xff); - outb(TIMER_CNTR0, 0xff); - for (i = FIRST_GUESS; i; i--) - ; - /* Read the value left in the counter */ - remainder = gettick(); - /* - * Formula for delaycount is: - * (loopcount * timer clock speed) / (counter ticks * 1000) - */ - delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff-remainder); -} - #if defined(I586_CPU) || defined(I686_CPU) void calibrate_cyclecounter(void) @@ -537,10 +547,14 @@ clock_expandyear(int clockyear) void inittodr(time_t base) { + struct timespec ts; mc_todregs rtclk; struct clock_ymdhms dt; int s; + + ts.tv_nsec = 0; + /* * We mostly ignore the suggested time and go for the RTC clock time * stored in the CMOS RAM. If the time can't be obtained from the @@ -555,8 +569,6 @@ inittodr(time_t base) base = 17*SECYR + 186*SECDAY + SECDAY/2; } - time.tv_usec = 0; - s = splclock(); if (rtcget(&rtclk)) { splx(s); @@ -592,24 +604,26 @@ inittodr(time_t base) } } - time.tv_sec = clock_ymdhms_to_secs(&dt) + tz.tz_minuteswest * 60; + ts.tv_sec = clock_ymdhms_to_secs(&dt) + tz.tz_minuteswest * 60; if (tz.tz_dsttime) - time.tv_sec -= 3600; + ts.tv_sec -= 3600; - if (base < time.tv_sec - 5*SECYR) + if (base < ts.tv_sec - 5*SECYR) printf("WARNING: file system time much less than clock time\n"); - else if (base > time.tv_sec + 5*SECYR) { + else if (base > ts.tv_sec + 5*SECYR) { printf("WARNING: clock time much less than file system time\n"); printf("WARNING: using file system time\n"); goto fstime; } + tc_setclock(&ts); timeset = 1; return; fstime: + ts.tv_sec = base; + tc_setclock(&ts); timeset = 1; - time.tv_sec = base; printf("WARNING: CHECK AND RESET THE DATE!\n"); } @@ -640,7 +654,7 @@ resettodr(void) diff = tz.tz_minuteswest * 60; if (tz.tz_dsttime) diff -= 3600; - clock_secs_to_ymdhms(time.tv_sec - diff, &dt); + clock_secs_to_ymdhms(time_second - diff, &dt); rtclk[MC_SEC] = dectohexdec(dt.dt_sec); rtclk[MC_MIN] = dectohexdec(dt.dt_min); @@ -666,3 +680,67 @@ setstatclockrate(int arg) else mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz); } + +void +i8254_inittimecounter(void) +{ + tc_init(&i8254_timecounter); +} + +/* + * If we're using lapic to drive hardclock, we can use a simpler + * algorithm for the i8254 timecounters. + */ +void +i8254_inittimecounter_simple(void) +{ + u_long tval = 0x8000; + + i8254_timecounter.tc_get_timecount = i8254_simple_get_timecount; + i8254_timecounter.tc_counter_mask = 0x7fff; + + i8254_timecounter.tc_frequency = TIMER_FREQ; + + mtx_enter(&timer_mutex); + outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); + outb(IO_TIMER1, tval & 0xff); + outb(IO_TIMER1, tval >> 8); + + rtclock_tval = tval; + mtx_leave(&timer_mutex); + + tc_init(&i8254_timecounter); +} + +u_int +i8254_simple_get_timecount(struct timecounter *tc) +{ + return (rtclock_tval - gettick()); +} + +u_int +i8254_get_timecount(struct timecounter *tc) +{ + u_char hi, lo; + u_int count; + u_long ef; + + ef = read_eflags(); + disable_intr(); + + outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); + lo = inb(TIMER_CNTR0); + hi = inb(TIMER_CNTR0); + + count = rtclock_tval - ((hi << 8) | lo); + + if (count < i8254_lastcount) { + i8254_ticked = 1; + i8254_offset += rtclock_tval; + } + i8254_lastcount = count; + count += i8254_offset; + write_eflags(ef); + + return (count); +} |