diff options
author | mav <mav@FreeBSD.org> | 2010-07-29 12:08:46 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2010-07-29 12:08:46 +0000 |
commit | 4f9a242ba1a525c2a24372820745ea1ac3b32a22 (patch) | |
tree | 1baf2b9638c10821a6a2d8440f3504707e019edf /sys/sun4v | |
parent | 9ce81bb370e2f2664e14369a49ab80d2d2ab3a4c (diff) | |
download | FreeBSD-src-4f9a242ba1a525c2a24372820745ea1ac3b32a22.zip FreeBSD-src-4f9a242ba1a525c2a24372820745ea1ac3b32a22.tar.gz |
Adapt sparc64 and sun4v timer code for the new event timers infrastructure.
Reviewed by: marius@
Diffstat (limited to 'sys/sun4v')
-rw-r--r-- | sys/sun4v/include/clock.h | 1 | ||||
-rw-r--r-- | sys/sun4v/include/intr_machdep.h | 2 | ||||
-rw-r--r-- | sys/sun4v/include/pcpu.h | 1 | ||||
-rw-r--r-- | sys/sun4v/include/smp.h | 5 | ||||
-rw-r--r-- | sys/sun4v/include/tick.h | 2 | ||||
-rw-r--r-- | sys/sun4v/sun4v/clock.c | 11 | ||||
-rw-r--r-- | sys/sun4v/sun4v/intr_machdep.c | 6 | ||||
-rw-r--r-- | sys/sun4v/sun4v/mp_machdep.c | 19 | ||||
-rw-r--r-- | sys/sun4v/sun4v/tick.c | 118 |
9 files changed, 109 insertions, 56 deletions
diff --git a/sys/sun4v/include/clock.h b/sys/sun4v/include/clock.h index b0e4c0b..d95cff6 100644 --- a/sys/sun4v/include/clock.h +++ b/sys/sun4v/include/clock.h @@ -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 --git a/sys/sun4v/include/intr_machdep.h b/sys/sun4v/include/intr_machdep.h index 5f22c93..370a5c0 100644 --- a/sys/sun4v/include/intr_machdep.h +++ b/sys/sun4v/include/intr_machdep.h @@ -46,6 +46,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 --git a/sys/sun4v/include/pcpu.h b/sys/sun4v/include/pcpu.h index 350e29a..ba79256 100644 --- a/sys/sun4v/include/pcpu.h +++ b/sys/sun4v/include/pcpu.h @@ -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 --git a/sys/sun4v/include/smp.h b/sys/sun4v/include/smp.h index 63a8e01..ec30d0d 100644 --- a/sys/sun4v/include/smp.h +++ b/sys/sun4v/include/smp.h @@ -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, u_long d1, u_long d2); 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 --git a/sys/sun4v/include/tick.h b/sys/sun4v/include/tick.h index 8586a0d..1bb739e 100644 --- a/sys/sun4v/include/tick.h +++ b/sys/sun4v/include/tick.h @@ -30,7 +30,5 @@ #define _MACHINE_TICK_H_ void tick_init(u_long clock); -void tick_start(void); -void tick_stop(void); #endif diff --git a/sys/sun4v/sun4v/clock.c b/sys/sun4v/sun4v/clock.c index a73ed35..75f6d43 100644 --- a/sys/sun4v/sun4v/clock.c +++ b/sys/sun4v/sun4v/clock.c @@ -30,7 +30,6 @@ #include <sys/systm.h> #include <machine/clock.h> -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 --git a/sys/sun4v/sun4v/intr_machdep.c b/sys/sun4v/sun4v/intr_machdep.c index 4192e0b..123493e 100644 --- a/sys/sun4v/sun4v/intr_machdep.c +++ b/sys/sun4v/sun4v/intr_machdep.c @@ -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 --git a/sys/sun4v/sun4v/mp_machdep.c b/sys/sun4v/sun4v/mp_machdep.c index 5b5df89..6461cf8 100644 --- a/sys/sun4v/sun4v/mp_machdep.c +++ b/sys/sun4v/sun4v/mp_machdep.c @@ -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 --git a/sys/sun4v/sun4v/tick.c b/sys/sun4v/sun4v/tick.c index 1a9672e..d8cfd1c 100644 --- a/sys/sun4v/sun4v/tick.c +++ b/sys/sun4v/sun4v/tick.c @@ -33,7 +33,9 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/interrupt.h> #include <sys/pcpu.h> +#include <sys/proc.h> #include <sys/sysctl.h> +#include <sys/timeet.h> #include <sys/timetc.h> #include <machine/clock.h> @@ -46,8 +48,6 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #endif -#define TICK_GRACE 10000 - SYSCTL_NODE(_machdep, OID_AUTO, tick, CTLFLAG_RD, 0, "tick statistics"); static int adjust_edges = 0; @@ -66,7 +66,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 +84,44 @@ 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_min_period.sec = 0; + tick_et.et_min_period.frac = 0x00010000LLU << 32; /* To be safe. */ + tick_et.et_max_period.sec = 3600 * 24; /* No practical limit. */ + tick_et.et_max_period.frac = 0; + 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) { - - 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)); + struct trapframe *oldframe; + struct thread *td; + + 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 adj, ref, s, tick, tick_increment; long delta; int count; @@ -108,6 +129,7 @@ tick_hardclock(struct trapframe *tf) if (curthread->td_critnest > 2 || curthread->td_critnest < 1) panic("nested hardclock %d\n", curthread->td_critnest); #endif + tick_increment = PCPU_GET(tickincrement); /* * The sequence of reading the TICK register, calculating the value * of the next tick and writing it to the TICK_CMPR register must not @@ -118,7 +140,10 @@ 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); + else + wrtickcmpr(1L << 63, 0); intr_restore_all(s); ref = PCPU_GET(tickref); @@ -131,6 +156,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 +173,6 @@ tick_hardclock(struct trapframe *tf) } PCPU_SET(tickref, ref); PCPU_SET(tickadj, adj); - } void @@ -155,41 +181,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) +static int +tick_et_start(struct eventtimer *et, + struct bintime *first, struct bintime *period) { - u_long base, s; - - if (curcpu == 0) - intr_setup(PIL_TICK, tick_hardclock, -1, NULL, NULL); + 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(); base = rd(tick); - base = roundup(base, tick_increment); + if (div != 0) + base = roundup(base, div); PCPU_SET(tickref, base); - wrtickcmpr(base + tick_increment, 0); + wrtickcmpr(base + fdiv, 0); intr_restore_all(s); + critical_exit(); + return (0); +} + +static int +tick_et_stop(struct eventtimer *et) +{ + + PCPU_SET(tickincrement, 0); + wrtickcmpr(1L << 63, 0); + return (0); } |