Module Name:    src
Committed By:   thorpej
Date:           Wed Mar  6 07:34:11 UTC 2024

Modified Files:
        src/sys/arch/alpha/alpha: mcclock.c mcclockvar.h
        src/sys/arch/alpha/gbus: mcclock_gbus.c

Log Message:
Alpha systems based on the "Laser" and "TurboLaser" system architecture
have an interesting feature: the RTC and console UART are present on each
CPU module, but only those peripherals on the "primary" CPU module matter,
because each CPU's module's periperals are mapped to the same physical
address, but are only accessible by that CPU module.  The firmware selects
a primary CPU to boot the system, and that CPU's RTC and UART are the
system RTC and console, respectively.

To handle this, on systems where it's needed, we wrap the RTC gettime/settime
calls and, if not running on the primary CPU already, cross-call to the primary
to perform the RTC access.


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/alpha/alpha/mcclock.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/alpha/alpha/mcclockvar.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/alpha/gbus/mcclock_gbus.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/alpha/alpha/mcclock.c
diff -u src/sys/arch/alpha/alpha/mcclock.c:1.22 src/sys/arch/alpha/alpha/mcclock.c:1.23
--- src/sys/arch/alpha/alpha/mcclock.c:1.22	Wed Mar  6 06:30:48 2024
+++ src/sys/arch/alpha/alpha/mcclock.c	Wed Mar  6 07:34:11 2024
@@ -1,4 +1,33 @@
-/* $NetBSD: mcclock.c,v 1.22 2024/03/06 06:30:48 thorpej Exp $ */
+/* $NetBSD: mcclock.c,v 1.23 2024/03/06 07:34:11 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2024 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 
 /*
  * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
@@ -29,9 +58,10 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 1.22 2024/03/06 06:30:48 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 1.23 2024/03/06 07:34:11 thorpej Exp $");
 
 #include "opt_clock_compat_osf1.h"
+#include "opt_multiprocessor.h"
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -40,6 +70,9 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 
 #include <sys/kernel.h>
 #include <sys/lwp.h>
 #include <sys/systm.h>
+#if defined(MULTIPROCESSOR)
+#include <sys/xcall.h>
+#endif
 
 #include <machine/cpu_counter.h>
 
@@ -64,18 +97,95 @@ __KERNEL_RCSID(0, "$NetBSD: mcclock.c,v 
 #define UNIX_YEAR_OFFSET 0
 #endif
 
-
 static void mcclock_set_pcc_freq(struct mc146818_softc *);
 static void mcclock_init(void *);
 
+#if defined(MULTIPROCESSOR)
+struct mcclock_trampoline_arg {
+	todr_chip_handle_t	handle;	/* IN */
+	struct clock_ymdhms	*dt;	/* IN */
+	int			rv;	/* OUT */
+};
+
+static void
+mcclock_trampoline(void *arg1, void *arg2)
+{
+	int (*func)(todr_chip_handle_t, struct clock_ymdhms *) = arg1;
+	struct mcclock_trampoline_arg *arg = arg2;
+
+	arg->rv = (*func)(arg->handle, arg->dt);
+}
+
+static int
+mcclock_bounce(int (*func)(todr_chip_handle_t, struct clock_ymdhms *),
+    struct mcclock_trampoline_arg *arg)
+{
+	/*
+	 * If we're not on the primary CPU, then we need to make
+	 * a cross-call to the primary to access the clock registers.
+	 * But we do a little work to avoid even calling into the
+	 * cross-call code if we can avoid it.
+	 */
+	int bound = curlwp_bind();
+
+	if (CPU_IS_PRIMARY(curcpu())) {
+		mcclock_trampoline(func, arg);
+		curlwp_bindx(bound);
+	} else {
+		curlwp_bindx(bound);
+		uint64_t token = xc_unicast(0, mcclock_trampoline,
+		    func, arg, &cpu_info_primary);
+		xc_wait(token);
+	}
+	return arg->rv;
+}
+
+static int
+mcclock_gettime_ymdhms(todr_chip_handle_t handle, struct clock_ymdhms *dt)
+{
+	struct mcclock_trampoline_arg arg = {
+		.handle = handle,
+		.dt = dt,
+	};
+
+	return mcclock_bounce(mc146818_gettime_ymdhms, &arg);
+}
+
+static int
+mcclock_settime_ymdhms(todr_chip_handle_t handle, struct clock_ymdhms *dt)
+{
+	struct mcclock_trampoline_arg arg = {
+		.handle = handle,
+		.dt = dt,
+	};
+
+	return mcclock_bounce(mc146818_settime_ymdhms, &arg);
+}
+#endif /* MULTIPROCESSOR */
+
 void
 mcclock_attach(struct mcclock_softc *msc)
 {
 	struct mc146818_softc *sc = &msc->sc_mc146818;
 
+	KASSERT(cold);
+	KASSERT(CPU_IS_PRIMARY(curcpu()));
+
 	sc->sc_year0 = 1900 + UNIX_YEAR_OFFSET;
 	sc->sc_flag = 0;	/* BINARY, 24HR */
 
+#if defined(MULTIPROCESSOR)
+	/*
+	 * Because some Alpha systems have clocks that can only be
+	 * accessed by the primary CPU, we need to wrap the mc146818
+	 * gettime/settime routines if we have such a clock.
+	 */
+	if (msc->sc_primary_only) {
+		sc->sc_handle.todr_gettime_ymdhms = mcclock_gettime_ymdhms;
+		sc->sc_handle.todr_settime_ymdhms = mcclock_settime_ymdhms;
+	}
+#endif
+
 	mc146818_attach(sc);
 
 	aprint_normal("\n");
@@ -99,6 +209,9 @@ mcclock_set_pcc_freq(struct mc146818_sof
 	uint8_t reg_a;
 	int i;
 
+	KASSERT(cold);
+	KASSERT(CPU_IS_PRIMARY(curcpu()));
+
 	/* save REG_A */
 	reg_a = (*sc->sc_mcread)(sc, MC_REGA);
 
@@ -139,13 +252,19 @@ mcclock_init(void *dev)
 {
 	struct mc146818_softc *sc = dev;
 
-	/* Only do this on the primary CPU. */
-	if (! CPU_IS_PRIMARY(curcpu())) {
-		return;
+	kpreempt_disable();
+
+	/*
+	 * The Alpha port calls clock init function is called on each CPU,
+	 * but for this clock, we only want to do work on the primary.
+	 */
+	if (CPU_IS_PRIMARY(curcpu())) {
+		/* enable interval clock interrupt */
+		(*sc->sc_mcwrite)(sc, MC_REGA,
+		    MC_BASE_32_KHz | MC_RATE_1024_Hz);
+		(*sc->sc_mcwrite)(sc, MC_REGB,
+		    MC_REGB_PIE | MC_REGB_SQWE | MC_REGB_BINARY | MC_REGB_24HR);
 	}
 
-	/* enable interval clock interrupt */
-	(*sc->sc_mcwrite)(sc, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz);
-	(*sc->sc_mcwrite)(sc, MC_REGB,
-	    MC_REGB_PIE | MC_REGB_SQWE | MC_REGB_BINARY | MC_REGB_24HR);
+	kpreempt_enable();
 }

Index: src/sys/arch/alpha/alpha/mcclockvar.h
diff -u src/sys/arch/alpha/alpha/mcclockvar.h:1.6 src/sys/arch/alpha/alpha/mcclockvar.h:1.7
--- src/sys/arch/alpha/alpha/mcclockvar.h:1.6	Wed Mar  6 06:30:48 2024
+++ src/sys/arch/alpha/alpha/mcclockvar.h	Wed Mar  6 07:34:11 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: mcclockvar.h,v 1.6 2024/03/06 06:30:48 thorpej Exp $ */
+/* $NetBSD: mcclockvar.h,v 1.7 2024/03/06 07:34:11 thorpej Exp $ */
 
 /*
  * Copyright (c) 1996 Carnegie-Mellon University.
@@ -32,6 +32,9 @@
 
 struct mcclock_softc {
 	struct mc146818_softc	sc_mc146818;
+
+	/* Accessible only on the primary CPU. */
+	bool			sc_primary_only;
 };
 
 void	mcclock_attach(struct mcclock_softc *);

Index: src/sys/arch/alpha/gbus/mcclock_gbus.c
diff -u src/sys/arch/alpha/gbus/mcclock_gbus.c:1.4 src/sys/arch/alpha/gbus/mcclock_gbus.c:1.5
--- src/sys/arch/alpha/gbus/mcclock_gbus.c:1.4	Wed Mar  6 06:30:49 2024
+++ src/sys/arch/alpha/gbus/mcclock_gbus.c	Wed Mar  6 07:34:11 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: mcclock_gbus.c,v 1.4 2024/03/06 06:30:49 thorpej Exp $ */
+/* $NetBSD: mcclock_gbus.c,v 1.5 2024/03/06 07:34:11 thorpej Exp $ */
 
 /*
  * Copyright (c) 1997 by Matthew Jacob
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: mcclock_gbus.c,v 1.4 2024/03/06 06:30:49 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mcclock_gbus.c,v 1.5 2024/03/06 07:34:11 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -86,6 +86,9 @@ mcclock_gbus_attach(device_t parent, dev
 		panic("mcclock_gbus_attach: couldn't map clock I/O space");
 	}
 
+	/* The RTC is accessible only by a CPU on the primary CPU module. */
+	msc->sc_primary_only = true;
+
 	sc->sc_mcread  = mcclock_gbus_read;
 	sc->sc_mcwrite = mcclock_gbus_write;
 

Reply via email to