diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc64/include/cpu.h | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/include/ctlreg.h | 8 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/clock.c | 70 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/cpu.c | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/locore.s | 27 |
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 |