Use %sys_tick to generate clock interrupts on systems that have it.
authorkettenis <kettenis@openbsd.org>
Thu, 7 Aug 2008 21:25:47 +0000 (21:25 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 7 Aug 2008 21:25:47 +0000 (21:25 +0000)
sys/arch/sparc64/include/cpu.h
sys/arch/sparc64/include/ctlreg.h
sys/arch/sparc64/sparc64/clock.c
sys/arch/sparc64/sparc64/cpu.c
sys/arch/sparc64/sparc64/locore.s

index 08a9a48..de4057b 100644 (file)
@@ -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 *);
index e033f7e..68b13fc 100644 (file)
@@ -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_ */
index a401897..329cf66 100644 (file)
@@ -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)
 {
index 193cebc..2d0dd14 100644 (file)
@@ -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());
index bb5d4df..f996fa7 100644 (file)
@@ -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