Module Name: src Committed By: macallan Date: Thu Nov 8 00:34:38 UTC 2012
Modified Files: src/sys/arch/sparc64/include: cpu.h ctlreg.h psl.h src/sys/arch/sparc64/sparc64: clock.c cpu.c locore.s Log Message: use system tick timer instead of %tick on UltraSPARC-III-ish CPUs review & fixes by Takeshi Nakayama To generate a diff of this commit: cvs rdiff -u -r1.98 -r1.99 src/sys/arch/sparc64/include/cpu.h cvs rdiff -u -r1.56 -r1.57 src/sys/arch/sparc64/include/ctlreg.h cvs rdiff -u -r1.49 -r1.50 src/sys/arch/sparc64/include/psl.h cvs rdiff -u -r1.106 -r1.107 src/sys/arch/sparc64/sparc64/clock.c cvs rdiff -u -r1.102 -r1.103 src/sys/arch/sparc64/sparc64/cpu.c cvs rdiff -u -r1.341 -r1.342 src/sys/arch/sparc64/sparc64/locore.s Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/sparc64/include/cpu.h diff -u src/sys/arch/sparc64/include/cpu.h:1.98 src/sys/arch/sparc64/include/cpu.h:1.99 --- src/sys/arch/sparc64/include/cpu.h:1.98 Sat Jul 30 19:29:12 2011 +++ src/sys/arch/sparc64/include/cpu.h Thu Nov 8 00:34:37 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.98 2011/07/30 19:29:12 martin Exp $ */ +/* $NetBSD: cpu.h,v 1.99 2012/11/08 00:34:37 macallan Exp $ */ /* * Copyright (c) 1992, 1993 @@ -128,7 +128,8 @@ struct cpu_info { /* %tick and cpu frequency information */ u_long ci_tick_increment; - uint64_t ci_cpu_clockrate[2]; + uint64_t ci_cpu_clockrate[2]; /* %tick */ + uint64_t ci_system_clockrate[2]; /* %stick */ /* Interrupts */ struct intrhand *ci_intrpending[16]; @@ -351,10 +352,12 @@ void * reserve_dumppages(void *); /* clock.c */ struct timeval; int tickintr(void *); /* level 10/14 (tick) interrupt code */ +int stickintr(void *); /* system tick interrupt code */ int clockintr(void *); /* level 10 (clock) interrupt code */ int statintr(void *); /* level 14 (statclock) interrupt code */ int schedintr(void *); /* level 10 (schedclock) interrupt code */ void tickintr_establish(int, int (*)(void *)); +void stickintr_establish(int, int (*)(void *)); /* locore.s */ struct fpstate64; void savefpstate(struct fpstate64 *); @@ -372,6 +375,10 @@ struct frame *getfp(void); void switchtoctx_us(int); void switchtoctx_usiii(int); void next_tick(long); +void next_stick(long); +void setstick(long); +long getstick(void); + /* trap.c */ void cpu_vmspace_exec(struct lwp *, vaddr_t, vaddr_t); int rwindow_save(struct lwp *); Index: src/sys/arch/sparc64/include/ctlreg.h diff -u src/sys/arch/sparc64/include/ctlreg.h:1.56 src/sys/arch/sparc64/include/ctlreg.h:1.57 --- src/sys/arch/sparc64/include/ctlreg.h:1.56 Sat Oct 8 08:49:07 2011 +++ src/sys/arch/sparc64/include/ctlreg.h Thu Nov 8 00:34:37 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: ctlreg.h,v 1.56 2011/10/08 08:49:07 nakayama Exp $ */ +/* $NetBSD: ctlreg.h,v 1.57 2012/11/08 00:34:37 macallan Exp $ */ /* * Copyright (c) 1996-2002 Eduardo Horvath @@ -415,6 +415,8 @@ #define CLEAR_SOFTINT %asr21 /* Clears these bits */ #define SOFTINT %asr22 /* Reads the register */ #define TICK_CMPR %asr23 +#define STICK %asr24 +#define STICK_CMPR %asr25 #define TICK_INT 0x01 /* level-14 clock tick */ #define SOFTINT1 (0x1<<1) @@ -432,6 +434,7 @@ #define SOFTINT13 (0x1<<13) #define SOFTINT14 (0x1<<14) #define SOFTINT15 (0x1<<15) +#define STICK_INTR (0x1<<16) /* system tick */ /* Interrupt Dispatch -- usually reserved for cross-calls */ #define ASR_IDSR 0x48 /* Interrupt dispatch status reg */ Index: src/sys/arch/sparc64/include/psl.h diff -u src/sys/arch/sparc64/include/psl.h:1.49 src/sys/arch/sparc64/include/psl.h:1.50 --- src/sys/arch/sparc64/include/psl.h:1.49 Tue Jul 12 07:51:34 2011 +++ src/sys/arch/sparc64/include/psl.h Thu Nov 8 00:34:37 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: psl.h,v 1.49 2011/07/12 07:51:34 mrg Exp $ */ +/* $NetBSD: psl.h,v 1.50 2012/11/08 00:34:37 macallan Exp $ */ /* * Copyright (c) 1992, 1993 @@ -330,6 +330,7 @@ SPARC64_GETPR64_DEF(ver) /* getver() * #define GETVER_CPU_IMPL() ((getver() & VER_IMPL) >> VER_IMPL_SHIFT) #define GETVER_CPU_MANUF() ((getver() & VER_MANUF) >> VER_MANUF_SHIFT) #define CPU_IS_SPITFIRE() (GETVER_CPU_IMPL() == IMPL_SPITFIRE) +#define CPU_IS_HUMMINGBIRD() (GETVER_CPU_IMPL() == IMPL_HUMMINGBIRD) #define CPU_IS_USIIIi() ((GETVER_CPU_IMPL() == IMPL_JALAPENO) || \ (GETVER_CPU_IMPL() == IMPL_SERRANO)) #define CPU_IS_USIII_UP() (GETVER_CPU_IMPL() >= IMPL_CHEETAH) Index: src/sys/arch/sparc64/sparc64/clock.c diff -u src/sys/arch/sparc64/sparc64/clock.c:1.106 src/sys/arch/sparc64/sparc64/clock.c:1.107 --- src/sys/arch/sparc64/sparc64/clock.c:1.106 Sun Sep 4 12:17:46 2011 +++ src/sys/arch/sparc64/sparc64/clock.c Thu Nov 8 00:34:38 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: clock.c,v 1.106 2011/09/04 12:17:46 nakayama Exp $ */ +/* $NetBSD: clock.c,v 1.107 2012/11/08 00:34:38 macallan Exp $ */ /* * Copyright (c) 1992, 1993 @@ -55,7 +55,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.106 2011/09/04 12:17:46 nakayama Exp $"); +__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.107 2012/11/08 00:34:38 macallan Exp $"); #include "opt_multiprocessor.h" @@ -99,6 +99,7 @@ __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1. * counter-timer timer#0 timer#1 %tick * counter-timer + SMP timer#0/%tick - timer#1 or %tick * no counter-timer %tick - %tick + * US-IIIi %stick - %stick */ /* @@ -137,6 +138,7 @@ void stopcounter(struct timer_4u *); int timerblurb = 10; /* Guess a value; used before clock is attached */ static u_int tick_get_timecount(struct timecounter *); +static u_int stick_get_timecount(struct timecounter *); /* * define timecounter "tick-counter" @@ -153,6 +155,17 @@ static struct timecounter tick_timecount NULL /* next timecounter */ }; +static struct timecounter stick_timecounter = { + stick_get_timecount, /* get_timecount */ + 0, /* no poll_pps */ + ~0u, /* counter_mask */ + 0, /* frequency - set at initialisation */ + "stick-counter", /* name */ + 100, /* quality */ + 0, /* private reference - UNUSED */ + NULL /* next timecounter */ +}; + /* * tick_get_timecount provide current tick counter value */ @@ -162,6 +175,12 @@ tick_get_timecount(struct timecounter *t return cpu_counter(); } +static u_int +stick_get_timecount(struct timecounter *tc) +{ + return getstick(); +} + #ifdef MULTIPROCESSOR static u_int counter_get_timecount(struct timecounter *); @@ -329,6 +348,27 @@ tickintr_establish(int pil, int (*fun)(v intr_restore(s); } +void +stickintr_establish(int pil, int (*fun)(void *)) +{ + int s; + struct intrhand *ih; + struct cpu_info *ci = curcpu(); + + ih = sparc_softintr_establish(pil, fun, NULL); + ih->ih_number = 1; + if (CPU_IS_PRIMARY(ci)) + intr_establish(pil, true, ih); + ci->ci_tick_ih = ih; + + /* set the next interrupt time */ + ci->ci_tick_increment = ci->ci_system_clockrate[0] / hz; + + s = intr_disable(); + next_stick(ci->ci_tick_increment); + intr_restore(s); +} + /* * Set up the real-time and statistics clocks. Leave stathz 0 only if * no alternative timer is available. @@ -338,6 +378,7 @@ tickintr_establish(int pil, int (*fun)(v void cpu_initclocks(void) { + struct cpu_info *ci = curcpu(); #ifndef MULTIPROCESSOR int statint, minint; #endif @@ -361,17 +402,24 @@ cpu_initclocks(void) } /* Make sure we have a sane cpu_clockrate -- we'll need it */ - if (!curcpu()->ci_cpu_clockrate[0]) { + if (!ci->ci_cpu_clockrate[0]) { /* Default to 200MHz clock XXXXX */ - curcpu()->ci_cpu_clockrate[0] = 200000000; - curcpu()->ci_cpu_clockrate[1] = 200000000 / 1000000; + ci->ci_cpu_clockrate[0] = 200000000; + ci->ci_cpu_clockrate[1] = 200000000 / 1000000; } /* Initialize the %tick register */ settick(0); - tick_timecounter.tc_frequency = curcpu()->ci_cpu_clockrate[0]; - tc_init(&tick_timecounter); + if (ci->ci_system_clockrate[0] == 0) { + tick_timecounter.tc_frequency = ci->ci_cpu_clockrate[0]; + tc_init(&tick_timecounter); + } else { + setstick(0); + stick_timecounter.tc_frequency = + ci->ci_system_clockrate[0]; + tc_init(&stick_timecounter); + } /* * Now handle machines w/o counter-timers. @@ -379,13 +427,21 @@ cpu_initclocks(void) if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr) { - aprint_normal("No counter-timer -- using %%tick at %luMHz as " - "system clock.\n", - (unsigned long)curcpu()->ci_cpu_clockrate[1]); - - /* We don't have a counter-timer -- use %tick */ - tickintr_establish(PIL_CLOCK, tickintr); + if (ci->ci_system_clockrate[0] == 0) { + aprint_normal("No counter-timer -- using %%tick " + "at %luMHz as system clock.\n", + (unsigned long)ci->ci_cpu_clockrate[1]); + + /* We don't have a counter-timer -- use %tick */ + tickintr_establish(PIL_CLOCK, tickintr); + } else { + aprint_normal("No counter-timer -- using %%stick " + "at %luMHz as system clock.\n", + (unsigned long)ci->ci_system_clockrate[1]); + /* We don't have a counter-timer -- use %stick */ + stickintr_establish(PIL_CLOCK, stickintr); + } /* We only have one timer so we have no statclock */ stathz = 0; @@ -525,6 +581,22 @@ tickintr(void *cap) return (1); } +int +stickintr(void *cap) +{ + int s; + + hardclock((struct clockframe *)cap); + + s = intr_disable(); + /* Reset the interrupt */ + next_stick(curcpu()->ci_tick_increment); + intr_restore(s); + curcpu()->ci_tick_evcnt.ev_count++; + + return (1); +} + #ifndef MULTIPROCESSOR /* * Level 14 (stat clock) interrupt handler. Index: src/sys/arch/sparc64/sparc64/cpu.c diff -u src/sys/arch/sparc64/sparc64/cpu.c:1.102 src/sys/arch/sparc64/sparc64/cpu.c:1.103 --- src/sys/arch/sparc64/sparc64/cpu.c:1.102 Sat Oct 27 17:18:12 2012 +++ src/sys/arch/sparc64/sparc64/cpu.c Thu Nov 8 00:34:38 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.102 2012/10/27 17:18:12 chs Exp $ */ +/* $NetBSD: cpu.c,v 1.103 2012/11/08 00:34:38 macallan Exp $ */ /* * Copyright (c) 1996 @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.102 2012/10/27 17:18:12 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.103 2012/11/08 00:34:38 macallan Exp $"); #include "opt_multiprocessor.h" @@ -242,7 +242,7 @@ void cpu_attach(device_t parent, device_t dev, void *aux) { int node; - long clk; + long clk, sclk = 0; struct mainbus_attach_args *ma = aux; struct cpu_info *ci; const char *sep; @@ -299,12 +299,23 @@ cpu_attach(device_t parent, device_t dev ci->ci_cpu_clockrate[1] = clk / 1000000; } + if (!CPU_IS_HUMMINGBIRD()) { + sclk = prom_getpropint(findroot(), "stick-frequency", 0); + } + ci->ci_system_clockrate[0] = sclk; + ci->ci_system_clockrate[1] = sclk / 1000000; + snprintf(buf, sizeof buf, "%s @ %s MHz", prom_getpropstring(node, "name"), clockfreq(clk)); snprintf(cpu_model, sizeof cpu_model, "%s (%s)", machine_model, buf); aprint_normal(": %s, UPA id %d\n", buf, ci->ci_cpuid); aprint_naive("\n"); + + if (ci->ci_system_clockrate[0] != 0) { + aprint_normal_dev(dev, "system tick frequency %d MHz\n", + (int)ci->ci_system_clockrate[1]); + } aprint_normal_dev(dev, ""); bigcache = 0; @@ -452,6 +463,8 @@ cpu_boot_secondary_processors(void) sync_tick = 1; membar_Sync(); settick(0); + if (ci->ci_system_clockrate[0] != 0) + setstick(0); setpstate(pstate); @@ -480,8 +493,12 @@ cpu_hatch(void) /* we do nothing here */ } settick(0); - - tickintr_establish(PIL_CLOCK, tickintr); + if (curcpu()->ci_system_clockrate[0] != 0) { + setstick(0); + stickintr_establish(PIL_CLOCK, stickintr); + } else { + tickintr_establish(PIL_CLOCK, tickintr); + } spl0(); } #endif /* MULTIPROCESSOR */ Index: src/sys/arch/sparc64/sparc64/locore.s diff -u src/sys/arch/sparc64/sparc64/locore.s:1.341 src/sys/arch/sparc64/sparc64/locore.s:1.342 --- src/sys/arch/sparc64/sparc64/locore.s:1.341 Sat Mar 17 22:19:53 2012 +++ src/sys/arch/sparc64/sparc64/locore.s Thu Nov 8 00:34:38 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: locore.s,v 1.341 2012/03/17 22:19:53 mrg Exp $ */ +/* $NetBSD: locore.s,v 1.342 2012/11/08 00:34:38 macallan Exp $ */ /* * Copyright (c) 2006-2010 Matthew R. Green @@ -3270,13 +3270,16 @@ ENTRY_NOPROFILE(sparc_interrupt) wrpr %g0, PSTATE_KERN|PSTATE_IG, %pstate ! DEBUG #endif /* - * If this is a %tick softint, clear it then call interrupt_vector. + * If this is a %tick or %stick softint, clear it then call + * interrupt_vector. Only one of them should be enabled at any given + * time. */ rd SOFTINT, %g1 - btst 1, %g1 + set 0x10001, %g5 + andcc %g5, %g1, %g5 bz,pt %icc, 0f sethi %hi(CPUINFO_VA+CI_TICK_IH), %g3 - wr %g0, 1, CLEAR_SOFTINT + wr %g0, %g5, CLEAR_SOFTINT ba,pt %icc, setup_sparcintr LDPTR [%g3 + %lo(CPUINFO_VA+CI_TICK_IH)], %g5 0: @@ -6058,6 +6061,77 @@ Ltick_ovflw: wr %o2, TICK_CMPR #endif +/* + * setstick(long) + */ +ENTRY(setstick) + retl + wr %o0, STICK + +/* + * long getstick(void) + */ +ENTRY(getstick) + retl + rd STICK, %o0 + +/* + * next_stick(long increment) + * + * Sets the %stick_cmpr register to fire off in `increment' machine + * cycles in the future. Also handles %stick wraparound. In 32-bit + * mode we're limited to a 32-bit increment. + */ +ENTRY(next_stick) + rd STICK_CMPR, %o2 + rd STICK, %o1 + + mov 1, %o3 ! Mask off high bits of these registers + sllx %o3, 63, %o3 + andn %o1, %o3, %o1 + andn %o2, %o3, %o2 + cmp %o1, %o2 ! Did we wrap? (tick < tick_cmpr) + bgt,pt %icc, 1f + add %o1, 1000, %o1 ! Need some slack so we don't lose intrs. + + /* + * Handle the unlikely case of %stick wrapping. + * + * This should only happen every 10 years or more. + * + * We need to increment the time base by the size of %stick in + * microseconds. This will require some divides and multiplies + * which can take time. So we re-read %stick. + * + */ + + /* XXXXX NOT IMPLEMENTED */ + + + +1: + add %o2, %o0, %o2 + andn %o2, %o3, %o4 + brlz,pn %o4, Lstick_ovflw + cmp %o2, %o1 ! Has this stick passed? + blt,pn %xcc, 1b ! Yes + nop + retl + wr %o2, STICK_CMPR + +Lstick_ovflw: +/* + * When we get here tick_cmpr has wrapped, but we don't know if %stick + * has wrapped. If bit 62 is set then we have not wrapped and we can + * use the current value of %o4 as %stick. Otherwise we need to return + * to our loop with %o4 as %stick_cmpr (%o2). + */ + srlx %o3, 1, %o5 + btst %o5, %o1 + bz,pn %xcc, 1b + mov %o4, %o2 + retl + wr %o2, STICK_CMPR ENTRY(setjmp) save %sp, -CC64FSZ, %sp ! Need a frame to return to.