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.
This commit is contained in:
Garrett Wollman 1994-08-15 03:15:20 +00:00
parent 99ca219150
commit 8ea838500f
9 changed files with 324 additions and 25 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */