Index: arch/alpha/alpha/clock.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/alpha/clock.c,v retrieving revision 1.36 diff -u -r1.36 clock.c --- arch/alpha/alpha/clock.c 11 Dec 2005 12:16:10 -0000 1.36 +++ arch/alpha/alpha/clock.c 7 Jul 2007 21:06:32 -0000 @@ -76,8 +76,6 @@ * @(#)clock.c 8.1 (Berkeley) 6/10/93 */ -#include "opt_multiprocessor.h" - #include /* RCS ID & Copyright macro defns */ __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.36 2005/12/11 12:16:10 christos Exp $"); @@ -86,85 +84,42 @@ #include #include #include -#include - -#include #include #include +#include -#include +#include -#include "opt_clock_compat_osf1.h" -#include "opt_ntp.h" +#define PCC_QUAL 1000 -#define MINYEAR 1998 /* "today" */ -#ifdef CLOCK_COMPAT_OSF1 -/* - * According to OSF/1's /usr/sys/include/arch/alpha/clock.h, - * the console adjusts the RTC years 13..19 to 93..99 and - * 20..40 to 00..20. (historical reasons?) - * DEC Unix uses an offset to the year to stay outside - * the dangerous area for the next couple of years. - */ -#define UNIX_YEAR_OFFSET 52 /* 41=>1993, 12=>2064 */ -#else -#define UNIX_YEAR_OFFSET 0 -#endif - -struct device *clockdev; -const struct clockfns *clockfns; -int clockinitted; +void (*clock_init)(void *); +void *clockdev; void -clockattach(dev, fns) - struct device *dev; - const struct clockfns *fns; +clockattach(void (*fns)(void *), void *dev) { /* * Just bookkeeping. */ - printf("\n"); - - if (clockfns != NULL) + if (clock_init != NULL) panic("clockattach: multiple clocks"); + clock_init = fns; clockdev = dev; - clockfns = fns; } /* - * Machine-dependent clock routines. - * - * Startrtclock restarts the real-time clock, which provides - * hardclock interrupts to kern_clock.c. - * - * Inittodr initializes the time of day hardware which provides - * date functions. Its primary function is to use some file - * system information in case the hardware clock lost state. - * - * Resettodr restores the time of day hardware after a time change. - */ - -/* * Start the real-time and statistics clocks. Leave stathz 0 since there * are no other timers available. */ void -cpu_initclocks() +cpu_initclocks(void) { - if (clockfns == NULL) - panic("cpu_initclocks: no clock attached"); + uint64_t pcc_freq; - tick = 1000000 / hz; /* number of microseconds between interrupts */ - tickfix = 1000000 - (hz * tick); - if (tickfix) { - int ftp; - - ftp = min(ffs(tickfix), ffs(hz)); - tickfix >>= (ftp - 1); - tickfixinterval = hz >> (ftp - 1); - } + if (clock_init == NULL) + panic("cpu_initclocks: no clock attached"); /* * Establish the clock interrupt; it's a special case. @@ -182,9 +137,15 @@ schedhz = 16; /* + * Initialize PCC timecounter. + */ + pcc_freq = cpu_frequency(curcpu()); + cc_init(pcc_freq, "PCC", PCC_QUAL); + + /* * Get the clock started. */ - (*clockfns->cf_init)(clockdev); + (*clock_init)(clockdev); } /* @@ -199,123 +160,3 @@ /* nothing we can do */ } - -/* - * Initialize the time of day register, based on the time base which is, e.g. - * from a filesystem. Base provides the time to within six months, - * and the time of year clock (if any) provides the rest. - */ -void -inittodr(base) - time_t base; -{ - struct clocktime ct; - int year; - struct clock_ymdhms dt; - time_t deltat; - int badbase; - - if (base < (MINYEAR-1970)*SECYR) { - printf("WARNING: preposterous time in file system"); - /* read the system clock anyway */ - base = (MINYEAR-1970)*SECYR; - badbase = 1; - } else - badbase = 0; - - (*clockfns->cf_get)(clockdev, base, &ct); -#ifdef DEBUG - printf("readclock: %d/%d/%d/%d/%d/%d", ct.year, ct.mon, ct.day, - ct.hour, ct.min, ct.sec); -#endif - clockinitted = 1; - - year = 1900 + UNIX_YEAR_OFFSET + ct.year; - if (year < 1970) - year += 100; - /* simple sanity checks (2037 = time_t overflow) */ - if (year < MINYEAR || year > 2037 || - ct.mon < 1 || ct.mon > 12 || ct.day < 1 || - ct.day > 31 || ct.hour > 23 || ct.min > 59 || ct.sec > 59) { - /* - * Believe the time in the file system for lack of - * anything better, resetting the TODR. - */ - time.tv_sec = base; - if (!badbase) { - printf("WARNING: preposterous clock chip time\n"); - resettodr(); - } - goto bad; - } - - dt.dt_year = year; - dt.dt_mon = ct.mon; - dt.dt_day = ct.day; - dt.dt_hour = ct.hour; - dt.dt_min = ct.min; - dt.dt_sec = ct.sec; - time.tv_sec = clock_ymdhms_to_secs(&dt); -#ifdef DEBUG - printf("=>%ld (%d)\n", time.tv_sec, base); -#endif - cc_microset_time = time; - cc_microset(curcpu()); - - if (!badbase) { - /* - * See if we gained/lost two or more days; - * if so, assume something is amiss. - */ - deltat = time.tv_sec - base; - if (deltat < 0) - deltat = -deltat; - if (deltat < 2 * SECDAY) - return; - printf("WARNING: clock %s %ld days", - time.tv_sec < base ? "lost" : "gained", - (long)deltat / SECDAY); - } -bad: - printf(" -- CHECK AND RESET THE DATE!\n"); -} - -/* - * Reset the TODR based on the time value; used when the TODR - * has a preposterous value and also when the time is reset - * by the stime system call. Also called when the TODR goes past - * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) - * to wrap the TODR around. - */ -void -resettodr() -{ - struct clock_ymdhms dt; - struct clocktime ct; - - if (!clockinitted) - return; - - cc_microset_time = time; -#if defined(MULTIPROCESSOR) - alpha_multicast_ipi(cpus_running, ALPHA_IPI_MICROSET); -#endif - cc_microset(curcpu()); - - clock_secs_to_ymdhms(time.tv_sec, &dt); - - /* rt clock wants 2 digits */ - ct.year = (dt.dt_year - UNIX_YEAR_OFFSET) % 100; - ct.mon = dt.dt_mon; - ct.day = dt.dt_day; - ct.hour = dt.dt_hour; - ct.min = dt.dt_min; - ct.sec = dt.dt_sec; - ct.dow = dt.dt_wday; -#ifdef DEBUG - printf("setclock: %d/%d/%d/%d/%d/%d\n", ct.year, ct.mon, ct.day, - ct.hour, ct.min, ct.sec); -#endif - - (*clockfns->cf_set)(clockdev, &ct); -} Index: arch/alpha/alpha/cpu.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/alpha/cpu.c,v retrieving revision 1.75 diff -u -r1.75 cpu.c --- arch/alpha/alpha/cpu.c 18 May 2007 02:45:18 -0000 1.75 +++ arch/alpha/alpha/cpu.c 7 Jul 2007 21:06:32 -0000 @@ -284,6 +284,7 @@ #endif ci->ci_cpuid = ma->ma_slot; ci->ci_softc = sc; + ci->ci_pcc_freq = hwrpb->rpb_cc_freq; /* * Though we could (should?) attach the LCA cpus' PCI @@ -562,7 +563,7 @@ ALPHA_TBIA(); alpha_pal_imb(); - cc_microset(ci); + cc_calibrate_cpu(ci); /* Initialize our base "runtime". */ microtime(&ci->ci_schedstate.spc_runtime); Index: arch/alpha/alpha/interrupt.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/alpha/interrupt.c,v retrieving revision 1.73 diff -u -r1.73 interrupt.c --- arch/alpha/alpha/interrupt.c 17 May 2007 14:51:11 -0000 1.73 +++ arch/alpha/alpha/interrupt.c 7 Jul 2007 21:06:32 -0000 @@ -206,7 +206,6 @@ interrupt(unsigned long a0, unsigned long a1, unsigned long a2, struct trapframe *framep) { - static int microset_iter; /* call cc_microset() once per sec. */ struct cpu_info *ci = curcpu(); struct cpu_softc *sc = ci->ci_softc; @@ -240,23 +239,6 @@ */ sc->sc_evcnt_clock.ev_count++; uvmexp.intrs++; - /* - * Update the PCC frequency for use by microtime(). - */ - if ( -#if defined(MULTIPROCESSOR) - CPU_IS_PRIMARY(ci) && -#endif - - microset_iter-- == 0) { - microset_iter = hz - 1; - cc_microset_time = time; -#if defined(MULTIPROCESSOR) - alpha_multicast_ipi(cpus_running, - ALPHA_IPI_MICROSET); -#endif - cc_microset(ci); - } if (platform.clockintr) { /* * Call hardclock(). This will also call Index: arch/alpha/alpha/ipifuncs.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/alpha/ipifuncs.c,v retrieving revision 1.35 diff -u -r1.35 ipifuncs.c --- arch/alpha/alpha/ipifuncs.c 17 May 2007 14:51:12 -0000 1.35 +++ arch/alpha/alpha/ipifuncs.c 7 Jul 2007 21:06:32 -0000 @@ -257,7 +257,7 @@ alpha_ipi_microset(struct cpu_info *ci, struct trapframe *framep) { - cc_microset(ci); + cc_calibrate_cpu(ci); } void Index: arch/alpha/alpha/mcclock.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/alpha/mcclock.c,v retrieving revision 1.10 diff -u -r1.10 mcclock.c --- arch/alpha/alpha/mcclock.c 12 Jan 1998 10:21:04 -0000 1.10 +++ arch/alpha/alpha/mcclock.c 7 Jul 2007 21:06:32 -0000 @@ -31,106 +31,106 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 1.10 1998/01/12 10:21:04 thorpej Exp $"); +#include "opt_clock_compat_osf1.h" + #include #include #include #include -#include -#include +#include +#include + +#include + #include +#include + +#include +#include + +#ifdef CLOCK_COMPAT_OSF1 +/* + * According to OSF/1's /usr/sys/include/arch/alpha/clock.h, + * the console adjusts the RTC years 13..19 to 93..99 and + * 20..40 to 00..20. (historical reasons?) + * DEC Unix uses an offset to the year to stay outside + * the dangerous area for the next couple of years. + */ +#define UNIX_YEAR_OFFSET 52 /* 41=>1993, 12=>2064 */ +#else +#define UNIX_YEAR_OFFSET 0 +#endif + -void mcclock_init __P((struct device *)); -void mcclock_get __P((struct device *, time_t, struct clocktime *)); -void mcclock_set __P((struct device *, struct clocktime *)); - -const struct clockfns mcclock_clockfns = { - mcclock_init, mcclock_get, mcclock_set, -}; - -#define mc146818_write(dev, reg, datum) \ - (*(dev)->sc_busfns->mc_bf_write)(dev, reg, datum) -#define mc146818_read(dev, reg) \ - (*(dev)->sc_busfns->mc_bf_read)(dev, reg) +static void mcclock_set_pcc_freq(struct mc146818_softc *); +static void mcclock_init(void *); void -mcclock_attach(sc, busfns) - struct mcclock_softc *sc; - const struct mcclock_busfns *busfns; +mcclock_attach(struct mc146818_softc *sc) { - printf(": mc146818 or compatible"); + sc->sc_year0 = 1900 + UNIX_YEAR_OFFSET; + sc->sc_flag = 0; /* BINARY, 24HR */ - sc->sc_busfns = busfns; + mc146818_attach(sc); + + aprint_normal("\n"); /* Turn interrupts off, just in case. */ - mc146818_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR); + (*sc->sc_mcwrite)(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR); + + mcclock_set_pcc_freq(sc); - clockattach(&sc->sc_dev, &mcclock_clockfns); + todr_attach(&sc->sc_handle); + clockattach(mcclock_init, (void *)sc); } -void -mcclock_init(dev) - struct device *dev; +static void +mcclock_set_pcc_freq(struct mc146818_softc *sc) { - struct mcclock_softc *sc = (struct mcclock_softc *)dev; + struct cpu_info *ci; + int64_t freq; + uint32_t pcc_start, pcc_count; + uint8_t reg_a; - mc146818_write(sc, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz); - mc146818_write(sc, MC_REGB, - MC_REGB_PIE | MC_REGB_SQWE | MC_REGB_BINARY | MC_REGB_24HR); -} + /* save REG_A */ + reg_a = (*sc->sc_mcread)(sc, MC_REGA); -/* - * Get the time of day, based on the clock's value and/or the base value. - */ -void -mcclock_get(dev, base, ct) - struct device *dev; - time_t base; - struct clocktime *ct; -{ - struct mcclock_softc *sc = (struct mcclock_softc *)dev; - mc_todregs regs; - int s; - - s = splclock(); - MC146818_GETTOD(sc, ®s) - splx(s); - - ct->sec = regs[MC_SEC]; - ct->min = regs[MC_MIN]; - ct->hour = regs[MC_HOUR]; - ct->dow = regs[MC_DOW]; - ct->day = regs[MC_DOM]; - ct->mon = regs[MC_MONTH]; - ct->year = regs[MC_YEAR]; + /* set interval 16Hz to measure pcc */ + (*sc->sc_mcwrite)(sc, MC_REGA, MC_BASE_32_KHz | MC_RATE_16_Hz); + + /* clear interrupt flags */ + (void)(*sc->sc_mcread)(sc, MC_REGC); + + /* wait till the periodic interupt flag is set */ + while (((*sc->sc_mcread)(sc, MC_REGC) & MC_REGC_PF) == 0) + ; + pcc_start = cpu_counter32(); + + /* wait till the periodic interupt flag is set again */ + while (((*sc->sc_mcread)(sc, MC_REGC) & MC_REGC_PF) == 0) + ; + + pcc_count = cpu_counter32() - pcc_start; + + freq = pcc_count * 16; + + /* restore REG_A */ + (*sc->sc_mcwrite)(sc, MC_REGA, reg_a); + + /* XXX assume all processors have the same clock and frequency */ + for (ci = &cpu_info_primary; ci; ci = ci->ci_next) + ci->ci_pcc_freq = freq; } -/* - * Reset the TODR based on the time value. - */ -void -mcclock_set(dev, ct) - struct device *dev; - struct clocktime *ct; +static void +mcclock_init(void *dev) { - struct mcclock_softc *sc = (struct mcclock_softc *)dev; - mc_todregs regs; - int s; - - s = splclock(); - MC146818_GETTOD(sc, ®s); - splx(s); - - regs[MC_SEC] = ct->sec; - regs[MC_MIN] = ct->min; - regs[MC_HOUR] = ct->hour; - regs[MC_DOW] = ct->dow; - regs[MC_DOM] = ct->day; - regs[MC_MONTH] = ct->mon; - regs[MC_YEAR] = ct->year; - - s = splclock(); - MC146818_PUTTOD(sc, ®s); - splx(s); + struct mc146818_softc *sc = dev; + + /* enable interval clock interrupt */ + (*sc->sc_mcwrite)(sc, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz); + (*sc->sc_mcwrite)(sc, MC_REGB, + MC_REGB_PIE | MC_REGB_SQWE | MC_REGB_BINARY | MC_REGB_24HR); } Index: arch/alpha/conf/files.alpha =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/conf/files.alpha,v retrieving revision 1.173 diff -u -r1.173 files.alpha --- arch/alpha/conf/files.alpha 7 Jul 2007 05:13:14 -0000 1.173 +++ arch/alpha/conf/files.alpha 7 Jul 2007 21:06:32 -0000 @@ -392,7 +392,7 @@ # Devices that can live on multiple busses # -device mcclock +device mcclock: mc146818 attach mcclock at ioasic with mcclock_ioasic attach mcclock at isa with mcclock_isa attach mcclock at gbus with mcclock_tlsb @@ -415,7 +415,6 @@ file arch/alpha/alpha/machdep.c file arch/alpha/alpha/mainbus.c file arch/alpha/alpha/mem.c -file kern/kern_microtime.c file arch/alpha/alpha/pmap.c file arch/alpha/alpha/process_machdep.c file arch/alpha/alpha/procfs_machdep.c procfs @@ -429,6 +428,7 @@ file arch/alpha/common/bus_dma.c file arch/alpha/common/comlogout.c file dev/cons.c +file kern/kern_cctr.c # Network protocol checksum routines file arch/alpha/alpha/in_cksum.c inet Index: arch/alpha/include/cpu.h =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/include/cpu.h,v retrieving revision 1.70 diff -u -r1.70 cpu.h --- arch/alpha/include/cpu.h 19 May 2007 17:09:35 -0000 1.70 +++ arch/alpha/include/cpu.h 7 Jul 2007 21:06:33 -0000 @@ -129,7 +129,7 @@ #ifdef _KERNEL #include -#include +#include #include /* @@ -152,7 +152,7 @@ */ struct lwp *ci_curlwp; /* current owner of the processor */ struct cpu_data ci_data; /* MI per-cpu data */ - struct cc_microtime_state ci_cc;/* cc_microtime state */ + struct cctr_state ci_cc; /* cycle counter state */ struct cpu_info *ci_next; /* next cpu_info structure */ int ci_mtx_count; int ci_mtx_oldspl; @@ -166,6 +166,7 @@ u_long ci_want_resched; /* preempt current process */ u_long ci_intrdepth; /* interrupt trap depth */ struct trapframe *ci_db_regs; /* registers for debuggers */ + uint64_t ci_pcc_freq; /* cpu cycles/second */ #if defined(MULTIPROCESSOR) volatile u_long ci_flags; /* flags; see below */ @@ -296,7 +297,6 @@ struct trapframe; int badaddr(void *, size_t); -#define microtime(tv) cc_microtime(tv) #define cpu_idle() /* nothing */ Index: arch/alpha/include/cpu_counter.h =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/include/cpu_counter.h,v retrieving revision 1.3 diff -u -r1.3 cpu_counter.h --- arch/alpha/include/cpu_counter.h 16 Feb 2006 20:17:13 -0000 1.3 +++ arch/alpha/include/cpu_counter.h 7 Jul 2007 21:06:33 -0000 @@ -48,6 +48,9 @@ #include #include +#define cc_calibrate_mp(ci) \ + alpha_multicast_ipi(cpus_running, ALPHA_IPI_MICROSET) + /* Process Cycle Counter is always available. */ #define cpu_hascounter() (1) #define cpu_counter() cpu_counter32() @@ -68,7 +71,7 @@ cpu_frequency(struct cpu_info *ci) { - return (hwrpb->rpb_cc_freq); + return (ci->ci_pcc_freq); } #endif /* _KERNEL */ Index: arch/alpha/include/types.h =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/include/types.h,v retrieving revision 1.35 diff -u -r1.35 types.h --- arch/alpha/include/types.h 3 Sep 2006 13:51:23 -0000 1.35 +++ arch/alpha/include/types.h 7 Jul 2007 21:06:33 -0000 @@ -66,6 +66,8 @@ #define __HAVE_SYSCALL_INTERN #define __HAVE_MINIMAL_EMUL #define __HAVE_AST_PERPROC +#define __HAVE_GENERIC_TODR +#define __HAVE_TIMECOUNTER #if defined(_KERNEL) #define __HAVE_RAS Index: arch/alpha/isa/mcclock_isa.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/isa/mcclock_isa.c,v retrieving revision 1.15 diff -u -r1.15 mcclock_isa.c --- arch/alpha/isa/mcclock_isa.c 11 Dec 2005 12:16:16 -0000 1.15 +++ arch/alpha/isa/mcclock_isa.c 7 Jul 2007 21:06:33 -0000 @@ -38,36 +38,25 @@ #include -#include -#include +#include + #include +#include #include -struct mcclock_isa_softc { - struct mcclock_softc sc_mcclock; - - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; -}; +#include -int mcclock_isa_match __P((struct device *, struct cfdata *, void *)); -void mcclock_isa_attach __P((struct device *, struct device *, void *)); +int mcclock_isa_match(struct device *, struct cfdata *, void *); +void mcclock_isa_attach(struct device *, struct device *, void *); -CFATTACH_DECL(mcclock_isa, sizeof (struct mcclock_isa_softc), +CFATTACH_DECL(mcclock_isa, sizeof(struct mc146818_softc), mcclock_isa_match, mcclock_isa_attach, NULL, NULL); -void mcclock_isa_write __P((struct mcclock_softc *, u_int, u_int)); -u_int mcclock_isa_read __P((struct mcclock_softc *, u_int)); - -const struct mcclock_busfns mcclock_isa_busfns = { - mcclock_isa_write, mcclock_isa_read, -}; +void mcclock_isa_write(struct mc146818_softc *, u_int, u_int); +u_int mcclock_isa_read(struct mc146818_softc *, u_int); int -mcclock_isa_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +mcclock_isa_match(struct device *parent, struct cfdata *match, void *aux) { struct isa_attach_args *ia = aux; bus_space_handle_t ioh; @@ -106,42 +95,37 @@ } void -mcclock_isa_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +mcclock_isa_attach(struct device *parent, struct device *self, void *aux) { struct isa_attach_args *ia = aux; - struct mcclock_isa_softc *sc = (struct mcclock_isa_softc *)self; + struct mc146818_softc *sc = (void *)self; - sc->sc_iot = ia->ia_iot; - if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, - ia->ia_io[0].ir_size, 0, &sc->sc_ioh)) + sc->sc_bst = ia->ia_iot; + if (bus_space_map(sc->sc_bst, ia->ia_io[0].ir_addr, + ia->ia_io[0].ir_size, 0, &sc->sc_bsh)) panic("mcclock_isa_attach: couldn't map clock I/O space"); - mcclock_attach(&sc->sc_mcclock, &mcclock_isa_busfns); + sc->sc_mcread = mcclock_isa_read; + sc->sc_mcwrite = mcclock_isa_write; + + mcclock_attach(sc); } void -mcclock_isa_write(mcsc, reg, datum) - struct mcclock_softc *mcsc; - u_int reg, datum; +mcclock_isa_write(struct mc146818_softc *sc, u_int reg, u_int datum) { - struct mcclock_isa_softc *sc = (struct mcclock_isa_softc *)mcsc; - bus_space_tag_t iot = sc->sc_iot; - bus_space_handle_t ioh = sc->sc_ioh; + bus_space_tag_t iot = sc->sc_bst; + bus_space_handle_t ioh = sc->sc_bsh; bus_space_write_1(iot, ioh, 0, reg); bus_space_write_1(iot, ioh, 1, datum); } u_int -mcclock_isa_read(mcsc, reg) - struct mcclock_softc *mcsc; - u_int reg; +mcclock_isa_read(struct mc146818_softc *sc, u_int reg) { - struct mcclock_isa_softc *sc = (struct mcclock_isa_softc *)mcsc; - bus_space_tag_t iot = sc->sc_iot; - bus_space_handle_t ioh = sc->sc_ioh; + bus_space_tag_t iot = sc->sc_bst; + bus_space_handle_t ioh = sc->sc_bsh; bus_space_write_1(iot, ioh, 0, reg); return bus_space_read_1(iot, ioh, 1); Index: arch/alpha/jensenio/mcclock_jensenio.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/jensenio/mcclock_jensenio.c,v retrieving revision 1.4 diff -u -r1.4 mcclock_jensenio.c --- arch/alpha/jensenio/mcclock_jensenio.c 2 Oct 2002 04:06:38 -0000 1.4 +++ arch/alpha/jensenio/mcclock_jensenio.c 7 Jul 2007 21:06:33 -0000 @@ -74,18 +74,17 @@ #include -#include -#include +#include + #include +#include #include #include #include +#include struct mcclock_jensenio_softc { - struct mcclock_softc sc_mcclock; - - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; + struct mc146818_softc sc_mc146818; bus_space_handle_t sc_std_rtc_ioh; }; @@ -96,12 +95,9 @@ CFATTACH_DECL(mcclock_jensenio, sizeof (struct mcclock_jensenio_softc), mcclock_jensenio_match, mcclock_jensenio_attach, NULL, NULL); -void mcclock_jensenio_write(struct mcclock_softc *, u_int, u_int); -u_int mcclock_jensenio_read(struct mcclock_softc *, u_int); +void mcclock_jensenio_write(struct mc146818_softc *, u_int, u_int); +u_int mcclock_jensenio_read(struct mc146818_softc *, u_int); -const struct mcclock_busfns mcclock_jensenio_busfns = { - mcclock_jensenio_write, mcclock_jensenio_read, -}; int mcclock_jensenio_match(struct device *parent, struct cfdata *match, void *aux) @@ -119,40 +115,42 @@ mcclock_jensenio_attach(struct device *parent, struct device *self, void *aux) { struct jensenio_attach_args *ja = aux; - struct mcclock_jensenio_softc *sc = (void *) self; + struct mcclock_jensenio_softc *jsc = (void *)self; + struct mc146818_softc *sc = &jsc->sc_mc146818; - sc->sc_iot = ja->ja_iot; - if (bus_space_map(sc->sc_iot, ja->ja_ioaddr, 0x02, 0, - &sc->sc_ioh)) + sc->sc_bst = ja->ja_iot; + if (bus_space_map(sc->sc_bst, ja->ja_ioaddr, 0x02, 0, + &sc->sc_bsh)) panic("mcclock_jensenio_attach: couldn't map clock I/O space"); /* * Map the I/O space normally used by the ISA RTC (port 0x70) so * as to avoid a false match at that address, as well. */ - (void) bus_space_map(sc->sc_iot, 0x70, 0x02, 0, - &sc->sc_std_rtc_ioh); + (void)bus_space_map(sc->sc_bst, 0x70, 0x02, 0, + &jsc->sc_std_rtc_ioh); + + sc->sc_mcread = mcclock_jensenio_read; + sc->sc_mcwrite = mcclock_jensenio_write; - mcclock_attach(&sc->sc_mcclock, &mcclock_jensenio_busfns); + mcclock_attach(sc); } void -mcclock_jensenio_write(struct mcclock_softc *mcsc, u_int reg, u_int datum) +mcclock_jensenio_write(struct mc146818_softc *sc, u_int reg, u_int datum) { - struct mcclock_jensenio_softc *sc = (void *) mcsc; - bus_space_tag_t iot = sc->sc_iot; - bus_space_handle_t ioh = sc->sc_ioh; + bus_space_tag_t iot = sc->sc_bst; + bus_space_handle_t ioh = sc->sc_bsh; bus_space_write_1(iot, ioh, 0, reg); bus_space_write_1(iot, ioh, 1, datum); } u_int -mcclock_jensenio_read(struct mcclock_softc *mcsc, u_int reg) +mcclock_jensenio_read(struct mc146818_softc *sc, u_int reg) { - struct mcclock_jensenio_softc *sc = (void *) mcsc; - bus_space_tag_t iot = sc->sc_iot; - bus_space_handle_t ioh = sc->sc_ioh; + bus_space_tag_t iot = sc->sc_bst; + bus_space_handle_t ioh = sc->sc_bsh; bus_space_write_1(iot, ioh, 0, reg); return bus_space_read_1(iot, ioh, 1); Index: arch/alpha/pci/a12c.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/pci/a12c.c,v retrieving revision 1.16 diff -u -r1.16 a12c.c --- arch/alpha/pci/a12c.c 11 Dec 2005 12:16:17 -0000 1.16 +++ arch/alpha/pci/a12c.c 7 Jul 2007 21:06:33 -0000 @@ -53,10 +53,11 @@ #include #include -#include #include #include +#include + #include #include #include @@ -127,7 +128,6 @@ struct a12c_softc *sc = (struct a12c_softc *)self; struct a12c_config *ccp; struct pcibus_attach_args pba; - extern const struct clockfns *clockfns; /* XXX? */ /* note that we've attached the chipset; can't have 2 A12Cs. */ a12cfound = 1; @@ -145,7 +145,7 @@ A12_ALL_EXTRACT(REGVAL(A12_VERS))); pci_a12_pickintr(ccp); - clockfns = &noclock_fns; /* XXX? */ + clockattach(noclock_init, NULL); /* XXX? */ memset(&pba, 0, sizeof(pba)); pba.pba_iot = 0; @@ -167,19 +167,8 @@ config_found_ia(self, "a12c_a12dc", &pba, NULL); } -static void noclock_init(struct device *dev) { - dev = dev; -} - -static void -noclock_get(struct device *dev, time_t t, struct clocktime *ct) +static void noclock_init(void (*)(void *), void *) { - *ct = zeroct; -} -static void -noclock_set(struct device *dev, struct clocktime *ct) -{ - if(dev!=NULL) - *ct = *ct; + /* nothing */ } Index: arch/alpha/tc/mcclock_ioasic.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/tc/mcclock_ioasic.c,v retrieving revision 1.11 diff -u -r1.11 mcclock_ioasic.c --- arch/alpha/tc/mcclock_ioasic.c 2 Oct 2002 04:06:40 -0000 1.11 +++ arch/alpha/tc/mcclock_ioasic.c 7 Jul 2007 21:06:33 -0000 @@ -36,41 +36,39 @@ #include #include -#include -#include +#include + +#include + #include +#include #include #include /* XXX */ +#include + struct mcclock_ioasic_clockdatum { u_char datum; char pad[3]; }; struct mcclock_ioasic_softc { - struct mcclock_softc sc_mcclock; + struct mc146818_softc sc_mc146818; struct mcclock_ioasic_clockdatum *sc_dp; }; -int mcclock_ioasic_match __P((struct device *, struct cfdata *, void *)); -void mcclock_ioasic_attach __P((struct device *, struct device *, void *)); +int mcclock_ioasic_match(struct device *, struct cfdata *, void *); +void mcclock_ioasic_attach(struct device *, struct device *, void *); -CFATTACH_DECL(mcclock_ioasic, sizeof (struct mcclock_ioasic_softc), +CFATTACH_DECL(mcclock_ioasic, sizeof(struct mcclock_ioasic_softc), mcclock_ioasic_match, mcclock_ioasic_attach, NULL, NULL); -void mcclock_ioasic_write __P((struct mcclock_softc *, u_int, u_int)); -u_int mcclock_ioasic_read __P((struct mcclock_softc *, u_int)); - -const struct mcclock_busfns mcclock_ioasic_busfns = { - mcclock_ioasic_write, mcclock_ioasic_read, -}; +void mcclock_ioasic_write(struct mc146818_softc *, u_int, u_int); +u_int mcclock_ioasic_read(struct mc146818_softc *, u_int); int -mcclock_ioasic_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +mcclock_ioasic_match(struct device *parent, struct cfdata *match, void *aux) { struct ioasicdev_attach_args *d = aux; @@ -81,34 +79,34 @@ } void -mcclock_ioasic_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +mcclock_ioasic_attach(struct device *parent, struct device *self, void *aux) { struct ioasicdev_attach_args *ioasicdev = aux; - struct mcclock_ioasic_softc *sc = (struct mcclock_ioasic_softc *)self; + struct mcclock_ioasic_softc *isc = (void *)self; + struct mc146818_softc *sc = &isc->sc_mc146818; + + /* XXX no bus_space(9) for TURBOchannel yet */ + isc->sc_dp = (void *)ioasicdev->iada_addr; - sc->sc_dp = (struct mcclock_ioasic_clockdatum *)ioasicdev->iada_addr; + sc->sc_mcread = mcclock_ioasic_read; + sc->sc_mcwrite = mcclock_ioasic_write; - mcclock_attach(&sc->sc_mcclock, &mcclock_ioasic_busfns); + /* call alpha common mcclock attachment */ + mcclock_attach(sc); } void -mcclock_ioasic_write(dev, reg, datum) - struct mcclock_softc *dev; - u_int reg, datum; +mcclock_ioasic_write(struct mc146818_softc *sc, u_int reg, u_int datum) { - struct mcclock_ioasic_softc *sc = (struct mcclock_ioasic_softc *)dev; + struct mcclock_ioasic_softc *isc = (void *)sc; - sc->sc_dp[reg].datum = datum; + isc->sc_dp[reg].datum = datum; } u_int -mcclock_ioasic_read(dev, reg) - struct mcclock_softc *dev; - u_int reg; +mcclock_ioasic_read(struct mc146818_softc *sc, u_int reg) { - struct mcclock_ioasic_softc *sc = (struct mcclock_ioasic_softc *)dev; + struct mcclock_ioasic_softc *isc = (void *)sc; - return (sc->sc_dp[reg].datum); + return isc->sc_dp[reg].datum; } Index: arch/alpha/tlsb/mcclock_tlsb.c =================================================================== RCS file: /cvsroot/src/sys/arch/alpha/tlsb/mcclock_tlsb.c,v retrieving revision 1.12 diff -u -r1.12 mcclock_tlsb.c --- arch/alpha/tlsb/mcclock_tlsb.c 4 Mar 2007 05:59:12 -0000 1.12 +++ arch/alpha/tlsb/mcclock_tlsb.c 7 Jul 2007 21:06:33 -0000 @@ -41,14 +41,18 @@ #include -#include -#include - #include #include /* XXX */ +#include + #include +#include + +#include + +#include "ioconf.h" #define KV(_addr) ((void *)ALPHA_PHYS_TO_K0SEG((_addr))) /* @@ -57,69 +61,62 @@ #define REGSHIFT 6 struct mcclock_tlsb_softc { - struct mcclock_softc sc_mcclock; + struct mc146818_softc sc_mc146818; unsigned long regbase; }; -int mcclock_tlsb_match __P((struct device *, struct cfdata *, void *)); -void mcclock_tlsb_attach __P((struct device *, struct device *, void *)); +int mcclock_tlsb_match(struct device *, struct cfdata *, void *); +void mcclock_tlsb_attach(struct device *, struct device *, void *); CFATTACH_DECL(mcclock_tlsb, sizeof (struct mcclock_tlsb_softc), mcclock_tlsb_match, mcclock_tlsb_attach, NULL, NULL); -extern struct cfdriver mcclock_cd; - -static void mcclock_tlsb_write __P((struct mcclock_softc *, u_int, u_int)); -static u_int mcclock_tlsb_read __P((struct mcclock_softc *, u_int)); +static void mcclock_tlsb_write(struct mc146818_softc *, u_int, u_int); +static u_int mcclock_tlsb_read(struct mc146818_softc *, u_int); -const struct mcclock_busfns mcclock_tlsb_busfns = { - mcclock_tlsb_write, mcclock_tlsb_read, -}; int -mcclock_tlsb_match(parent, match, aux) - struct device *parent; - struct cfdata *match; - void *aux; +mcclock_tlsb_match(struct device *parent, struct cfdata *match, void *aux) { struct gbus_attach_args *ga = aux; + if (strcmp(ga->ga_name, mcclock_cd.cd_name)) return (0); return (1); } void -mcclock_tlsb_attach(parent, self, aux) - struct device *parent, *self; - void *aux; +mcclock_tlsb_attach(struct device *parent, struct device *self, void *aux) { - struct mcclock_tlsb_softc *sc = (struct mcclock_tlsb_softc *)self; struct gbus_attach_args *ga = aux; + struct mcclock_tlsb_softc *tsc = (void *)self; + struct mc146818_softc *sc = &tsc->sc_mc146818; /* XXX Should be bus.h'd, so we can accommodate the kn7aa. */ - sc->regbase = TLSB_GBUS_BASE + ga->ga_offset; + tsc->regbase = TLSB_GBUS_BASE + ga->ga_offset; + + sc->sc_mcread = mcclock_tlsb_read; + sc->sc_mcwrite = mcclock_tlsb_write; - mcclock_attach(&sc->sc_mcclock, &mcclock_tlsb_busfns); + mcclock_attach(sc); } static void -mcclock_tlsb_write(mcsc, reg, val) - struct mcclock_softc *mcsc; - u_int reg, val; +mcclock_tlsb_write(struct mc146818_softc *sc, u_int reg, u_int val) { - struct mcclock_tlsb_softc *sc = (struct mcclock_tlsb_softc *)mcsc; + struct mcclock_tlsb_softc *tsc = (void *)sc; unsigned char *ptr = (unsigned char *) - KV(sc->regbase + (reg << REGSHIFT)); + KV(tsc->regbase + (reg << REGSHIFT)); + *ptr = val; } static u_int -mcclock_tlsb_read(mcsc, reg) - struct mcclock_softc *mcsc; - u_int reg; +mcclock_tlsb_read(struct mc146818_softc *sc, u_int reg) { - struct mcclock_tlsb_softc *sc = (struct mcclock_tlsb_softc *)mcsc; + struct mcclock_tlsb_softc *tsc = (void *)sc; unsigned char *ptr = (unsigned char *) - KV(sc->regbase + (reg << REGSHIFT)); + KV(tsc->regbase + (reg << REGSHIFT)); + return *ptr; } Index: arch/amd64/amd64/ipifuncs.c =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/amd64/ipifuncs.c,v retrieving revision 1.9 diff -u -r1.9 ipifuncs.c --- arch/amd64/amd64/ipifuncs.c 21 Mar 2007 06:36:43 -0000 1.9 +++ arch/amd64/amd64/ipifuncs.c 7 Jul 2007 21:06:33 -0000 @@ -83,7 +83,7 @@ void (*ipifunc[X86_NIPI])(struct cpu_info *) = { x86_64_ipi_halt, - tsc_calibrate_cpu, + cc_calibrate_cpu, x86_64_ipi_flush_fpu, x86_64_ipi_synch_fpu, pmap_do_tlb_shootdown, Index: arch/amd64/conf/files.amd64 =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/conf/files.amd64,v retrieving revision 1.40 diff -u -r1.40 files.amd64 --- arch/amd64/conf/files.amd64 7 Jul 2007 05:13:14 -0000 1.40 +++ arch/amd64/conf/files.amd64 7 Jul 2007 21:06:33 -0000 @@ -141,6 +141,7 @@ file arch/x86/isa/clock.c isa # TSC timecounter support +file kern/kern_cctr.c file arch/x86/x86/tsc.c # attribute used to represent the "keyboard controller" Index: arch/amd64/include/cpu.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/cpu.h,v retrieving revision 1.24 diff -u -r1.24 cpu.h --- arch/amd64/include/cpu.h 21 May 2007 08:10:39 -0000 1.24 +++ arch/amd64/include/cpu.h 7 Jul 2007 21:06:33 -0000 @@ -55,14 +55,14 @@ #include #include #include -#include +#include struct cpu_info { struct device *ci_dev; struct cpu_info *ci_self; void *ci_self200; /* self + 0x200, see lock_stubs.S */ struct cpu_data ci_data; /* MI per-cpu data */ - struct cc_microtime_state ci_cc;/* cc_microtime state */ + struct cctr_state ci_cc; /* cycle counter state */ struct cpu_info *ci_next; struct lwp *ci_curlwp; Index: arch/i386/conf/files.i386 =================================================================== RCS file: /cvsroot/src/sys/arch/i386/conf/files.i386,v retrieving revision 1.311 diff -u -r1.311 files.i386 --- arch/i386/conf/files.i386 7 Jul 2007 05:13:15 -0000 1.311 +++ arch/i386/conf/files.i386 7 Jul 2007 21:06:33 -0000 @@ -255,6 +255,7 @@ file arch/x86/isa/clock.c isa # TSC support +file kern/kern_cctr.c i586_cpu | i686_cpu file arch/x86/x86/tsc.c i586_cpu | i686_cpu # Numeric Processing Extension; Math Co-processor Index: arch/i386/i386/ipifuncs.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/i386/ipifuncs.c,v retrieving revision 1.17 diff -u -r1.17 ipifuncs.c --- arch/i386/i386/ipifuncs.c 17 May 2007 14:51:20 -0000 1.17 +++ arch/i386/i386/ipifuncs.c 7 Jul 2007 21:06:33 -0000 @@ -88,7 +88,7 @@ { i386_ipi_halt, #if defined(I586_CPU) || defined(I686_CPU) - tsc_calibrate_cpu, /* keep cycle counters synchronized */ + cc_calibrate_cpu, /* keep cycle counters synchronized */ #else 0, #endif Index: arch/i386/include/cpu.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/cpu.h,v retrieving revision 1.142 diff -u -r1.142 cpu.h --- arch/i386/include/cpu.h 3 Jun 2007 19:32:28 -0000 1.142 +++ arch/i386/include/cpu.h 7 Jul 2007 21:06:34 -0000 @@ -58,7 +58,7 @@ #include #include /* will also get LOCKDEBUG */ #include -#include +#include #include /* offsetof */ @@ -85,7 +85,7 @@ cpuid_t ci_cpuid; /* our CPU ID */ u_int ci_apicid; /* our APIC ID */ struct cpu_data ci_data; /* MI per-cpu data */ - struct cc_microtime_state ci_cc;/* cc_microtime state */ + struct cctr_state ci_cc; /* cycle counter state */ /* * Private members. Index: arch/ia64/conf/files.ia64 =================================================================== RCS file: /cvsroot/src/sys/arch/ia64/conf/files.ia64,v retrieving revision 1.2 diff -u -r1.2 files.ia64 --- arch/ia64/conf/files.ia64 2 Jul 2006 17:23:59 -0000 1.2 +++ arch/ia64/conf/files.ia64 7 Jul 2007 21:06:34 -0000 @@ -44,7 +44,7 @@ file dev/cons.c file dev/cninit.c -# XXX: TODO: file kern/kern_microtime.c +# XXX: TODO: file kern/kern_cctr.c # # System bus types Index: arch/ia64/include/cpu.h =================================================================== RCS file: /cvsroot/src/sys/arch/ia64/include/cpu.h,v retrieving revision 1.2 diff -u -r1.2 cpu.h --- arch/ia64/include/cpu.h 16 Feb 2007 02:53:47 -0000 1.2 +++ arch/ia64/include/cpu.h 7 Jul 2007 21:06:34 -0000 @@ -82,7 +82,7 @@ #ifdef _KERNEL #include -#include +#include #include #include @@ -95,7 +95,7 @@ */ struct lwp *ci_curlwp; /* current owner of the processor */ struct cpu_data ci_data; /* MI per-cpu data */ - struct cc_microtime_state ci_cc;/* cc_microtime state */ + struct cctr_state ci_cc; /* cycle counter state */ struct cpu_info *ci_next; /* next cpu_info structure */ /* XXX: Todo */ @@ -170,10 +170,5 @@ #define cpu_proc_fork(p1, p2) /* XXX: Look into this. */ -/* XXX: TODO: generic microtime support kern/kern_microtime.c - * #define microtime(tv) cc_microtime(tv) - */ - - #endif /* _KERNEL_ */ #endif /* _IA64_CPU_H */ Index: arch/x86/include/cpu_counter.h =================================================================== RCS file: /cvsroot/src/sys/arch/x86/include/cpu_counter.h,v retrieving revision 1.1 diff -u -r1.1 cpu_counter.h --- arch/x86/include/cpu_counter.h 7 Jul 2007 17:38:27 -0000 1.1 +++ arch/x86/include/cpu_counter.h 7 Jul 2007 21:06:34 -0000 @@ -43,6 +43,8 @@ * x86 common functions for CPU counter. */ +#define cc_calibrate_mp(ci) x86_broadcast_ipi(X86_IPI_MICROSET) + static __inline uint64_t cpu_counter(void) { Index: arch/x86/x86/tsc.c =================================================================== RCS file: /cvsroot/src/sys/arch/x86/x86/tsc.c,v retrieving revision 1.10 diff -u -r1.10 tsc.c --- arch/x86/x86/tsc.c 16 Nov 2006 01:32:39 -0000 1.10 +++ arch/x86/x86/tsc.c 7 Jul 2007 21:06:34 -0000 @@ -88,8 +88,6 @@ #include "opt_multiprocessor.h" #ifdef i386 #include "opt_enhanced_speedstep.h" -#endif -#ifdef i386 #include "opt_powernow_k7.h" #endif #include "opt_powernow_k8.h" @@ -100,44 +98,21 @@ #include #include #include -#include #include /* XXX for bootverbose */ #include #include -#include #include +#include uint64_t tsc_freq; u_int tsc_present; int tsc_is_broken = 0; - -static int64_t tsc_cal_val; /* last calibrate time stamp */ - -static timecounter_get_t tsc_get_timecount; -static timecounter_pps_t tsc_calibrate; - -void tsc_calibrate_cpu(struct cpu_info *); - -static struct timecounter tsc_timecounter = { - tsc_get_timecount, /* get_timecount */ - tsc_calibrate, /* once per second - used to calibrate cpu TSC */ - ~0u, /* counter_mask */ - 0, /* frequency */ - "TSC", /* name */ -#if (defined(ENHANCED_SPEEDSTEP) || defined(POWERNOW_K7) || defined(POWERNOW_K8)) - -100, /* don't pick TSC automatically */ - /* if frequency changes might affect TSC */ -#else - 800, /* quality (adjusted in code) */ -#endif - NULL, - NULL, -}; +int tsc_qual = -100000; void init_TSC(void) { - u_int64_t tscval[2]; + uint64_t tscval[2]; if (cpu_feature & CPUID_TSC) tsc_present = 1; @@ -157,6 +132,12 @@ } while (tscval[1] < tscval[0]); tsc_freq = 10 * (tscval[1] - tscval[0]); +#if defined(ENHANCED_SPEEDSTEP) || defined(POWERNOW_K7) || defined(POWERNOW_K8) + tsc_qual = -100; /* don't pick TSC automatically */ + /* if frequency changes might affect TSC */ +#else + tsc_qual = 800; /* quality (adjusted in code) */ +#endif if (bootverbose) printf("TSC clock: %" PRId64 " Hz\n", tsc_freq); } @@ -164,164 +145,8 @@ void init_TSC_tc(void) { - if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { - tsc_timecounter.tc_frequency = tsc_freq; - tc_init(&tsc_timecounter); - } -} - -/* XXX make tsc_timecounter.tc_frequency settable by sysctl() */ - -/* - * pick up tick count scaled to reference tick count - */ -static u_int -tsc_get_timecount(struct timecounter *tc) -{ - struct cpu_info *ci = curcpu(); - int64_t rcc, cc; - u_int gen; - - if (ci->ci_cc.cc_denom == 0) { - /* - * This is our first time here on this CPU. Just - * start with reasonable initial values. - */ - ci->ci_cc.cc_cc = cpu_counter32(); - ci->ci_cc.cc_val = 0; - if (ci->ci_cc.cc_gen == 0) - ci->ci_cc.cc_gen++; - - ci->ci_cc.cc_denom = cpu_frequency(ci); - if (ci->ci_cc.cc_denom == 0) - ci->ci_cc.cc_denom = tsc_freq; - ci->ci_cc.cc_delta = ci->ci_cc.cc_denom; - } - /* read counter and re-read when the re-calibration - strikes inbetween */ - do { - /* pick up current generation number */ - gen = ci->ci_cc.cc_gen; - - /* determine local delta ticks */ - cc = cpu_counter32() - ci->ci_cc.cc_cc; - if (cc < 0) - cc += 0x100000000LL; - - /* scale to primary */ - rcc = (cc * ci->ci_cc.cc_delta) / ci->ci_cc.cc_denom - + ci->ci_cc.cc_val; - } while (gen == 0 || gen != ci->ci_cc.cc_gen); - - return rcc; -} - -/* - * called once per second via the pps callback - * for the calibration of the TSC counters. - * it is called only for the PRIMARY cpu. all - * other cpus are called via a broadcast IPI - */ -static void -tsc_calibrate(struct timecounter *tc) -{ - struct cpu_info *ci = curcpu(); - - /* pick up reference ticks */ - tsc_cal_val = cpu_counter32(); - -#if defined(MULTIPROCESSOR) - x86_broadcast_ipi(X86_IPI_MICROSET); -#endif - - tsc_calibrate_cpu(ci); -} - -/* - * This routine is called about once per second directly by the master - * processor and via an interprocessor interrupt for other processors. - * It determines the CC frequency of each processor relative to the - * master clock and the time this determination is made. These values - * are used by tsc_get_timecount() to interpolate the ticks between - * timer interrupts. Note that we assume the kernel variables have - * been zeroed early in life. - */ -void -tsc_calibrate_cpu(struct cpu_info *ci) -{ - u_int gen; - int64_t val; - int64_t delta, denom; - int s; -#ifdef TIMECOUNTER_DEBUG - int64_t factor, old_factor; -#endif - val = tsc_cal_val; - - s = splhigh(); - /* create next generation number */ - gen = ci->ci_cc.cc_gen; - gen++; - if (gen == 0) - gen++; - /* update in progress */ - ci->ci_cc.cc_gen = 0; - - denom = ci->ci_cc.cc_cc; - ci->ci_cc.cc_cc = cpu_counter32(); - - if (ci->ci_cc.cc_denom == 0) { - /* - * This is our first time here on this CPU. Just - * start with reasonable initial values. - */ - ci->ci_cc.cc_val = val; - ci->ci_cc.cc_denom = cpu_frequency(ci); - if (ci->ci_cc.cc_denom == 0) - ci->ci_cc.cc_denom = tsc_freq; - ci->ci_cc.cc_delta = ci->ci_cc.cc_denom; - ci->ci_cc.cc_gen = gen; - splx(s); - return; + if (tsc_present && tsc_freq != 0 && !tsc_is_broken) { + (void)cc_init(tsc_freq, "TSC", tsc_qual); } - -#ifdef TIMECOUNTER_DEBUG - old_factor = (ci->ci_cc.cc_delta * 1000 ) / ci->ci_cc.cc_denom; -#endif - - /* local ticks per period */ - denom = ci->ci_cc.cc_cc - denom; - if (denom < 0) - denom += 0x100000000LL; - - ci->ci_cc.cc_denom = denom; - - /* reference ticks per period */ - delta = val - ci->ci_cc.cc_val; - if (delta < 0) - delta += 0x100000000LL; - - ci->ci_cc.cc_val = val; - ci->ci_cc.cc_delta = delta; - - /* publish new generation number */ - ci->ci_cc.cc_gen = gen; - splx(s); - -#ifdef TIMECOUNTER_DEBUG - factor = (delta * 1000) / denom - old_factor; - if (factor < 0) - factor = -factor; - - if (factor > old_factor / 10) - printf("tsc_calibrate_cpu[%lu]: 10%% exceeded - delta %" - PRId64 ", denom %" PRId64 ", factor %" PRId64 - ", old factor %" PRId64"\n", ci->ci_cpuid, - delta, denom, (delta * 1000) / denom, old_factor); -#if 0 - printf("tsc_calibrate_cpu[%lu]: delta %" PRId64 - ", denom %" PRId64 ", factor %" PRId64 "\n", ci->ci_cpuid, delta, denom, (delta * 1000) / denom); -#endif -#endif /* TIMECOUNTER_DEBUG */ } --- /dev/null 2007-07-08 06:06:43.000000000 +0900 +++ arch/alpha/alpha/clockvar.h 2006-09-19 21:04:38.000000000 +0900 @@ -0,0 +1,34 @@ +/* $NetBSD: clockvar.h,v 1.8 2005/12/11 12:21:20 christos Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Definitions for CPU-independent clock handling for the alpha + */ + +void clockattach(void (*)(void *), void *); --- /dev/null 2007-07-08 06:06:43.000000000 +0900 +++ arch/alpha/alpha/mcclockvar.h 2006-09-19 21:06:46.000000000 +0900 @@ -0,0 +1,30 @@ +/* $NetBSD: mcclockvar.h,v 1.6 2005/12/11 12:21:20 christos Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +void mcclock_attach(struct mc146818_softc *); --- /dev/null 2007-07-08 06:06:43.000000000 +0900 +++ kern/kern_cctr.c 2007-07-07 20:24:39.000000000 +0900 @@ -0,0 +1,302 @@ +/* $NetBSD$ */ + + +/*- + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * re-implementation of TSC for MP systems merging cc_microtime and + * TSC for timecounters by Frank Kardel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* basic calibration ideas are (kern_microtime.c): */ +/****************************************************************************** + * * + * Copyright (c) David L. Mills 1993, 1994 * + * * + * Permission to use, copy, modify, and distribute this software and its * + * documentation for any purpose and without fee is hereby granted, provided * + * that the above copyright notice appears in all copies and that both the * + * copyright notice and this permission notice appear in supporting * + * documentation, and that the name University of Delaware not be used in * + * advertising or publicity pertaining to distribution of the software * + * without specific, written prior permission. The University of Delaware * + * makes no representations about the suitability this software for any * + * purpose. It is provided "as is" without express or implied warranty. * + * * + ******************************************************************************/ + +/* reminiscents from older version of this file are: */ +/*- + * Copyright (c) 1998-2003 Poul-Henning Kamp + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +/* __FBSDID("$FreeBSD: src/sys/i386/i386/tsc.c,v 1.204 2003/10/21 18:28:34 silby Exp $"); */ +__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.10 2006/11/16 01:32:39 christos Exp $"); + +#include "opt_multiprocessor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* XXX make cc_timecounter.tc_frequency settable by sysctl() */ + +static timecounter_get_t cc_get_timecount; +static timecounter_pps_t cc_calibrate; + +void cc_calibrate_cpu(struct cpu_info *); + +static int64_t cc_cal_val; /* last calibrate time stamp */ + +static struct timecounter cc_timecounter = { + .tc_get_timecount = cc_get_timecount, + .tc_poll_pps = cc_calibrate, + .tc_counter_mask = ~0u, + .tc_frequency = 0, + .tc_name = "unkown cycle counter", + /* + * don't pick cycle counter automatically + * if frequency changes might affect cycle counter + */ + .tc_quality = -100000, + + .tc_priv = NULL, + .tc_next = NULL +}; + +/* + * initialize cycle counter based timecounter + */ +struct timecounter * +cc_init(uint64_t freq, const char *name, int quality) +{ + + cc_timecounter.tc_frequency = freq; + cc_timecounter.tc_name = name; + cc_timecounter.tc_quality = quality; + tc_init(&cc_timecounter); + + return &cc_timecounter; +} + +/* + * pick up tick count scaled to reference tick count + */ +static u_int +cc_get_timecount(struct timecounter *tc) +{ + struct cpu_info *ci = curcpu(); + int64_t rcc, cc; + u_int gen; + + if (ci->ci_cc.cc_denom == 0) { + /* + * This is our first time here on this CPU. Just + * start with reasonable initial values. + */ + ci->ci_cc.cc_cc = cpu_counter32(); + ci->ci_cc.cc_val = 0; + if (ci->ci_cc.cc_gen == 0) + ci->ci_cc.cc_gen++; + + ci->ci_cc.cc_denom = cpu_frequency(ci); + if (ci->ci_cc.cc_denom == 0) + ci->ci_cc.cc_denom = cc_timecounter.tc_frequency; + ci->ci_cc.cc_delta = ci->ci_cc.cc_denom; + } + + /* + * read counter and re-read when the re-calibration + * strikes inbetween + */ + do { + /* pick up current generation number */ + gen = ci->ci_cc.cc_gen; + + /* determine local delta ticks */ + cc = cpu_counter32() - ci->ci_cc.cc_cc; + if (cc < 0) + cc += 0x100000000LL; + + /* scale to primary */ + rcc = (cc * ci->ci_cc.cc_delta) / ci->ci_cc.cc_denom + + ci->ci_cc.cc_val; + } while (gen == 0 || gen != ci->ci_cc.cc_gen); + + return rcc; +} + +/* + * called once per clock tick via the pps callback + * for the calibration of the TSC counters. + * it is called only for the PRIMARY cpu. all + * other cpus are called via a broadcast IPI + * calibration interval is 1 second - we call + * the calobration code only every hz calls + */ +static void +cc_calibrate(struct timecounter *tc) +{ + static int calls; + struct cpu_info *ci; + + /* + * XXX: for high interrupt frequency + * support: ++calls < hz / tc_tick + */ + if (++calls < hz) + return; + + calls = 0; + ci = curcpu(); + /* pick up reference ticks */ + cc_cal_val = cpu_counter32(); + +#if defined(MULTIPROCESSOR) + cc_calibrate_mp(ci); +#endif + cc_calibrate_cpu(ci); +} + +/* + * This routine is called about once per second directly by the master + * processor and via an interprocessor interrupt for other processors. + * It determines the CC frequency of each processor relative to the + * master clock and the time this determination is made. These values + * are used by cc_get_timecount() to interpolate the ticks between + * timer interrupts. Note that we assume the kernel variables have + * been zeroed early in life. + */ +void +cc_calibrate_cpu(struct cpu_info *ci) +{ + u_int gen; + int64_t val; + int64_t delta, denom; + int s; +#ifdef TIMECOUNTER_DEBUG + int64_t factor, old_factor; +#endif + val = cc_cal_val; + + s = splhigh(); + /* create next generation number */ + gen = ci->ci_cc.cc_gen; + gen++; + if (gen == 0) + gen++; + + /* update in progress */ + ci->ci_cc.cc_gen = 0; + + denom = ci->ci_cc.cc_cc; + ci->ci_cc.cc_cc = cpu_counter32(); + + if (ci->ci_cc.cc_denom == 0) { + /* + * This is our first time here on this CPU. Just + * start with reasonable initial values. + */ + ci->ci_cc.cc_val = val; + ci->ci_cc.cc_denom = cpu_frequency(ci); + if (ci->ci_cc.cc_denom == 0) + ci->ci_cc.cc_denom = cc_timecounter.tc_frequency;; + ci->ci_cc.cc_delta = ci->ci_cc.cc_denom; + ci->ci_cc.cc_gen = gen; + splx(s); + return; + } + +#ifdef TIMECOUNTER_DEBUG + old_factor = (ci->ci_cc.cc_delta * 1000 ) / ci->ci_cc.cc_denom; +#endif + + /* local ticks per period */ + denom = ci->ci_cc.cc_cc - denom; + if (denom < 0) + denom += 0x100000000LL; + + ci->ci_cc.cc_denom = denom; + + /* reference ticks per period */ + delta = val - ci->ci_cc.cc_val; + if (delta < 0) + delta += 0x100000000LL; + + ci->ci_cc.cc_val = val; + ci->ci_cc.cc_delta = delta; + + /* publish new generation number */ + ci->ci_cc.cc_gen = gen; + splx(s); + +#ifdef TIMECOUNTER_DEBUG + factor = (delta * 1000) / denom - old_factor; + if (factor < 0) + factor = -factor; + + if (factor > old_factor / 10) + printf("cc_calibrate_cpu[%lu]: 10%% exceeded - delta %" + PRId64 ", denom %" PRId64 ", factor %" PRId64 + ", old factor %" PRId64"\n", ci->ci_cpuid, + delta, denom, (delta * 1000) / denom, old_factor); +#endif /* TIMECOUNTER_DEBUG */ +} --- /dev/null 2007-07-08 06:06:43.000000000 +0900 +++ sys/cctr.h 2007-07-08 05:31:55.000000000 +0900 @@ -0,0 +1,57 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_CCTR_H_ +#define _SYS_CCTR_H_ + +/* + * Variables used by cycle counter in kern_cctr.c. + */ +struct cctr_state { + volatile u_int cc_gen; /* generation number for this data set */ + volatile int64_t cc_val; /* reference CC value at calibration time */ + volatile int64_t cc_cc; /* local CC value at calibration time */ + volatile int64_t cc_delta; /* reference CC difference for + last calibration period */ + volatile int64_t cc_denom; /* local CC difference for + last calibration period */ +}; + +struct cpu_info; + +void cc_calibrate_cpu(struct cpu_info *); +struct timecounter *cc_init(uint64_t, const char *, int); + +#endif /* _SYS_CCTR_H_ */