summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2008-08-07 21:25:49 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2008-08-07 21:25:49 +0000
commit0c2518a79df986738e77c042da11eb4d193d89b0 (patch)
tree1676145ebcb7f808e3543e7aa695b575b47851ae /sys/arch/sparc64
parentbcb2af5c44c8592ece8afbc8a7d3094609952498 (diff)
Use %sys_tick to generate clock interrupts on systems that have it.
Diffstat (limited to 'sys/arch/sparc64')
-rw-r--r--sys/arch/sparc64/include/cpu.h6
-rw-r--r--sys/arch/sparc64/include/ctlreg.h8
-rw-r--r--sys/arch/sparc64/sparc64/clock.c70
-rw-r--r--sys/arch/sparc64/sparc64/cpu.c6
-rw-r--r--sys/arch/sparc64/sparc64/locore.s27
5 files changed, 96 insertions, 21 deletions
diff --git a/sys/arch/sparc64/include/cpu.h b/sys/arch/sparc64/include/cpu.h
index 08a9a48c29f..de4057bd262 100644
--- a/sys/arch/sparc64/include/cpu.h
+++ b/sys/arch/sparc64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.64 2008/08/07 18:46:04 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.65 2008/08/07 21:25:48 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.28 2001/06/14 22:56:58 thorpej Exp $ */
/*
@@ -215,6 +215,8 @@ struct clockframe {
#define CLKF_PC(framep) ((framep)->t.tf_pc)
#define CLKF_INTR(framep) ((framep)->saved_intr_level != 0)
+extern void (*cpu_start_clock)(void);
+
void setsoftnet(void);
#define aston(p) ((p)->p_md.md_astpending = 1)
@@ -249,9 +251,11 @@ caddr_t reserve_dumppages(caddr_t);
/* clock.c */
struct timeval;
int tickintr(void *); /* level 10 (tick) interrupt code */
+int sys_tickintr(void *); /* level 10 (sys_tick) interrupt code */
int clockintr(void *);/* level 10 (clock) interrupt code */
int statintr(void *); /* level 14 (statclock) interrupt code */
void tick_start(void);
+void sys_tick_start(void);
/* locore.s */
struct fpstate64;
void savefpstate(struct fpstate64 *);
diff --git a/sys/arch/sparc64/include/ctlreg.h b/sys/arch/sparc64/include/ctlreg.h
index e033f7ebb2f..68b13fcf01b 100644
--- a/sys/arch/sparc64/include/ctlreg.h
+++ b/sys/arch/sparc64/include/ctlreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ctlreg.h,v 1.19 2008/07/12 07:37:25 kettenis Exp $ */
+/* $OpenBSD: ctlreg.h,v 1.20 2008/08/07 21:25:48 kettenis Exp $ */
/* $NetBSD: ctlreg.h,v 1.28 2001/08/06 23:55:34 eeh Exp $ */
/*
@@ -584,6 +584,8 @@ sparc_rdpr_ ## name() \
GEN_RD(asi);
GEN_RD(asr22);
+GEN_RD(sys_tick);
+GEN_RD(sys_tick_cmpr);
GEN_RDPR(cwp);
GEN_RDPR(tick);
GEN_RDPR(pstate);
@@ -723,10 +725,12 @@ void flush(void *p)
: "memory");
}
-/* read 64-bit %tick register */
+/* Read 64-bit %tick and %sys_tick registers. */
#define tick() (sparc_rdpr(tick) & TICK_TICKS)
+#define sys_tick() (sparc_rd(sys_tick) & TICK_TICKS)
extern void tickcmpr_set(u_int64_t);
+extern void sys_tickcmpr_set(u_int64_t);
#endif /* _LOCORE */
#endif /* _SPARC64_CTLREG_ */
diff --git a/sys/arch/sparc64/sparc64/clock.c b/sys/arch/sparc64/sparc64/clock.c
index a4018979f5d..329cf66cc83 100644
--- a/sys/arch/sparc64/sparc64/clock.c
+++ b/sys/arch/sparc64/sparc64/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.45 2008/08/07 18:46:04 kettenis Exp $ */
+/* $OpenBSD: clock.c,v 1.46 2008/08/07 21:25:47 kettenis Exp $ */
/* $NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */
/*
@@ -612,22 +612,25 @@ cpu_initclocks(void)
strlcpy(level0.ih_name, "clock", sizeof(level0.ih_name));
intr_establish(10, &level0);
+ /* We only have one timer so we have no statclock */
+ stathz = 0;
+
+ if (sys_tick_rate > 0 && impl != IMPL_HUMMINGBIRD) {
+ tick_increment = sys_tick_rate / hz;
+ level0.ih_fun = sys_tickintr;
+ cpu_start_clock = sys_tick_start;
+ } else {
+ /* set the next interrupt time */
+ tick_increment = cpu_clockrate / hz;
+ level0.ih_fun = tickintr;
+ cpu_start_clock = tick_start;
+ }
+
for (ci = cpus; ci != NULL; ci = ci->ci_next)
memcpy(&ci->ci_tickintr, &level0, sizeof(level0));
- /* We only have one timer so we have no statclock */
- stathz = 0;
+ cpu_start_clock();
- /* set the next interrupt time */
- tick_increment = cpu_clockrate / hz;
-#ifdef DEBUG
- printf("Using %%tick -- intr in %ld cycles...",
- tick_increment);
-#endif
- tick_start();
-#ifdef DEBUG
- printf("done.\n");
-#endif
return;
}
@@ -772,6 +775,30 @@ tickintr(cap)
return (1);
}
+int
+sys_tickintr(cap)
+ void *cap;
+{
+ struct cpu_info *ci = curcpu();
+ u_int64_t s;
+
+ /*
+ * Do we need to worry about overflow here?
+ */
+ while (ci->ci_tick < sys_tick()) {
+ ci->ci_tick += tick_increment;
+ hardclock((struct clockframe *)cap);
+ level0.ih_count.ec_count++;
+ }
+
+ /* Reset the interrupt. */
+ s = intr_disable();
+ sys_tickcmpr_set(ci->ci_tick);
+ intr_restore(s);
+
+ return (1);
+}
+
/*
* Level 14 (stat clock) interrupt handler.
*/
@@ -930,6 +957,23 @@ tick_start(void)
intr_restore(s);
}
+void
+sys_tick_start(void)
+{
+ struct cpu_info *ci = curcpu();
+ u_int64_t s;
+
+ /*
+ * Try to make the tick interrupts as synchronously as possible on
+ * all CPUs to avoid inaccuracies for migrating processes.
+ */
+
+ s = intr_disable();
+ ci->ci_tick = roundup(sys_tick(), tick_increment);
+ sys_tickcmpr_set(ci->ci_tick);
+ intr_restore(s);
+}
+
u_int
tick_get_timecount(struct timecounter *tc)
{
diff --git a/sys/arch/sparc64/sparc64/cpu.c b/sys/arch/sparc64/sparc64/cpu.c
index 193cebcdca4..2d0dd141742 100644
--- a/sys/arch/sparc64/sparc64/cpu.c
+++ b/sys/arch/sparc64/sparc64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.45 2008/07/21 13:30:05 art Exp $ */
+/* $OpenBSD: cpu.c,v 1.46 2008/08/07 21:25:47 kettenis Exp $ */
/* $NetBSD: cpu.c,v 1.13 2001/05/26 21:27:15 chs Exp $ */
/*
@@ -76,6 +76,8 @@ struct cacheinfo cacheinfo = {
us_dcache_flush_page
};
+void (*cpu_start_clock)(void);
+
/* Linked list of all CPUs in system. */
struct cpu_info *cpus = NULL;
@@ -502,7 +504,7 @@ cpu_hatch(void)
microuptime(&ci->ci_schedstate.spc_runtime);
splx(s);
- tick_start();
+ cpu_start_clock();
SCHED_LOCK(s);
cpu_switchto(NULL, sched_chooseproc());
diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s
index bb5d4dff754..f996fa7d13f 100644
--- a/sys/arch/sparc64/sparc64/locore.s
+++ b/sys/arch/sparc64/sparc64/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.150 2008/08/07 18:46:04 kettenis Exp $ */
+/* $OpenBSD: locore.s,v 1.151 2008/08/07 21:25:47 kettenis Exp $ */
/* $NetBSD: locore.s,v 1.137 2001/08/13 06:10:10 jdolecek Exp $ */
/*
@@ -4282,10 +4282,11 @@ _C_LABEL(sparc_interrupt):
* If this is a %tick softint, clear it then call interrupt_vector.
*/
rd SOFTINT, %g1
- btst TICK_INT, %g1
+ set (TICK_INT|STICK_INT), %g2
+ andcc %g2, %g1, %g2
bz,pt %icc, 0f
GET_CPUINFO_VA(%g7)
- wr %g0, TICK_INT, CLEAR_SOFTINT
+ wr %g2, 0, CLEAR_SOFTINT
ba,pt %icc, setup_sparcintr
add %g7, CI_TICKINTR, %g5
0:
@@ -8918,6 +8919,26 @@ ENTRY(tickcmpr_set)
retl
nop
+ENTRY(sys_tickcmpr_set)
+ ba 1f
+ mov 8, %o2 ! Initial step size
+ .align 64
+1: wr %o0, 0, %sys_tick_cmpr
+ rd %sys_tick_cmpr, %g0
+
+ rd %sys_tick, %o1 ! Read current %sys_tick
+ sllx %o1, 1, %o1
+ srlx %o1, 1, %o1
+
+ cmp %o0, %o1 ! Make sure the value we wrote to
+ bg,pt %xcc, 2f ! %sys_tick_cmpr was in the future.
+ add %o0, %o2, %o0 ! If not, add the step size, double
+ ba,pt %xcc, 1b ! the step size and try again.
+ sllx %o2, 1, %o2
+2:
+ retl
+ nop
+
#define MICROPERSEC (1000000)
.data
.align 16