summaryrefslogtreecommitdiffstats
path: root/sys/amd64
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/amd64
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/amd64')
-rw-r--r--sys/amd64/amd64/tsc.c60
-rw-r--r--sys/amd64/isa/clock.c60
2 files changed, 112 insertions, 8 deletions
diff --git a/sys/amd64/amd64/tsc.c b/sys/amd64/amd64/tsc.c
index cf0a7f6..35f2e42 100644
--- a/sys/amd64/amd64/tsc.c
+++ b/sys/amd64/amd64/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/amd64/isa/clock.c b/sys/amd64/isa/clock.c
index cf0a7f6..35f2e42 100644
--- a/sys/amd64/isa/clock.c
+++ b/sys/amd64/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);
}
OpenPOWER on IntegriCloud