tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Patch: more than 1 TOD clock



Hi,

From a conversation with Martin, where he noticed that the TOD clock
jumped forward each boot by around 30 minutes.  On his machine (Sun V210)
there are 2 TOD clocks.  We attach the first, but the boot firmware and
the out-of-band monitor prefer the second.

It looks straightforward to support multiple TOD clocks, if we read only
from the first and write to all of them.  I've done this in the attached
patch and both TOD clocks are recognised and written to:

  [   1.0000000] rtc0 at ebus0 addr 70-71: mc146818 compatible time-of-day clock: m5819p

  [   1.0000000] dsrtc0 at iic0 addr 0x68: DS1307 Real-time Clock/NVRAM
  [   1.0000000] (secondary clock)

Any thoughts on the idea/implementation?  Note, that I've only tested on
one machine with the 2 TOD clocks so far.

Thanks and regards,

Julian
-- 
--- src/sys/kern/kern_todr.c.dist	2026-01-23 16:30:48.189998898 +0100
+++ src/sys/kern/kern_todr.c	2026-02-09 17:43:11.619996310 +0100
@@ -78,6 +78,7 @@
 #include <sys/device_calls.h>
 #include <sys/intr.h>
 #include <sys/kernel.h>
+#include <sys/kmem.h>
 #include <sys/mutex.h>
 #include <sys/rndsource.h>
 #include <sys/sdt.h>
@@ -86,11 +87,17 @@
 
 #include <dev/clock_subr.h>	/* hmm.. this should probably move to sys */
 
+struct todr_list {
+	todr_chip_handle_t todr_handle;
+	struct todr_list *todr_next;
+};
+
 static int todr_gettime(todr_chip_handle_t, struct timeval *);
 static int todr_settime(todr_chip_handle_t, struct timeval *);
 
 static kmutex_t todr_mutex;
-static todr_chip_handle_t todr_handle;
+static struct todr_list todr_head =
+	{ .todr_handle = NULL, .todr_next = NULL };
 static bool todr_initialized;
 
 /* The minimum reasonable RTC date before preposterousness */
@@ -179,6 +186,7 @@
 void
 todr_attach(todr_chip_handle_t todr)
 {
+	struct todr_list *todr_newp, *todr_iterp;
 
 	/*
 	 * todr_init() is called very early in main(), but this is
@@ -191,13 +199,22 @@
 		return;
 	}
 
-	todr_lock();
-	if (todr_handle) {
-		todr_unlock();
-		printf("todr_attach: TOD already configured\n");
-		return;
+	/* Initial entry is static, others allocated. */
+	if (todr_head.todr_handle != NULL) {
+		todr_newp = kmem_alloc(sizeof(struct todr_list),
+		    KM_SLEEP);
+		todr_newp->todr_next = NULL;
+		todr_lock();
+		todr_newp->todr_handle = todr;
+		todr_iterp = &todr_head;
+		while (todr_iterp->todr_next != NULL)
+			todr_iterp = todr_iterp->todr_next;
+		todr_iterp->todr_next = todr_newp;
+		printf("(secondary clock)\n");
+	} else {
+		todr_lock();
+		todr_head.todr_handle = todr;
 	}
-	todr_handle = todr;
 	todr_unlock();
 }
 
@@ -246,16 +263,17 @@
 	/*
 	 * Some ports need to be supplied base in order to fabricate a time_t.
 	 */
-	if (todr_handle)
-		todr_handle->todr_base_time = base;
+	if (todr_head.todr_handle != NULL)
+		todr_head.todr_handle->todr_base_time = base;
 
 	memset(&tv, 0, sizeof(tv));
 
-	if ((todr_handle == NULL) ||
-	    (todr_gettime(todr_handle, &tv) != 0) ||
+	/* Note, that we only read time from the first RTC. */
+	if ((todr_head.todr_handle == NULL) ||
+	    (todr_gettime(todr_head.todr_handle, &tv) != 0) ||
 	    (tv.tv_sec < (PREPOSTEROUS_YEARS * SECS_PER_COMMON_YEAR))) {
 
-		if (todr_handle != NULL)
+		if (todr_head.todr_handle != NULL)
 			printf("WARNING: preposterous TOD clock time\n");
 		else
 			printf("WARNING: no TOD clock present\n");
@@ -322,6 +340,7 @@
 todr_save_systime(void)
 {
 	struct timeval tv;
+	struct todr_list *todr_iterp;
 
 	KASSERT(todr_lock_owned());
 
@@ -338,9 +357,14 @@
 	if (tv.tv_sec == 0)
 		return;
 
-	if (todr_handle)
-		if (todr_settime(todr_handle, &tv) != 0)
-			printf("Cannot set TOD clock time\n");
+	todr_iterp = &todr_head;
+	do {
+printf("Saving system time to a TOD clock\n");
+		if (todr_iterp->todr_handle != NULL)
+			if (todr_settime(todr_iterp->todr_handle, &tv) != 0)
+				printf("Cannot set TOD clock time\n");
+		todr_iterp = todr_iterp->todr_next;
+	} while (todr_iterp != NULL);
 }
 
 /*


Home | Main Index | Thread Index | Old Index