summaryrefslogtreecommitdiff
path: root/sys/arch/amd64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-04-28 12:58:29 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-04-28 12:58:29 +0000
commit24ee44d5c45a34741b11031b1bc91780b2dcbf50 (patch)
treeb19ba67f2ac16694b2da626250ccf27bc69fc9c3 /sys/arch/amd64
parent6887b193b9ca540f1400351cad1d1dbf7dca36b2 (diff)
Use the same inittodr()/resettodr() implementation as on arm64/armv7/sparc64
and move it to the end of machdep.c. Rework the actual implementation for te MC14818 compatible RTC into something that can be used as a todr_handle. ok mpi@
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r--sys/arch/amd64/amd64/machdep.c92
-rw-r--r--sys/arch/amd64/include/cpu.h3
-rw-r--r--sys/arch/amd64/isa/clock.c97
3 files changed, 121 insertions, 71 deletions
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
index 21c88098743..ddb7315a03d 100644
--- a/sys/arch/amd64/amd64/machdep.c
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.261 2020/01/24 05:27:31 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.262 2020/04/28 12:58:27 kettenis Exp $ */
/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
/*-
@@ -277,6 +277,7 @@ cpu_startup(void)
printf("%s", version);
startclocks();
+ rtcinit();
printf("real mem = %lu (%luMB)\n", ptoa((psize_t)physmem),
ptoa((psize_t)physmem)/1024/1024);
@@ -2066,3 +2067,92 @@ check_context(const struct reg *regs, struct trapframe *tf)
return 0;
}
+
+#include <sys/timetc.h>
+#include <dev/clock_subr.h>
+
+todr_chip_handle_t todr_handle;
+
+#define MINYEAR ((OpenBSD / 100) - 1) /* minimum plausible year */
+
+/*
+ * inittodr:
+ *
+ * Initialize time from the time-of-day register.
+ */
+void
+inittodr(time_t base)
+{
+ time_t deltat;
+ struct timeval rtctime;
+ struct timespec ts;
+ int badbase;
+
+ if (base < (MINYEAR - 1970) * SECYR) {
+ printf("WARNING: preposterous time in file system\n");
+ /* read the system clock anyway */
+ base = (MINYEAR - 1970) * SECYR;
+ badbase = 1;
+ } else
+ badbase = 0;
+
+ if (todr_handle == NULL ||
+ todr_gettime(todr_handle, &rtctime) != 0 ||
+ rtctime.tv_sec < (MINYEAR - 1970) * SECYR) {
+ /*
+ * Believe the time in the file system for lack of
+ * anything better, resetting the TODR.
+ */
+ rtctime.tv_sec = base;
+ rtctime.tv_usec = 0;
+ if (todr_handle != NULL && !badbase)
+ printf("WARNING: bad clock chip time\n");
+ ts.tv_sec = rtctime.tv_sec;
+ ts.tv_nsec = rtctime.tv_usec * 1000;
+ tc_setclock(&ts);
+ goto bad;
+ } else {
+ ts.tv_sec = rtctime.tv_sec;
+ ts.tv_nsec = rtctime.tv_usec * 1000;
+ tc_setclock(&ts);
+ }
+
+ if (!badbase) {
+ /*
+ * See if we gained/lost two or more days; if
+ * so, assume something is amiss.
+ */
+ deltat = rtctime.tv_sec - base;
+ if (deltat < 0)
+ deltat = -deltat;
+ if (deltat < 2 * SECDAY)
+ return; /* all is well */
+#ifndef SMALL_KERNEL
+ printf("WARNING: clock %s %lld days\n",
+ rtctime.tv_sec < base ? "lost" : "gained",
+ (long long)(deltat / SECDAY));
+#endif
+ }
+ bad:
+ printf("WARNING: CHECK AND RESET THE DATE!\n");
+}
+
+/*
+ * resettodr:
+ *
+ * Reset the time-of-day register with the current time.
+ */
+void
+resettodr(void)
+{
+ struct timeval rtctime;
+
+ if (time_second == 1)
+ return;
+
+ microtime(&rtctime);
+
+ if (todr_handle != NULL &&
+ todr_settime(todr_handle, &rtctime) != 0)
+ printf("WARNING: can't update clock chip time\n");
+}
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
index df98aafcc3b..0c96b8abde8 100644
--- a/sys/arch/amd64/include/cpu.h
+++ b/sys/arch/amd64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.134 2020/04/15 16:38:24 kettenis Exp $ */
+/* $OpenBSD: cpu.h,v 1.135 2020/04/28 12:58:28 kettenis Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@@ -390,6 +390,7 @@ void proc_trampoline(void);
/* clock.c */
extern void (*initclock_func)(void);
void startclocks(void);
+void rtcinit(void);
void rtcstart(void);
void rtcstop(void);
void i8254_delay(int);
diff --git a/sys/arch/amd64/isa/clock.c b/sys/arch/amd64/isa/clock.c
index b80bcf7c647..a93b1a160f0 100644
--- a/sys/arch/amd64/isa/clock.c
+++ b/sys/arch/amd64/isa/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.31 2019/08/21 20:44:09 cheloha Exp $ */
+/* $OpenBSD: clock.c,v 1.32 2020/04/28 12:58:28 kettenis Exp $ */
/* $NetBSD: clock.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
/*-
@@ -86,8 +86,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* Primitive clock interrupt routines.
*/
-/* #define CLOCKDEBUG */
-/* #define CLOCK_PARANOIA */
+/* #define CLOCK_DEBUG */
#include <sys/param.h>
#include <sys/systm.h>
@@ -101,6 +100,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <machine/pio.h>
#include <machine/cpufunc.h>
+#include <dev/clock_subr.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <dev/ic/mc146818reg.h>
@@ -344,8 +344,6 @@ bintobcd(int n)
return ((u_char)(((n / 10) << 4) & 0xf0) | ((n % 10) & 0x0f));
}
-static int timeset;
-
/*
* check whether the CMOS layout is "standard"-like (ie, not PS/2-like),
* to be called at splclock()
@@ -422,47 +420,21 @@ clock_expandyear(int clockyear)
return (clockyear);
}
-/*
- * Initialize the time of day register, based on the time base which is, e.g.
- * from a filesystem.
- */
-void
-inittodr(time_t base)
+int
+rtcgettime(struct todr_chip_handle *handle, struct timeval *tv)
{
- struct timespec ts;
mc_todregs rtclk;
struct clock_ymdhms dt;
int s;
-
- ts.tv_nsec = 0;
-
- /*
- * We mostly ignore the suggested time (which comes from the
- * file system) and go for the RTC clock time stored in the
- * CMOS RAM. If the time can't be obtained from the CMOS, or
- * if the time obtained from the CMOS is 5 or more years less
- * than the suggested time, we used the suggested time. (In
- * the latter case, it's likely that the CMOS battery has
- * died.)
- */
-
- /*
- * if the file system time is more than a year older than the
- * kernel, warn and then set the base time to the CONFIG_TIME.
- */
- if (base < 30*SECYR) { /* if before 2000, something's odd... */
- printf("WARNING: preposterous time in file system\n");
- base = 30*SECYR;
- }
-
+
s = splclock();
if (rtcget(&rtclk)) {
splx(s);
- printf("WARNING: invalid time in clock chip\n");
- goto fstime;
+ return EINVAL;
}
splx(s);
-#ifdef DEBUG_CLOCK
+
+#ifdef CLOCK_DEBUG
printf("readclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR],
rtclk[MC_MONTH], rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN],
rtclk[MC_SEC]);
@@ -475,44 +447,18 @@ inittodr(time_t base)
dt.dt_mon = bcdtobin(rtclk[MC_MONTH]);
dt.dt_year = clock_expandyear(bcdtobin(rtclk[MC_YEAR]));
- ts.tv_sec = clock_ymdhms_to_secs(&dt) - utc_offset;
-
- if (base != 0 && base < ts.tv_sec - 5*SECYR)
- printf("WARNING: file system time much less than clock time\n");
- 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;
- printf("WARNING: CHECK AND RESET THE DATE!\n");
+ tv->tv_sec = clock_ymdhms_to_secs(&dt) - utc_offset;
+ tv->tv_usec = 0;
+ return 0;
}
-/*
- * Reset the clock.
- */
-void
-resettodr(void)
+int
+rtcsettime(struct todr_chip_handle *handle, struct timeval *tv)
{
mc_todregs rtclk;
struct clock_ymdhms dt;
int century, s;
- /*
- * We might have been called by boot() due to a crash early
- * on. Don't reset the clock chip in this case.
- */
- if (!timeset)
- return;
-
s = splclock();
if (rtcget(&rtclk))
memset(&rtclk, 0, sizeof(rtclk));
@@ -528,10 +474,11 @@ resettodr(void)
rtclk[MC_MONTH] = bintobcd(dt.dt_mon);
rtclk[MC_DOM] = bintobcd(dt.dt_day);
-#ifdef DEBUG_CLOCK
+#ifdef CLOCK_DEBUG
printf("setclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH],
rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]);
#endif
+
s = splclock();
rtcput(&rtclk);
if (rtc_update_century > 0) {
@@ -539,6 +486,18 @@ resettodr(void)
mc146818_write(NULL, centb, century); /* XXX softc */
}
splx(s);
+ return 0;
+}
+
+extern todr_chip_handle_t todr_handle;
+struct todr_chip_handle rtc_todr;
+
+void
+rtcinit(void)
+{
+ rtc_todr.todr_gettime = rtcgettime;
+ rtc_todr.todr_settime = rtcsettime;
+ todr_handle = &rtc_todr;
}
void