summaryrefslogtreecommitdiffstats
path: root/sys/sun4v
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2010-07-29 12:08:46 +0000
committermav <mav@FreeBSD.org>2010-07-29 12:08:46 +0000
commit4f9a242ba1a525c2a24372820745ea1ac3b32a22 (patch)
tree1baf2b9638c10821a6a2d8440f3504707e019edf /sys/sun4v
parent9ce81bb370e2f2664e14369a49ab80d2d2ab3a4c (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/sun4v/include/intr_machdep.h2
-rw-r--r--sys/sun4v/include/pcpu.h1
-rw-r--r--sys/sun4v/include/smp.h5
-rw-r--r--sys/sun4v/include/tick.h2
-rw-r--r--sys/sun4v/sun4v/clock.c11
-rw-r--r--sys/sun4v/sun4v/intr_machdep.c6
-rw-r--r--sys/sun4v/sun4v/mp_machdep.c19
-rw-r--r--sys/sun4v/sun4v/tick.c118
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);
}
OpenPOWER on IntegriCloud