summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1994-08-15 03:15:20 +0000
committerwollman <wollman@FreeBSD.org>1994-08-15 03:15:20 +0000
commitd1747d99343973bfb8d64254147b2e1b0ac5ab63 (patch)
treed219bc60ff8562e306a361c7b99cc4c08812feb6 /sys/i386
parentbe8746b39613d0e068e09206d4660427a1735576 (diff)
downloadFreeBSD-src-d1747d99343973bfb8d64254147b2e1b0ac5ab63.zip
FreeBSD-src-d1747d99343973bfb8d64254147b2e1b0ac5ab63.tar.gz
Enable use of the RTC chip for the statistical clock. While this does
not provide the full accuracy of a randomized statistical clock, it does provide greater accuracy than the previous method, while not significantly increasing overhead. It also provides profiling support at 1024 Hz. You must re-compile config before making a new kernel, or you will end up with unresolved symbols. Reviewed uy: Bruce evans said it worked for him.
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/tsc.c60
-rw-r--r--sys/i386/include/spl.h5
-rw-r--r--sys/i386/isa/clock.c60
-rw-r--r--sys/i386/isa/icu.s4
-rw-r--r--sys/i386/isa/rtc.h20
5 files changed, 137 insertions, 12 deletions
diff --git a/sys/i386/i386/tsc.c b/sys/i386/i386/tsc.c
index cf0a7f6..35f2e42 100644
--- a/sys/i386/i386/tsc.c
+++ b/sys/i386/i386/tsc.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.12 1994/08/11 00:28:24 wollman Exp $
+ * $Id: clock.c,v 1.13 1994/08/13 03:49:56 wollman Exp $
*/
/*
@@ -60,6 +60,7 @@
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
void hardclock();
+void statclock();
static int beeping;
int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */
u_int timer0_prescale;
@@ -102,6 +103,44 @@ clkintr(frame)
hardclock(&frame);
}
+static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
+
+/*
+ * This routine receives statistical clock interrupts from the RTC.
+ * As explained above, these occur at 128 interrupts per second.
+ * When profiling, we receive interrupts at a rate of 1024 Hz.
+ *
+ * This does not actually add as much overhead as it sounds, because
+ * when the statistical clock is active, the hardclock driver no longer
+ * needs to keep (inaccurate) statistics on its own. This decouples
+ * statistics gathering from scheduling interrupts.
+ *
+ * The RTC chip requires that we read status register C (RTC_INTR)
+ * to acknowledge an interrupt, before it will generate the next one.
+ */
+void
+rtcintr(struct clockframe frame)
+{
+ u_char stat;
+ stat = rtcin(RTC_INTR);
+ if(stat & RTCIR_PERIOD) {
+ statclock(&frame);
+ }
+}
+
+#ifdef DEBUG
+void
+printrtc(void)
+{
+ outb(IO_RTC, RTC_STATUSA);
+ printf("RTC status A = %x", inb(IO_RTC+1));
+ outb(IO_RTC, RTC_STATUSB);
+ printf(", B = %x", inb(IO_RTC+1));
+ outb(IO_RTC, RTC_INTR);
+ printf(", C = %x\n", inb(IO_RTC+1));
+}
+#endif
+
#if 0
void
timerintr(struct clockframe frame)
@@ -338,9 +377,9 @@ startrtclock()
/* initialize brain-dead battery powered clock */
outb (IO_RTC, RTC_STATUSA);
- outb (IO_RTC+1, 0x26);
+ outb (IO_RTC+1, rtc_statusa);
outb (IO_RTC, RTC_STATUSB);
- outb (IO_RTC+1, 2);
+ outb (IO_RTC+1, RTCSB_24HR);
outb (IO_RTC, RTC_DIAG);
if (s = inb (IO_RTC+1))
@@ -460,13 +499,17 @@ test_inittodr(time_t base)
*/
#define V(s) __CONCAT(V, s)
extern void V(clk)();
-
+extern void V(rtc)();
void
enablertclock()
{
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
INTREN(IRQ0);
+ setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL);
+ INTREN(IRQ8);
+ outb(IO_RTC, RTC_STATUSB);
+ outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR);
}
@@ -482,10 +525,19 @@ spinwait(int millisecs)
void
cpu_initclocks()
{
+ stathz = RTC_NOPROFRATE;
+ profhz = RTC_PROFRATE;
enablertclock();
}
void
setstatclockrate(int newhz)
{
+ if(newhz == RTC_PROFRATE) {
+ rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
+ } else {
+ rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
+ }
+ outb(IO_RTC, RTC_STATUSA);
+ outb(IO_RTC+1, rtc_statusa);
}
diff --git a/sys/i386/include/spl.h b/sys/i386/include/spl.h
index 739fc20..2a9c1dc 100644
--- a/sys/i386/include/spl.h
+++ b/sys/i386/include/spl.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: spl.h,v 1.3 1994/08/02 07:39:06 davidg Exp $
*/
#ifndef _MACHINE_IPL_H_
@@ -79,6 +79,7 @@ extern unsigned net_imask; /* group of interrupts masked with splimp() */
extern volatile unsigned ipending; /* active interrupts masked by cpl */
extern volatile unsigned netisr;
extern unsigned tty_imask; /* group of interrupts masked with spltty() */
+extern unsigned stat_imask; /* interrupts masked with splstatclock() */
/*
* ipending has to be volatile so that it is read every time it is accessed
@@ -110,7 +111,7 @@ static __inline int name(void) \
GENSPL(splbio, cpl |= bio_imask)
GENSPL(splclock, cpl = HWI_MASK | SWI_MASK)
GENSPL(splhigh, cpl = HWI_MASK | SWI_MASK)
-GENSPL(splstatclock, cpl = HWI_MASK | SWI_MASK)
+GENSPL(splstatclock, cpl |= stat_imask | SWI_CLOCK_MASK)
GENSPL(splimp, cpl |= net_imask)
GENSPL(splnet, cpl |= SWI_NET_MASK)
GENSPL(splsoftclock, cpl = SWI_CLOCK_MASK)
diff --git a/sys/i386/isa/clock.c b/sys/i386/isa/clock.c
index cf0a7f6..35f2e42 100644
--- a/sys/i386/isa/clock.c
+++ b/sys/i386/isa/clock.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)clock.c 7.2 (Berkeley) 5/12/91
- * $Id: clock.c,v 1.12 1994/08/11 00:28:24 wollman Exp $
+ * $Id: clock.c,v 1.13 1994/08/13 03:49:56 wollman Exp $
*/
/*
@@ -60,6 +60,7 @@
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
void hardclock();
+void statclock();
static int beeping;
int timer0_divisor = TIMER_DIV(100); /* XXX should be hz */
u_int timer0_prescale;
@@ -102,6 +103,44 @@ clkintr(frame)
hardclock(&frame);
}
+static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
+
+/*
+ * This routine receives statistical clock interrupts from the RTC.
+ * As explained above, these occur at 128 interrupts per second.
+ * When profiling, we receive interrupts at a rate of 1024 Hz.
+ *
+ * This does not actually add as much overhead as it sounds, because
+ * when the statistical clock is active, the hardclock driver no longer
+ * needs to keep (inaccurate) statistics on its own. This decouples
+ * statistics gathering from scheduling interrupts.
+ *
+ * The RTC chip requires that we read status register C (RTC_INTR)
+ * to acknowledge an interrupt, before it will generate the next one.
+ */
+void
+rtcintr(struct clockframe frame)
+{
+ u_char stat;
+ stat = rtcin(RTC_INTR);
+ if(stat & RTCIR_PERIOD) {
+ statclock(&frame);
+ }
+}
+
+#ifdef DEBUG
+void
+printrtc(void)
+{
+ outb(IO_RTC, RTC_STATUSA);
+ printf("RTC status A = %x", inb(IO_RTC+1));
+ outb(IO_RTC, RTC_STATUSB);
+ printf(", B = %x", inb(IO_RTC+1));
+ outb(IO_RTC, RTC_INTR);
+ printf(", C = %x\n", inb(IO_RTC+1));
+}
+#endif
+
#if 0
void
timerintr(struct clockframe frame)
@@ -338,9 +377,9 @@ startrtclock()
/* initialize brain-dead battery powered clock */
outb (IO_RTC, RTC_STATUSA);
- outb (IO_RTC+1, 0x26);
+ outb (IO_RTC+1, rtc_statusa);
outb (IO_RTC, RTC_STATUSB);
- outb (IO_RTC+1, 2);
+ outb (IO_RTC+1, RTCSB_24HR);
outb (IO_RTC, RTC_DIAG);
if (s = inb (IO_RTC+1))
@@ -460,13 +499,17 @@ test_inittodr(time_t base)
*/
#define V(s) __CONCAT(V, s)
extern void V(clk)();
-
+extern void V(rtc)();
void
enablertclock()
{
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
INTREN(IRQ0);
+ setidt(ICU_OFFSET+8, &V(rtc), SDT_SYS386IGT, SEL_KPL);
+ INTREN(IRQ8);
+ outb(IO_RTC, RTC_STATUSB);
+ outb(IO_RTC+1, RTCSB_PINTR | RTCSB_24HR);
}
@@ -482,10 +525,19 @@ spinwait(int millisecs)
void
cpu_initclocks()
{
+ stathz = RTC_NOPROFRATE;
+ profhz = RTC_PROFRATE;
enablertclock();
}
void
setstatclockrate(int newhz)
{
+ if(newhz == RTC_PROFRATE) {
+ rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
+ } else {
+ rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
+ }
+ outb(IO_RTC, RTC_STATUSA);
+ outb(IO_RTC+1, rtc_statusa);
}
diff --git a/sys/i386/isa/icu.s b/sys/i386/isa/icu.s
index 6d897d7..735eeda 100644
--- a/sys/i386/isa/icu.s
+++ b/sys/i386/isa/icu.s
@@ -36,7 +36,7 @@
*
* @(#)icu.s 7.2 (Berkeley) 5/21/91
*
- * $Id: icu.s,v 1.9 1994/05/25 08:58:55 rgrimes Exp $
+ * $Id: icu.s,v 1.10 1994/08/13 03:50:01 wollman Exp $
*/
/*
@@ -58,6 +58,8 @@ _cpl: .long HWI_MASK | SWI_MASK /* current priority (all off) */
.globl _imen
_imen: .long HWI_MASK /* interrupt mask enable (all h/w off) */
_high_imask: .long HWI_MASK | SWI_MASK
+ .globl _stat_imask
+_stat_imask: .long (1 << 8)
.globl _tty_imask
_tty_imask: .long 0
.globl _bio_imask
diff --git a/sys/i386/isa/rtc.h b/sys/i386/isa/rtc.h
index ba008b6..9c0f501 100644
--- a/sys/i386/isa/rtc.h
+++ b/sys/i386/isa/rtc.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)rtc.h 7.1 (Berkeley) 5/12/91
- * $Id: rtc.h,v 1.3 1993/11/07 17:44:34 wollman Exp $
+ * $Id: rtc.h,v 1.4 1993/12/18 01:12:47 ache Exp $
*/
#ifndef _I386_ISA_RTC_H_
@@ -54,10 +54,28 @@
#define RTC_DAY 0x07 /* day of month */
#define RTC_MONTH 0x08 /* month of year */
#define RTC_YEAR 0x09 /* month of year */
+
#define RTC_STATUSA 0x0a /* status register A */
#define RTCSA_TUP 0x80 /* time update, don't look now */
+#define RTCSA_DIVIDER 0x20 /* divider correct for 32768 Hz */
+#define RTCSA_8192 0x03
+#define RTCSA_4096 0x04
+#define RTCSA_2048 0x05
+#define RTCSA_1024 0x06 /* default for profiling */
+#define RTCSA_PROF RTCSA_1024
+#define RTC_PROFRATE 1024
+#define RTCSA_512 0x07
+#define RTCSA_256 0x08
+#define RTCSA_128 0x09
+#define RTCSA_NOPROF RTCSA_128
+#define RTC_NOPROFRATE 128
+#define RTCSA_64 0x0a
+#define RTCSA_32 0x0b
#define RTC_STATUSB 0x0b /* status register B */
+#define RTCSB_HALT 0x80 /* stop clock updates */
+#define RTCSB_PINTR 0x40 /* periodic clock interrupt */
+#define RTCSB_24HR 0x02 /* 24-hour mode */
#define RTC_INTR 0x0c /* status register C (R) interrupt source */
#define RTCIR_UPDATE 0x10 /* update intr */
OpenPOWER on IntegriCloud