summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/i386/conf/files.i3863
-rw-r--r--sys/arch/i386/i386/apm.c6
-rw-r--r--sys/arch/i386/i386/lapic.c12
-rw-r--r--sys/arch/i386/i386/machdep.c10
-rw-r--r--sys/arch/i386/include/_types.h3
-rw-r--r--sys/arch/i386/include/cpu.h21
-rw-r--r--sys/arch/i386/isa/clock.c154
7 files changed, 139 insertions, 70 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index 9a344bbbac5..54a34506343 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.155 2007/03/19 03:02:09 marco Exp $
+# $OpenBSD: files.i386,v 1.156 2007/03/19 09:29:33 art Exp $
#
# new style config file for i386 architecture
#
@@ -30,7 +30,6 @@ file arch/i386/i386/longrun.c !small_kernel & i586_cpu
file arch/i386/i386/mem.c
file arch/i386/i386/i686_mem.c mtrr
file arch/i386/i386/k6_mem.c mtrr
-file arch/i386/i386/microtime.s
file arch/i386/i386/p4tcc.c !small_kernel & i686_cpu
file arch/i386/i386/pmap.c
file arch/i386/i386/powernow.c !small_kernel & i586_cpu
diff --git a/sys/arch/i386/i386/apm.c b/sys/arch/i386/i386/apm.c
index aca6a6a1443..404c19d0204 100644
--- a/sys/arch/i386/i386/apm.c
+++ b/sys/arch/i386/i386/apm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: apm.c,v 1.73 2007/02/27 15:16:30 marco Exp $ */
+/* $OpenBSD: apm.c,v 1.74 2007/03/19 09:29:33 art Exp $ */
/*-
* Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved.
@@ -351,7 +351,7 @@ apm_resume(struct apm_softc *sc, struct apmregs *regs)
/* they say that some machines may require reinitializing the clock */
initrtclock();
- inittodr(time.tv_sec);
+ inittodr(time_second);
/* lower bit in cx means pccard was powered down */
dopowerhooks(PWR_RESUME);
apm_record_event(sc, regs->bx);
@@ -464,7 +464,7 @@ apm_handle_event(struct apm_softc *sc, struct apmregs *regs)
break;
case APM_UPDATE_TIME:
DPRINTF(("update time, please\n"));
- inittodr(time.tv_sec);
+ inittodr(time_second);
apm_record_event(sc, regs->bx);
break;
case APM_CRIT_SUSPEND_REQ:
diff --git a/sys/arch/i386/i386/lapic.c b/sys/arch/i386/i386/lapic.c
index bd74f8d5f10..3c05f8f3aec 100644
--- a/sys/arch/i386/i386/lapic.c
+++ b/sys/arch/i386/i386/lapic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lapic.c,v 1.13 2007/02/20 21:15:01 tom Exp $ */
+/* $OpenBSD: lapic.c,v 1.14 2007/03/19 09:29:33 art Exp $ */
/* $NetBSD: lapic.c,v 1.1.2.8 2000/02/23 06:10:50 sommerfeld Exp $ */
/*-
@@ -44,6 +44,7 @@
#include <sys/user.h>
#include <sys/systm.h>
#include <sys/device.h>
+#include <sys/timetc.h>
#include <uvm/uvm_extern.h>
@@ -259,8 +260,7 @@ extern void (*initclock_func)(void); /* XXX put in header file */
* We're actually using the IRQ0 timer. Hmm.
*/
void
-lapic_calibrate_timer(ci)
- struct cpu_info *ci;
+lapic_calibrate_timer(struct cpu_info *ci)
{
unsigned int starttick, tick1, tick2, endtick;
unsigned int startapic, apic1, apic2, endapic;
@@ -386,7 +386,6 @@ lapic_calibrate_timer(ci)
* for all our timing needs..
*/
delay_func = lapic_delay;
- microtime_func = lapic_microtime;
initclock_func = lapic_initclocks;
}
}
@@ -396,8 +395,7 @@ lapic_calibrate_timer(ci)
*/
void
-lapic_delay(usec)
- int usec;
+lapic_delay(int usec)
{
int32_t tick, otick;
int64_t deltat; /* XXX may want to be 64bit */
@@ -432,6 +430,7 @@ i386_ipi_microset(struct cpu_info *ci)
ci->ci_tscbase = rdtsc();
}
+#if 0
/*
* XXX need to make work correctly on other than cpu 0.
*/
@@ -457,6 +456,7 @@ lapic_microtime(tv)
*tv = now;
}
+#endif
/*
* XXX the following belong mostly or partly elsewhere..
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 9a144fb849e..3343744a8ca 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.379 2007/02/21 19:34:25 deraadt Exp $ */
+/* $OpenBSD: machdep.c,v 1.380 2007/03/19 09:29:33 art Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -256,7 +256,6 @@ void (*setperf_setup)(struct cpu_info *);
int setperf_prio = 0; /* for concurrent handlers */
void (*delay_func)(int) = i8254_delay;
-void (*microtime_func)(struct timeval *) = i8254_microtime;
void (*initclock_func)(void) = i8254_initclocks;
void (*update_cpuspeed)(void) = NULL;
@@ -3288,9 +3287,14 @@ cpu_reset()
}
void
-cpu_initclocks()
+cpu_initclocks(void)
{
(*initclock_func)();
+
+ if (initclock_func == i8254_initclocks)
+ i8254_inittimecounter();
+ else
+ i8254_inittimecounter_simple();
}
void
diff --git a/sys/arch/i386/include/_types.h b/sys/arch/i386/include/_types.h
index cef2a372f29..52cbef65faa 100644
--- a/sys/arch/i386/include/_types.h
+++ b/sys/arch/i386/include/_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: _types.h,v 1.4 2007/02/20 21:15:01 tom Exp $ */
+/* $OpenBSD: _types.h,v 1.5 2007/03/19 09:29:33 art Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -117,5 +117,6 @@ typedef void * __wctype_t;
/* Feature test macros */
#define __HAVE_CPUINFO
#define __HAVE_MUTEX
+#define __HAVE_TIMECOUNTER
#endif /* _I386__TYPES_H_ */
diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h
index a066cbea0bb..faebea52539 100644
--- a/sys/arch/i386/include/cpu.h
+++ b/sys/arch/i386/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.88 2007/03/15 10:22:29 art Exp $ */
+/* $OpenBSD: cpu.h,v 1.89 2007/03/19 09:29:33 art Exp $ */
/* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */
/*-
@@ -237,30 +237,15 @@ extern void need_resched(struct cpu_info *);
*/
extern void (*delay_func)(int);
struct timeval;
-extern void (*microtime_func)(struct timeval *);
#define DELAY(x) (*delay_func)(x)
#define delay(x) (*delay_func)(x)
-#define microtime(tv) (*microtime_func)(tv)
#if defined(I586_CPU) || defined(I686_CPU)
/*
* High resolution clock support (Pentium only)
*/
void calibrate_cyclecounter(void);
-#ifndef HZ
-extern u_quad_t pentium_base_tsc;
-#define CPU_CLOCKUPDATE() \
- do { \
- if (cpuspeed) { \
- __asm __volatile("cli\n" \
- "rdtsc\n" \
- : "=A" (pentium_base_tsc) \
- : ); \
- __asm __volatile("sti"); \
- } \
- } while (0)
-#endif
#endif
/*
@@ -357,8 +342,10 @@ void initrtclock(void);
void startrtclock(void);
void rtcdrain(void *);
void i8254_delay(int);
-void i8254_microtime(struct timeval *);
void i8254_initclocks(void);
+void i8254_inittimecounter(void);
+void i8254_inittimecounter_simple(void);
+
/* est.c */
#if !defined(SMALL_KERNEL) && defined(I686_CPU)
diff --git a/sys/arch/i386/isa/clock.c b/sys/arch/i386/isa/clock.c
index 0fd1090e682..f3b34498b3a 100644
--- a/sys/arch/i386/isa/clock.c
+++ b/sys/arch/i386/isa/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.38 2006/12/20 17:50:40 gwk Exp $ */
+/* $OpenBSD: clock.c,v 1.39 2007/03/19 09:29:33 art Exp $ */
/* $NetBSD: clock.c,v 1.39 1996/05/12 23:11:54 mycroft Exp $ */
/*-
@@ -92,6 +92,8 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/timeout.h>
+#include <sys/timetc.h>
+#include <sys/mutex.h>
#include <machine/cpu.h>
#include <machine/intr.h>
@@ -105,7 +107,6 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <i386/isa/timerreg.h>
void spinwait(int);
-void findcpuspeed(void);
int clockintr(void *);
int gettick(void);
int rtcget(mc_todregs *);
@@ -125,6 +126,19 @@ int cpuspeed;
int clock_broken_latch;
#endif
+/* Timecounter on the i8254 */
+uint32_t i8254_lastcount;
+uint32_t i8254_offset;
+int i8254_ticked;
+u_int i8254_get_timecount(struct timecounter *tc);
+u_int i8254_simple_get_timecount(struct timecounter *tc);
+
+static struct timecounter i8254_timecounter = {
+ i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL
+};
+struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH);
+u_long rtclock_tval;
+
#define SECMIN ((unsigned)60) /* seconds per minute */
#define SECHOUR ((unsigned)(60*SECMIN)) /* seconds per hour */
@@ -161,8 +175,6 @@ startrtclock(void)
{
int s;
- findcpuspeed(); /* use the clock (while it's free)
- to find the cpu speed */
initrtclock();
/* Check diagnostic status */
@@ -190,12 +202,17 @@ rtcdrain(void *v)
void
initrtclock(void)
{
+ mtx_enter(&timer_mutex);
+
/* initialize 8253 clock */
outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
/* Correct rounding will buy us a better precision in timekeeping */
outb(IO_TIMER1, TIMER_DIV(hz) % 256);
outb(IO_TIMER1, TIMER_DIV(hz) / 256);
+
+ rtclock_tval = TIMER_DIV(hz);
+ mtx_leave(&timer_mutex);
}
int
@@ -203,6 +220,15 @@ clockintr(void *arg)
{
struct clockframe *frame = arg; /* not strictly necessary */
+ if (timecounter->tc_get_timecount == i8254_get_timecount) {
+ if (i8254_ticked) {
+ i8254_ticked = 0;
+ } else {
+ i8254_offset += rtclock_tval;
+ i8254_lastcount = 0;
+ }
+ }
+
hardclock(frame);
return (1);
}
@@ -233,6 +259,11 @@ gettick(void)
int v1, v2, v3;
int w1, w2, w3;
+ /*
+ * Don't lock the mutex in this case, clock_broken_latch
+ * CPUs don't do MP anyway.
+ */
+
disable_intr();
v1 = inb(TIMER_CNTR0);
@@ -279,14 +310,18 @@ gettick(void)
#endif
{
u_char lo, hi;
+ u_long ef;
+ mtx_enter(&timer_mutex);
+ ef = read_eflags();
disable_intr();
/* Select counter 0 and latch it. */
outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
lo = inb(TIMER_CNTR0);
hi = inb(TIMER_CNTR0);
- enable_intr();
+ write_eflags(ef);
+ mtx_leave(&timer_mutex);
return ((hi << 8) | lo);
}
}
@@ -350,31 +385,6 @@ i8254_delay(int n)
}
}
-unsigned int delaycount; /* calibrated loop variable (1 millisecond) */
-
-#define FIRST_GUESS 0x2000
-
-void
-findcpuspeed(void)
-{
- int i;
- int remainder;
-
- /* Put counter in count down mode */
- outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
- outb(TIMER_CNTR0, 0xff);
- outb(TIMER_CNTR0, 0xff);
- for (i = FIRST_GUESS; i; i--)
- ;
- /* Read the value left in the counter */
- remainder = gettick();
- /*
- * Formula for delaycount is:
- * (loopcount * timer clock speed) / (counter ticks * 1000)
- */
- delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff-remainder);
-}
-
#if defined(I586_CPU) || defined(I686_CPU)
void
calibrate_cyclecounter(void)
@@ -537,10 +547,14 @@ clock_expandyear(int clockyear)
void
inittodr(time_t base)
{
+ struct timespec ts;
mc_todregs rtclk;
struct clock_ymdhms dt;
int s;
+
+ ts.tv_nsec = 0;
+
/*
* We mostly ignore the suggested time and go for the RTC clock time
* stored in the CMOS RAM. If the time can't be obtained from the
@@ -555,8 +569,6 @@ inittodr(time_t base)
base = 17*SECYR + 186*SECDAY + SECDAY/2;
}
- time.tv_usec = 0;
-
s = splclock();
if (rtcget(&rtclk)) {
splx(s);
@@ -592,24 +604,26 @@ inittodr(time_t base)
}
}
- time.tv_sec = clock_ymdhms_to_secs(&dt) + tz.tz_minuteswest * 60;
+ ts.tv_sec = clock_ymdhms_to_secs(&dt) + tz.tz_minuteswest * 60;
if (tz.tz_dsttime)
- time.tv_sec -= 3600;
+ ts.tv_sec -= 3600;
- if (base < time.tv_sec - 5*SECYR)
+ if (base < ts.tv_sec - 5*SECYR)
printf("WARNING: file system time much less than clock time\n");
- else if (base > time.tv_sec + 5*SECYR) {
+ else if (base > ts.tv_sec + 5*SECYR) {
printf("WARNING: clock time much less than file system time\n");
printf("WARNING: using file system time\n");
goto fstime;
}
+ tc_setclock(&ts);
timeset = 1;
return;
fstime:
+ ts.tv_sec = base;
+ tc_setclock(&ts);
timeset = 1;
- time.tv_sec = base;
printf("WARNING: CHECK AND RESET THE DATE!\n");
}
@@ -640,7 +654,7 @@ resettodr(void)
diff = tz.tz_minuteswest * 60;
if (tz.tz_dsttime)
diff -= 3600;
- clock_secs_to_ymdhms(time.tv_sec - diff, &dt);
+ clock_secs_to_ymdhms(time_second - diff, &dt);
rtclk[MC_SEC] = dectohexdec(dt.dt_sec);
rtclk[MC_MIN] = dectohexdec(dt.dt_min);
@@ -666,3 +680,67 @@ setstatclockrate(int arg)
else
mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz);
}
+
+void
+i8254_inittimecounter(void)
+{
+ tc_init(&i8254_timecounter);
+}
+
+/*
+ * If we're using lapic to drive hardclock, we can use a simpler
+ * algorithm for the i8254 timecounters.
+ */
+void
+i8254_inittimecounter_simple(void)
+{
+ u_long tval = 0x8000;
+
+ i8254_timecounter.tc_get_timecount = i8254_simple_get_timecount;
+ i8254_timecounter.tc_counter_mask = 0x7fff;
+
+ i8254_timecounter.tc_frequency = TIMER_FREQ;
+
+ mtx_enter(&timer_mutex);
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+ outb(IO_TIMER1, tval & 0xff);
+ outb(IO_TIMER1, tval >> 8);
+
+ rtclock_tval = tval;
+ mtx_leave(&timer_mutex);
+
+ tc_init(&i8254_timecounter);
+}
+
+u_int
+i8254_simple_get_timecount(struct timecounter *tc)
+{
+ return (rtclock_tval - gettick());
+}
+
+u_int
+i8254_get_timecount(struct timecounter *tc)
+{
+ u_char hi, lo;
+ u_int count;
+ u_long ef;
+
+ ef = read_eflags();
+ disable_intr();
+
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+ lo = inb(TIMER_CNTR0);
+ hi = inb(TIMER_CNTR0);
+
+ count = rtclock_tval - ((hi << 8) | lo);
+
+ if (count < i8254_lastcount) {
+ i8254_ticked = 1;
+ i8254_offset += rtclock_tval;
+ }
+ i8254_lastcount = count;
+ count += i8254_offset;
+ write_eflags(ef);
+
+ return (count);
+}