diff -ruNp sys.prev/conf/files.sparc64 sys/conf/files.sparc64 --- sys.prev/conf/files.sparc64 2010-05-20 20:38:11.000000000 +0300 +++ sys/conf/files.sparc64 2010-07-15 17:55:18.000000000 +0300 @@ -59,6 +59,7 @@ dev/syscons/scterm-teken.c optional sc dev/syscons/scvtb.c optional sc dev/uart/uart_cpu_sparc64.c optional uart dev/uart/uart_kbd_sun.c optional uart sc +kern/kern_clocksource.c standard kern/syscalls.c optional ktr libkern/ffs.c standard libkern/ffsl.c standard diff -ruNp sys.prev/conf/files.sun4v sys/conf/files.sun4v --- sys.prev/conf/files.sun4v 2010-04-26 14:52:42.000000000 +0300 +++ sys/conf/files.sun4v 2010-07-15 21:44:49.000000000 +0300 @@ -29,6 +29,7 @@ dev/ofw/openfirm.c standard dev/ofw/openfirmio.c standard dev/ofw/openpromio.c standard dev/uart/uart_cpu_sparc64.c optional uart +kern/kern_clocksource.c standard kern/syscalls.c optional ktr libkern/ffs.c standard libkern/ffsl.c standard diff -ruNp sys.prev/sparc64/include/intr_machdep.h sys/sparc64/include/intr_machdep.h --- sys.prev/sparc64/include/intr_machdep.h 2009-12-25 10:01:19.000000000 +0200 +++ sys/sparc64/include/intr_machdep.h 2010-07-15 18:02:18.000000000 +0300 @@ -47,6 +47,8 @@ #define PIL_AST 4 /* ast ipi */ #define PIL_STOP 5 /* stop cpu ipi */ #define PIL_PREEMPT 6 /* preempt idle thread cpu ipi */ +#define PIL_HARDCLOCK 7 /* hardclock broadcast */ +#define PIL_STATCLOCK 8 /* statclock broadcast */ #define PIL_FILTER 12 /* filter interrupts */ #define PIL_FAST 13 /* fast interrupts */ #define PIL_TICK 14 /* tick interrupts */ diff -ruNp sys.prev/sparc64/include/pcpu.h sys/sparc64/include/pcpu.h --- sys.prev/sparc64/include/pcpu.h 2010-02-22 12:39:02.000000000 +0200 +++ sys/sparc64/include/pcpu.h 2010-07-15 19:16:07.000000000 +0300 @@ -53,6 +53,7 @@ struct pmap; vm_offset_t pc_addr; \ u_long pc_tickref; \ u_long pc_tickadj; \ + u_long pc_tickincrement; \ u_int pc_clock; \ u_int pc_impl; \ u_int pc_mid; \ diff -ruNp sys.prev/sparc64/include/smp.h sys/sparc64/include/smp.h --- sys.prev/sparc64/include/smp.h 2010-07-06 21:49:07.000000000 +0300 +++ sys/sparc64/include/smp.h 2010-07-15 18:00:05.000000000 +0300 @@ -58,6 +58,8 @@ #define IPI_AST PIL_AST #define IPI_RENDEZVOUS PIL_RENDEZVOUS #define IPI_PREEMPT PIL_PREEMPT +#define IPI_HARDCLOCK PIL_HARDCLOCK +#define IPI_STATCLOCK PIL_STATCLOCK #define IPI_STOP PIL_STOP #define IPI_STOP_HARD PIL_STOP diff -ruNp sys.prev/sparc64/include/tick.h sys/sparc64/include/tick.h --- sys.prev/sparc64/include/tick.h 2010-02-22 12:39:02.000000000 +0200 +++ sys/sparc64/include/tick.h 2010-07-15 19:37:09.000000000 +0300 @@ -32,7 +32,6 @@ extern u_int hardclock_use_stick; void tick_clear(u_int cpu_impl); -void tick_start(void); void tick_stop(u_int cpu_impl); #endif diff -ruNp sys.prev/sparc64/sparc64/clock.c sys/sparc64/sparc64/clock.c --- sys.prev/sparc64/sparc64/clock.c 2009-03-14 17:09:10.000000000 +0200 +++ sys/sparc64/sparc64/clock.c 2010-07-15 17:55:55.000000000 +0300 @@ -81,14 +81,3 @@ delay_tick(int usec) sched_unpin(); } -void -cpu_startprofclock(void) -{ - -} - -void -cpu_stopprofclock(void) -{ - -} diff -ruNp sys.prev/sparc64/sparc64/intr_machdep.c sys/sparc64/sparc64/intr_machdep.c --- sys.prev/sparc64/sparc64/intr_machdep.c 2009-12-25 10:01:19.000000000 +0200 +++ sys/sparc64/sparc64/intr_machdep.c 2010-07-15 18:01:31.000000000 +0300 @@ -96,7 +96,9 @@ static const char *const pil_names[] = { "ast", /* PIL_AST */ "stop", /* PIL_STOP */ "preempt", /* PIL_PREEMPT */ - "stray", "stray", "stray", "stray", "stray", + "hardclock", /* PIL_HARDCLOCK */ + "statclock", /* PIL_STATCLOCK */ + "stray", "stray", "stray", "filter", /* PIL_FILTER */ "fast", /* PIL_FAST */ "tick", /* PIL_TICK */ diff -ruNp sys.prev/sparc64/sparc64/mp_machdep.c sys/sparc64/sparc64/mp_machdep.c --- sys.prev/sparc64/sparc64/mp_machdep.c 2010-05-05 08:06:21.000000000 +0300 +++ sys/sparc64/sparc64/mp_machdep.c 2010-07-15 19:52:29.000000000 +0300 @@ -96,7 +96,9 @@ __FBSDID("$FreeBSD: head/sys/sparc64/spa #define SUNW_STOPSELF "SUNW,stop-self" static ih_func_t cpu_ipi_ast; +static ih_func_t cpu_ipi_hardclock; static ih_func_t cpu_ipi_preempt; +static ih_func_t cpu_ipi_statclock; static ih_func_t cpu_ipi_stop; /* @@ -279,6 +281,8 @@ cpu_mp_start(void) -1, NULL, NULL); intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL); intr_setup(PIL_PREEMPT, cpu_ipi_preempt, -1, NULL, NULL); + intr_setup(PIL_HARDCLOCK, cpu_ipi_hardclock, -1, NULL, NULL); + intr_setup(PIL_STATCLOCK, cpu_ipi_statclock, -1, NULL, NULL); cpuid_to_mid[curcpu] = PCPU_GET(mid); @@ -437,9 +441,6 @@ cpu_mp_bootstrap(struct pcpu *pc) wrpr(pil, 0, PIL_TICK); wrpr(pstate, 0, PSTATE_KERNEL); - /* Start the (S)TICK interrupts. */ - tick_start(); - smp_cpus++; KASSERT(curthread != NULL, ("%s: curthread", __func__)); PCPU_SET(other_cpus, all_cpus & ~(1 << curcpu)); @@ -451,6 +452,9 @@ cpu_mp_bootstrap(struct pcpu *pc) while (csa->csa_count != 0) ; + /* Start per-CPU event timers. */ + cpu_initclocks_ap(); + /* Ok, now enter the scheduler. */ sched_throw(NULL); } @@ -508,6 +512,20 @@ cpu_ipi_preempt(struct trapframe *tf) } static void +cpu_ipi_hardclock(struct trapframe *tf) +{ + + hardclockintr(tf); +} + +static void +cpu_ipi_statclock(struct trapframe *tf) +{ + + statclockintr(tf); +} + +static void spitfire_ipi_selected(u_int cpus, u_long d0, u_long d1, u_long d2) { u_int cpu; diff -ruNp sys.prev/sparc64/sparc64/tick.c sys/sparc64/sparc64/tick.c --- sys.prev/sparc64/sparc64/tick.c 2010-05-05 08:06:21.000000000 +0300 +++ sys/sparc64/sparc64/tick.c 2010-07-15 22:51:57.000000000 +0300 @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD: head/sys/sparc64/spa #include #include #include +#include #include #include @@ -77,19 +78,21 @@ SYSCTL_INT(_machdep_tick, OID_AUTO, hard &hardclock_use_stick, 0, "hardclock uses STICK instead of TICK timer"); static struct timecounter tick_tc; -static u_long tick_increment; +static struct eventtimer tick_et; +static int tick_bbwar = 0; static uint64_t tick_cputicks(void); static timecounter_get_t tick_get_timecount_up; #ifdef SMP static timecounter_get_t tick_get_timecount_mp; #endif -static void tick_hardclock(struct trapframe *tf); -static void tick_hardclock_bbwar(struct trapframe *tf); +static int tick_et_start(struct eventtimer *et, + struct bintime *first, struct bintime *period); +static int tick_et_stop(struct eventtimer *et); +static void tick_intr(struct trapframe *tf); static inline void tick_hardclock_common(struct trapframe *tf, u_long tick, u_long adj); static inline void tick_process(struct trapframe *tf); -static void stick_hardclock(struct trapframe *tf); static uint64_t tick_cputicks(void) @@ -103,8 +106,9 @@ cpu_initclocks(void) { uint32_t clock; - stathz = hz; - + if (PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI && + PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII) + tick_bbwar = 1; /* * Given that the STICK timers typically are driven at rather low * frequencies they shouldn't be used except when really necessary. @@ -113,27 +117,15 @@ cpu_initclocks(void) if (OF_getprop(OF_parent(PCPU_GET(node)), "stick-frequency", &clock, sizeof(clock)) == -1) panic("%s: could not determine STICK frequency", __func__); - intr_setup(PIL_TICK, stick_hardclock, -1, NULL, NULL); /* * We don't provide a CPU ticker as long as the frequency * supplied isn't actually used per-CPU. */ } else { clock = PCPU_GET(clock); - intr_setup(PIL_TICK, PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI && - PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ? - tick_hardclock_bbwar : tick_hardclock, -1, NULL, NULL); set_cputicker(tick_cputicks, clock, 0); } - tick_increment = clock / hz; - /* - * Avoid stopping of hardclock in terms of a lost (S)TICK interrupt - * by ensuring that the (S)TICK period is at least TICK_GRACE ticks. - */ - if (tick_increment < TICK_GRACE(clock)) - panic("%s: HZ too high, decrease to at least %d", - __func__, clock / TICK_GRACE(clock)); - tick_start(); + intr_setup(PIL_TICK, tick_intr, -1, NULL, NULL); /* * Initialize the TICK-based timecounter. This must not happen @@ -161,19 +153,32 @@ cpu_initclocks(void) } #endif tc_init(&tick_tc); + tick_et.et_name = hardclock_use_stick ? "stick" : "tick"; + tick_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | + ET_FLAGS_PERCPU; + tick_et.et_quality = 1000; + tick_et.et_frequency = clock; + tick_et.et_start = tick_et_start; + tick_et.et_stop = tick_et_stop; + tick_et.et_priv = NULL; + et_register(&tick_et); + + cpu_initclocks_bsp(); } static inline void tick_process(struct trapframe *tf) { + struct trapframe *oldframe; + struct thread *td; - if (curcpu == 0) - hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - else - hardclock_cpu(TRAPF_USERMODE(tf)); - if (profprocs != 0) - profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - statclock(TRAPF_USERMODE(tf)); + if (tick_et.et_active) { + td = curthread; + oldframe = td->td_intr_frame; + td->td_intr_frame = tf; + tick_et.et_event_cb(&tick_et, tick_et.et_arg); + td->td_intr_frame = oldframe; + } } /* @@ -184,58 +189,38 @@ tick_process(struct trapframe *tf) */ static void -tick_hardclock(struct trapframe *tf) -{ - u_long adj, tick; - register_t s; - - critical_enter(); - adj = PCPU_GET(tickadj); - s = intr_disable(); - tick = rd(tick); - wr(tick_cmpr, tick + tick_increment - adj, 0); - intr_restore(s); - tick_hardclock_common(tf, tick, adj); - critical_exit(); -} - -static void -tick_hardclock_bbwar(struct trapframe *tf) +tick_intr(struct trapframe *tf) { u_long adj, tick; register_t s; + u_long tick_increment = PCPU_GET(tickincrement); critical_enter(); adj = PCPU_GET(tickadj); s = intr_disable(); - tick = rd(tick); - wrtickcmpr(tick + tick_increment - adj, 0); + if (hardclock_use_stick) + tick = rdstick(); + else + tick = rd(tick); + if (tick_increment == 0) + ; /* Do not rearm in one-shot mode. */ + else if (hardclock_use_stick) + wrstickcmpr(tick + tick_increment - adj, 0); + else if (tick_bbwar) + wrtickcmpr(tick + tick_increment - adj, 0); + else + wr(tick_cmpr, tick + tick_increment - adj, 0); intr_restore(s); tick_hardclock_common(tf, tick, adj); critical_exit(); } -static void -stick_hardclock(struct trapframe *tf) -{ - u_long adj, stick; - register_t s; - - critical_enter(); - adj = PCPU_GET(tickadj); - s = intr_disable(); - stick = rdstick(); - wrstickcmpr(stick + tick_increment - adj, 0); - intr_restore(s); - tick_hardclock_common(tf, stick, adj); - critical_exit(); -} - static inline void tick_hardclock_common(struct trapframe *tf, u_long tick, u_long adj) { u_long ref; long delta; + u_long tick_increment = PCPU_GET(tickincrement); int count; ref = PCPU_GET(tickref); @@ -248,6 +233,8 @@ tick_hardclock_common(struct trapframe * if (adj != 0) adjust_ticks++; count++; + if (tick_increment == 0) + break; } if (count > 0) { adjust_missed += count - 1; @@ -295,11 +282,47 @@ tick_get_timecount_mp(struct timecounter #endif void -tick_start(void) +tick_clear(u_int cpu_impl) { + + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) + wrstick(0, 0); + wrpr(tick, 0, 0); +} + +void +tick_stop(u_int cpu_impl) +{ + + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) + wrstickcmpr(1L << 63, 0); + wrtickcmpr(1L << 63, 0); +} + +static int +tick_et_start(struct eventtimer *et, + struct bintime *first, struct bintime *period) +{ + u_long fdiv, div; u_long base; register_t s; + if (period != NULL) { + div = (tick_et.et_frequency * (period->frac >> 32)) >> 32; + if (period->sec != 0) + div += tick_et.et_frequency * period->sec; + } else + div = 0; + if (first != NULL) { + fdiv = (tick_et.et_frequency * (first->frac >> 32)) >> 32; + if (first->sec != 0) + fdiv += tick_et.et_frequency * first->sec; + } else + fdiv = div; + PCPU_SET(tickincrement, div); + /* * Try to make the (S)TICK interrupts as synchronously as possible * on all CPUs to avoid inaccuracies for migrating processes. Leave @@ -312,32 +335,24 @@ tick_start(void) base = rdstick(); else base = rd(tick); - base = roundup(base, tick_increment); + if (div != 0) + base = roundup(base, div); PCPU_SET(tickref, base); if (hardclock_use_stick != 0) - wrstickcmpr(base + tick_increment, 0); + wrstickcmpr(base + fdiv, 0); else - wrtickcmpr(base + tick_increment, 0); + wrtickcmpr(base + fdiv, 0); intr_restore(s); critical_exit(); + return (0); } -void -tick_clear(u_int cpu_impl) +static int +tick_et_stop(struct eventtimer *et) { - if (cpu_impl == CPU_IMPL_SPARC64V || - cpu_impl >= CPU_IMPL_ULTRASPARCIII) - wrstick(0, 0); - wrpr(tick, 0, 0); + PCPU_SET(tickincrement, 0); + tick_stop(PCPU_GET(impl)); + return (0); } -void -tick_stop(u_int cpu_impl) -{ - - if (cpu_impl == CPU_IMPL_SPARC64V || - cpu_impl >= CPU_IMPL_ULTRASPARCIII) - wrstickcmpr(1L << 63, 0); - wrtickcmpr(1L << 63, 0); -} diff -ruNp sys.prev/sun4v/include/clock.h sys/sun4v/include/clock.h --- sys.prev/sun4v/include/clock.h 2009-03-14 17:10:03.000000000 +0200 +++ sys/sun4v/include/clock.h 2010-07-15 21:23:08.000000000 +0300 @@ -29,7 +29,6 @@ #ifndef _MACHINE_CLOCK_H_ #define _MACHINE_CLOCK_H_ -extern u_long tick_increment; extern u_long tick_freq; extern u_long tick_MHz; diff -ruNp sys.prev/sun4v/include/intr_machdep.h sys/sun4v/include/intr_machdep.h --- sys.prev/sun4v/include/intr_machdep.h 2009-03-14 17:10:03.000000000 +0200 +++ sys/sun4v/include/intr_machdep.h 2010-07-15 21:45:21.000000000 +0300 @@ -47,6 +47,8 @@ #define PIL_AST 4 /* ast ipi */ #define PIL_STOP 5 /* stop cpu ipi */ #define PIL_PREEMPT 6 /* preempt idle thread cpu ipi */ +#define PIL_HARDCLOCK 7 /* hardclock broadcast */ +#define PIL_STATCLOCK 8 /* statclock broadcast */ #define PIL_FAST 13 /* fast interrupts */ #define PIL_TICK 14 diff -ruNp sys.prev/sun4v/include/pcpu.h sys/sun4v/include/pcpu.h --- sys.prev/sun4v/include/pcpu.h 2009-06-24 21:56:48.000000000 +0300 +++ sys/sun4v/include/pcpu.h 2010-07-15 21:33:26.000000000 +0300 @@ -73,6 +73,7 @@ struct pmap; uint64_t pc_nrq_size; \ u_long pc_tickref; \ u_long pc_tickadj; \ + u_long pc_tickincrement; \ struct rwindow pc_kwbuf; \ u_long pc_kwbuf_sp; \ u_int pc_kwbuf_full; \ diff -ruNp sys.prev/sun4v/include/smp.h sys/sun4v/include/smp.h --- sys.prev/sun4v/include/smp.h 2009-08-14 23:06:12.000000000 +0300 +++ sys/sun4v/include/smp.h 2010-07-15 21:47:52.000000000 +0300 @@ -46,7 +46,8 @@ #define IPI_STOP PIL_STOP #define IPI_STOP_HARD PIL_STOP #define IPI_PREEMPT PIL_PREEMPT - +#define IPI_HARDCLOCK PIL_HARDCLOCK +#define IPI_STATCLOCK PIL_STATCLOCK #define IPI_RETRIES 5000 @@ -81,6 +82,8 @@ void cpu_ipi_send(u_int mid, u_long d0, void cpu_ipi_ast(struct trapframe *tf); void cpu_ipi_stop(struct trapframe *tf); void cpu_ipi_preempt(struct trapframe *tf); +void cpu_ipi_hardclock(struct trapframe *tf); +void cpu_ipi_statclock(struct trapframe *tf); void ipi_selected(u_int cpus, u_int ipi); void ipi_all_but_self(u_int ipi); diff -ruNp sys.prev/sun4v/include/tick.h sys/sun4v/include/tick.h --- sys.prev/sun4v/include/tick.h 2009-03-14 17:10:03.000000000 +0200 +++ sys/sun4v/include/tick.h 2010-07-15 21:29:52.000000000 +0300 @@ -30,7 +30,5 @@ #define _MACHINE_TICK_H_ void tick_init(u_long clock); -void tick_start(void); -void tick_stop(void); #endif diff -ruNp sys.prev/sun4v/sun4v/clock.c sys/sun4v/sun4v/clock.c --- sys.prev/sun4v/sun4v/clock.c 2009-03-14 17:10:03.000000000 +0200 +++ sys/sun4v/sun4v/clock.c 2010-07-15 21:23:17.000000000 +0300 @@ -30,7 +30,6 @@ #include #include -u_long tick_increment; u_long tick_freq; u_long tick_MHz; @@ -46,13 +45,3 @@ DELAY(int n) while (rd(tick) < end) ; } - -void -cpu_startprofclock(void) -{ -} - -void -cpu_stopprofclock(void) -{ -} diff -ruNp sys.prev/sun4v/sun4v/intr_machdep.c sys/sun4v/sun4v/intr_machdep.c --- sys.prev/sun4v/sun4v/intr_machdep.c 2009-03-14 17:10:03.000000000 +0200 +++ sys/sun4v/sun4v/intr_machdep.c 2010-07-15 21:47:16.000000000 +0300 @@ -109,7 +109,9 @@ static char *pil_names[] = { "ast", /* PIL_AST */ "stop", /* PIL_STOP */ "preempt", /* PIL_PREEMPT */ - "stray", "stray", "stray", "stray", "stray", "stray", + "hardclock", /* PIL_HARDCLOCK */ + "statclock", /* PIL_STATCLOCK */ + "stray", "stray", "stray", "stray", "fast", /* PIL_FAST */ "tick", /* PIL_TICK */ }; @@ -262,6 +264,8 @@ intr_init(void) intr_handlers[PIL_RENDEZVOUS] = (ih_func_t *)smp_rendezvous_action; intr_handlers[PIL_STOP]= cpu_ipi_stop; intr_handlers[PIL_PREEMPT]= cpu_ipi_preempt; + intr_handlers[PIL_HARDCLOCK]= cpu_ipi_hardclock; + intr_handlers[PIL_STATCLOCK]= cpu_ipi_statclock; #endif mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); cpu_intrq_alloc(); diff -ruNp sys.prev/sun4v/sun4v/mp_machdep.c sys/sun4v/sun4v/mp_machdep.c --- sys.prev/sun4v/sun4v/mp_machdep.c 2009-06-24 21:56:48.000000000 +0300 +++ sys/sun4v/sun4v/mp_machdep.c 2010-07-15 22:02:18.000000000 +0300 @@ -392,7 +392,6 @@ cpu_mp_bootstrap(struct pcpu *pc) tte_hash_set_scratchpad_kernel(kernel_pmap->pm_hash); trap_init(); cpu_intrq_init(); - tick_start(); #ifdef TRAP_TRACING mp_trap_trace_init(); @@ -413,6 +412,10 @@ cpu_mp_bootstrap(struct pcpu *pc) while (csa->csa_count != 0) ; + + /* Start per-CPU event timers. */ + cpu_initclocks_ap(); + /* ok, now enter the scheduler */ sched_throw(NULL); } @@ -467,6 +470,20 @@ cpu_ipi_preempt(struct trapframe *tf) } void +cpu_ipi_hardclock(struct trapframe *tf) +{ + + hardclockintr(tf); +} + +void +cpu_ipi_statclock(struct trapframe *tf) +{ + + statclockintr(tf); +} + +void cpu_ipi_selected(int cpu_count, uint16_t *cpulist, u_long d0, u_long d1, u_long d2, uint64_t *ackmask) { diff -ruNp sys.prev/sun4v/sun4v/tick.c sys/sun4v/sun4v/tick.c --- sys.prev/sun4v/sun4v/tick.c 2009-03-14 17:10:03.000000000 +0200 +++ sys/sun4v/sun4v/tick.c 2010-07-15 22:51:09.000000000 +0300 @@ -33,7 +33,9 @@ __FBSDID("$FreeBSD: head/sys/sun4v/sun4v #include #include #include +#include #include +#include #include #include @@ -66,7 +68,12 @@ static int adjust_ticks = 0; SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_ticks, CTLFLAG_RD, &adjust_ticks, 0, "total number of tick interrupts with adjustment"); -static void tick_hardclock(struct trapframe *); +static struct eventtimer tick_et; + +static int tick_et_start(struct eventtimer *et, + struct bintime *first, struct bintime *period); +static int tick_et_stop(struct eventtimer *et); +static void tick_intr(struct trapframe *); static uint64_t tick_cputicks(void) @@ -79,28 +86,41 @@ void cpu_initclocks(void) { - stathz = hz; - tick_start(); + intr_setup(PIL_TICK, tick_intr, -1, NULL, NULL); + + tick_et.et_name = "tick"; + tick_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | + ET_FLAGS_PERCPU; + tick_et.et_quality = 1000; + tick_et.et_frequency = tick_freq; + tick_et.et_start = tick_et_start; + tick_et.et_stop = tick_et_stop; + tick_et.et_priv = NULL; + et_register(&tick_et); + + cpu_initclocks_bsp(); } static __inline void tick_process(struct trapframe *tf) { + struct trapframe *oldframe; + struct thread *td; - if (curcpu == 0) - hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - else - hardclock_cpu(TRAPF_USERMODE(tf)); - if (profprocs != 0) - profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - - statclock(TRAPF_USERMODE(tf)); + if (tick_et.et_active) { + td = curthread; + oldframe = td->td_intr_frame; + td->td_intr_frame = tf; + tick_et.et_event_cb(&tick_et, tick_et.et_arg); + td->td_intr_frame = oldframe; + } } static void -tick_hardclock(struct trapframe *tf) +tick_intr(struct trapframe *tf) { u_long adj, s, tick, ref; + u_long tick_increment = PCPU_GET(tickincrement); long delta; int count; @@ -118,7 +138,8 @@ tick_hardclock(struct trapframe *tf) adj = PCPU_GET(tickadj); s = intr_disable_all(); tick = rd(tick); - wrtickcmpr(tick + tick_increment - adj, 0); + if (tick_increment != 0) + wrtickcmpr(tick + tick_increment - adj, 0); intr_restore_all(s); ref = PCPU_GET(tickref); @@ -131,6 +152,8 @@ tick_hardclock(struct trapframe *tf) if (adj != 0) adjust_ticks++; count++; + if (tick_increment == 0) + break; } if (count > 0) { adjust_missed += count - 1; @@ -146,7 +169,6 @@ tick_hardclock(struct trapframe *tf) } PCPU_SET(tickref, ref); PCPU_SET(tickadj, adj); - } void @@ -155,41 +177,55 @@ tick_init(u_long clock) tick_freq = clock; tick_MHz = clock / 1000000; - tick_increment = clock / hz; - /* - * Avoid stopping of hardclock in terms of a lost tick interrupt - * by ensuring that the tick period is at least TICK_GRACE ticks. - */ - printf("tick_freq=%ld hz=%d tick_increment=%ld\n", - tick_freq, hz, tick_increment); - -#ifndef SIMULATOR - if (tick_increment < TICK_GRACE) - panic("%s: HZ too high, decrease to at least %ld", __func__, - clock / TICK_GRACE); -#endif set_cputicker(tick_cputicks, tick_freq, 0); } -void -tick_start(void) -{ - u_long base, s; - - if (curcpu == 0) - intr_setup(PIL_TICK, tick_hardclock, -1, NULL, NULL); +static int +tick_et_start(struct eventtimer *et, + struct bintime *first, struct bintime *period) +{ + u_long fdiv, div; + u_long base; + register_t s; + + if (period != NULL) { + div = (tick_et.et_frequency * (period->frac >> 32)) >> 32; + if (period->sec != 0) + div += tick_et.et_frequency * period->sec; + } else + div = 0; + if (first != NULL) { + fdiv = (tick_et.et_frequency * (first->frac >> 32)) >> 32; + if (first->sec != 0) + fdiv += tick_et.et_frequency * first->sec; + } else + fdiv = div; + PCPU_SET(tickincrement, div); /* * Try to make the tick interrupts as synchronously as possible on * all CPUs to avoid inaccuracies for migrating processes. Leave out * one tick to make sure that it is not missed. */ + critical_enter(); PCPU_SET(tickadj, 0); - s = intr_disable_all(); + s = intr_disable(); base = rd(tick); - base = roundup(base, tick_increment); + if (div != 0) + base = roundup(base, div); PCPU_SET(tickref, base); - wrtickcmpr(base + tick_increment, 0); - intr_restore_all(s); + wrtickcmpr(base + fdiv, 0); + intr_restore(s); + critical_exit(); + return (0); +} + +static int +tick_et_stop(struct eventtimer *et) +{ + + PCPU_SET(tickincrement, 0); + wrtickcmpr(1L << 63, 0); + return (0); }