svn commit: r212696 - in stable/7/sys/sparc64: include sparc64

Marius Strobl marius at FreeBSD.org
Wed Sep 15 20:17:22 UTC 2010


Author: marius
Date: Wed Sep 15 20:17:20 2010
New Revision: 212696
URL: http://svn.freebsd.org/changeset/base/212696

Log:
  MFC: r210601 (partial), r211071, r211073
  
  - As it is not possible for sched_bind(9) to context switch with
    td_critnest > 1 when not already running on the desired CPU read the
    TICK counter of the BSP via a direct cross trap request in that case
    instead.
  - Provide a STICK based timecounter.

Modified:
  stable/7/sys/sparc64/include/smp.h
  stable/7/sys/sparc64/sparc64/genassym.c
  stable/7/sys/sparc64/sparc64/mp_exception.S
  stable/7/sys/sparc64/sparc64/mp_machdep.c
  stable/7/sys/sparc64/sparc64/tick.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/sparc64/include/smp.h
==============================================================================
--- stable/7/sys/sparc64/include/smp.h	Wed Sep 15 20:17:18 2010	(r212695)
+++ stable/7/sys/sparc64/include/smp.h	Wed Sep 15 20:17:20 2010	(r212696)
@@ -78,6 +78,11 @@ struct ipi_cache_args {
 	vm_paddr_t ica_pa;
 };
 
+struct ipi_rd_args {
+	u_int	ira_mask;
+	register_t *ira_val;
+};
+
 struct ipi_tlb_args {
 	u_int	ita_mask;
 	struct	pmap *ita_pmap;
@@ -102,6 +107,7 @@ void	mp_init(u_int cpu_impl);
 
 extern	struct mtx ipi_mtx;
 extern	struct ipi_cache_args ipi_cache_args;
+extern	struct ipi_rd_args ipi_rd_args;
 extern	struct ipi_tlb_args ipi_tlb_args;
 
 extern	char *mp_tramp_code;
@@ -116,6 +122,10 @@ extern	char tl_ipi_spitfire_dcache_page_
 extern	char tl_ipi_spitfire_icache_page_inval[];
 
 extern	char tl_ipi_level[];
+
+extern	char tl_ipi_stick_rd[];
+extern	char tl_ipi_tick_rd[];
+
 extern	char tl_ipi_tlb_context_demap[];
 extern	char tl_ipi_tlb_page_demap[];
 extern	char tl_ipi_tlb_range_demap[];
@@ -169,6 +179,22 @@ ipi_icache_page_inval(void *func, vm_pad
 }
 
 static __inline void *
+ipi_rd(u_int cpu, void *func, u_long *val)
+{
+	struct ipi_rd_args *ira;
+
+	if (smp_cpus == 1)
+		return (NULL);
+	sched_pin();
+	ira = &ipi_rd_args;
+	mtx_lock_spin(&ipi_mtx);
+	ira->ira_mask = 1 << cpu | PCPU_GET(cpumask);
+	ira->ira_val = val;
+	cpu_ipi_single(cpu, 0, (u_long)func, (u_long)ira);
+	return (&ira->ira_mask);
+}
+
+static __inline void *
 ipi_tlb_context_demap(struct pmap *pm)
 {
 	struct ipi_tlb_args *ita;
@@ -273,6 +299,13 @@ ipi_icache_page_inval(void *func __unuse
 }
 
 static __inline void *
+ipi_rd(u_int cpu __unused, void *func __unused, u_long *val __unused)
+{
+
+	return (NULL);
+}
+
+static __inline void *
 ipi_tlb_context_demap(struct pmap *pm __unused)
 {
 

Modified: stable/7/sys/sparc64/sparc64/genassym.c
==============================================================================
--- stable/7/sys/sparc64/sparc64/genassym.c	Wed Sep 15 20:17:18 2010	(r212695)
+++ stable/7/sys/sparc64/sparc64/genassym.c	Wed Sep 15 20:17:20 2010	(r212696)
@@ -105,10 +105,6 @@ ASSYM(IC_SIZE, offsetof(struct cacheinfo
 ASSYM(IC_LINESIZE, offsetof(struct cacheinfo, ic_linesize));
 #endif
 
-#ifdef SMP
-ASSYM(ICA_PA, offsetof(struct ipi_cache_args, ica_pa));
-#endif
-
 ASSYM(KTR_SIZEOF, sizeof(struct ktr_entry));
 ASSYM(KTR_LINE, offsetof(struct ktr_entry, ktr_line));
 ASSYM(KTR_FILE, offsetof(struct ktr_entry, ktr_file));
@@ -215,7 +211,12 @@ ASSYM(IR_ARG, offsetof(struct intr_reque
 ASSYM(IR_PRI, offsetof(struct intr_request, ir_pri));
 ASSYM(IR_VEC, offsetof(struct intr_request, ir_vec));
 
-#ifdef SMP
+#if defined(SUN4U) && defined(SMP)
+ASSYM(ICA_PA, offsetof(struct ipi_cache_args, ica_pa));
+
+ASSYM(IRA_MASK, offsetof(struct ipi_rd_args, ira_mask));
+ASSYM(IRA_VAL, offsetof(struct ipi_rd_args, ira_val));
+
 ASSYM(ITA_MASK, offsetof(struct ipi_tlb_args, ita_mask));
 ASSYM(ITA_PMAP, offsetof(struct ipi_tlb_args, ita_pmap));
 ASSYM(ITA_START, offsetof(struct ipi_tlb_args, ita_start));

Modified: stable/7/sys/sparc64/sparc64/mp_exception.S
==============================================================================
--- stable/7/sys/sparc64/sparc64/mp_exception.S	Wed Sep 15 20:17:18 2010	(r212695)
+++ stable/7/sys/sparc64/sparc64/mp_exception.S	Wed Sep 15 20:17:20 2010	(r212696)
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
  */
 ENTRY(tl_ipi_spitfire_dcache_page_inval)
 #if KTR_COMPILE & KTR_SMP
-	CATR(KTR_SMP, "ipi_dcache_page_inval: pa=%#lx"
+	CATR(KTR_SMP, "tl_ipi_spitfire_dcache_page_inval: pa=%#lx"
 	    , %g1, %g2, %g3, 7, 8, 9)
 	ldx	[%g5 + ICA_PA], %g2
 	stx	%g2, [%g1 + KTR_PARM1]
@@ -87,7 +87,7 @@ END(tl_ipi_spitfire_dcache_page_inval)
  */
 ENTRY(tl_ipi_spitfire_icache_page_inval)
 #if KTR_COMPILE & KTR_SMP
-	CATR(KTR_SMP, "ipi_icache_page_inval: pa=%#lx"
+	CATR(KTR_SMP, "tl_ipi_spitfire_icache_page_inval: pa=%#lx"
 	    , %g1, %g2, %g3, 7, 8, 9)
 	ldx	[%g5 + ICA_PA], %g2
 	stx	%g2, [%g1 + KTR_PARM1]
@@ -126,7 +126,7 @@ END(tl_ipi_spitfire_icache_page_inval)
  */
 ENTRY(tl_ipi_cheetah_dcache_page_inval)
 #if KTR_COMPILE & KTR_SMP
-	CATR(KTR_SMP, "ipi_dcache_page_inval: pa=%#lx"
+	CATR(KTR_SMP, "tl_ipi_cheetah_dcache_page_inval: pa=%#lx"
 	    , %g1, %g2, %g3, 7, 8, 9)
 	ldx	[%g5 + ICA_PA], %g2
 	stx	%g2, [%g1 + KTR_PARM1]
@@ -256,7 +256,7 @@ END(tl_ipi_tlb_range_demap)
  */
 ENTRY(tl_ipi_tlb_context_demap)
 #if KTR_COMPILE & KTR_SMP
-	CATR(KTR_SMP, "ipi_tlb_page_demap: pm=%p va=%#lx"
+	CATR(KTR_SMP, "tl_ipi_tlb_context_demap: pm=%p va=%#lx"
 	    , %g1, %g2, %g3, 7, 8, 9)
 	ldx	[%g5 + ITA_PMAP], %g2
 	stx	%g2, [%g1 + KTR_PARM1]
@@ -274,3 +274,27 @@ ENTRY(tl_ipi_tlb_context_demap)
 	IPI_DONE(%g5, %g1, %g2, %g3)
 	retry
 END(tl_ipi_tlb_context_demap)
+
+/*
+ * Read %stick.
+ */
+ENTRY(tl_ipi_stick_rd)
+	ldx	[%g5 + IRA_VAL], %g1
+	rd	%asr24, %g2
+	stx	%g2, [%g1]
+
+	IPI_DONE(%g5, %g1, %g2, %g3)
+	retry
+END(tl_ipi_stick_rd)
+
+/*
+ * Read %tick.
+ */
+ENTRY(tl_ipi_tick_rd)
+	ldx	[%g5 + IRA_VAL], %g1
+	rd	%tick, %g2
+	stx	%g2, [%g1]
+
+	IPI_DONE(%g5, %g1, %g2, %g3)
+	retry
+END(tl_ipi_tick_rd)

Modified: stable/7/sys/sparc64/sparc64/mp_machdep.c
==============================================================================
--- stable/7/sys/sparc64/sparc64/mp_machdep.c	Wed Sep 15 20:17:18 2010	(r212695)
+++ stable/7/sys/sparc64/sparc64/mp_machdep.c	Wed Sep 15 20:17:20 2010	(r212696)
@@ -107,6 +107,7 @@ static ih_func_t cpu_ipi_stop;
  */
 struct	cpu_start_args cpu_start_args = { 0, -1, -1, 0, 0, 0 };
 struct	ipi_cache_args ipi_cache_args;
+struct	ipi_rd_args ipi_rd_args;
 struct	ipi_tlb_args ipi_tlb_args;
 struct	pcb stoppcbs[MAXCPU];
 

Modified: stable/7/sys/sparc64/sparc64/tick.c
==============================================================================
--- stable/7/sys/sparc64/sparc64/tick.c	Wed Sep 15 20:17:18 2010	(r212695)
+++ stable/7/sys/sparc64/sparc64/tick.c	Wed Sep 15 20:17:20 2010	(r212696)
@@ -42,9 +42,13 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/ofw/openfirm.h>
 
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
 #include <machine/cpu.h>
 #include <machine/frame.h>
 #include <machine/intr_machdep.h>
+#include <machine/smp.h>
 #include <machine/tick.h>
 #include <machine/ver.h>
 
@@ -76,10 +80,15 @@ u_int hardclock_use_stick = 0;
 SYSCTL_INT(_machdep_tick, OID_AUTO, hardclock_use_stick, CTLFLAG_RD,
     &hardclock_use_stick, 0, "hardclock uses STICK instead of TICK timer");
 
+static struct timecounter stick_tc;
 static struct timecounter tick_tc;
 static u_long tick_increment;
 
 static uint64_t tick_cputicks(void);
+static timecounter_get_t stick_get_timecount_up;
+#ifdef SMP
+static timecounter_get_t stick_get_timecount_mp;
+#endif
 static timecounter_get_t tick_get_timecount_up;
 #ifdef SMP
 static timecounter_get_t tick_get_timecount_mp;
@@ -101,25 +110,31 @@ tick_cputicks(void)
 void
 cpu_initclocks(void)
 {
-	uint32_t clock;
+	uint32_t clock, sclock;
 
 	stathz = hz;
 
+	clock = PCPU_GET(clock);
+	sclock = 0;
+	if (PCPU_GET(impl) == CPU_IMPL_SPARC64V ||
+	    PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCIII) {
+		if (OF_getprop(OF_parent(PCPU_GET(node)), "stick-frequency",
+		    &sclock, sizeof(sclock)) == -1) {
+			panic("%s: could not determine STICK frequency",
+			    __func__);
+		}
+	}
 	/*
 	 * Given that the STICK timers typically are driven at rather low
 	 * frequencies they shouldn't be used except when really necessary.
 	 */
 	if (hardclock_use_stick != 0) {
-		if (OF_getprop(OF_parent(PCPU_GET(node)), "stick-frequency",
-		    &clock, sizeof(clock)) == -1)
-		panic("%s: could not determine STICK frequency", __func__);
 		intr_setup(PIL_TICK, stick_hardclock, -1, NULL, NULL);
 		/*
 		 * We don't provide a CPU ticker as long as the frequency
 		 * supplied isn't actually used per-CPU.
 		 */
 	} else {
-		clock = PCPU_GET(clock);
 		intr_setup(PIL_TICK, PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI &&
 		    PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ?
 		    tick_hardclock_bbwar : tick_hardclock, -1, NULL, NULL);
@@ -136,31 +151,45 @@ cpu_initclocks(void)
 	tick_start();
 
 	/*
-	 * Initialize the TICK-based timecounter.  This must not happen
-	 * before SI_SUB_INTRINSIC for tick_get_timecount_mp() to work.
+	 * Initialize the (S)TICK-based timecounter(s).
+	 * Note that we (try to) sync the (S)TICK timers of APs with the BSP
+	 * during their startup but not afterwards.  The resulting drift can
+	 * cause problems when the time is calculated based on (S)TICK values
+	 * read on different CPUs.  Thus we always read the register on the
+	 * BSP (if necessary via an IPI as sched_bind(9) isn't available in
+	 * all circumstances) and use a low quality for the otherwise high
+	 * quality (S)TICK timers in the MP case.
 	 */
 	tick_tc.tc_get_timecount = tick_get_timecount_up;
 	tick_tc.tc_poll_pps = NULL;
 	tick_tc.tc_counter_mask = ~0u;
-	tick_tc.tc_frequency = PCPU_GET(clock);
+	tick_tc.tc_frequency = clock;
 	tick_tc.tc_name = "tick";
 	tick_tc.tc_quality = TICK_QUALITY_UP;
 	tick_tc.tc_priv = NULL;
 #ifdef SMP
-	/*
-	 * We (try to) sync the (S)TICK timers of APs with the BSP during
-	 * their startup but not afterwards.  The resulting drift can
-	 * cause problems when the time is calculated based on (S)TICK
-	 * values read on different CPUs.  Thus we bind to the BSP for
-	 * reading the register and use a low quality for the otherwise
-	 * high quality (S)TICK timers in the MP case.
-	 */
 	if (cpu_mp_probe()) {
 		tick_tc.tc_get_timecount = tick_get_timecount_mp;
 		tick_tc.tc_quality = TICK_QUALITY_MP;
 	}
 #endif
 	tc_init(&tick_tc);
+	if (sclock != 0) {
+		stick_tc.tc_get_timecount = stick_get_timecount_up;
+		stick_tc.tc_poll_pps = NULL;
+		stick_tc.tc_counter_mask = ~0u;
+		stick_tc.tc_frequency = sclock;
+		stick_tc.tc_name = "stick";
+		stick_tc.tc_quality = TICK_QUALITY_UP;
+		stick_tc.tc_priv = NULL;
+#ifdef SMP
+		if (cpu_mp_probe()) {
+			stick_tc.tc_get_timecount = stick_get_timecount_mp;
+			stick_tc.tc_quality = TICK_QUALITY_MP;
+		}
+#endif
+		tc_init(&stick_tc);
+	}
 }
 
 static inline void
@@ -266,6 +295,13 @@ tick_hardclock_common(struct trapframe *
 }
 
 static u_int
+stick_get_timecount_up(struct timecounter *tc)
+{
+
+	return ((u_int)rdstick());
+}
+
+static u_int
 tick_get_timecount_up(struct timecounter *tc)
 {
 
@@ -274,22 +310,30 @@ tick_get_timecount_up(struct timecounter
 
 #ifdef SMP
 static u_int
-tick_get_timecount_mp(struct timecounter *tc)
+stick_get_timecount_mp(struct timecounter *tc)
 {
-	struct thread *td;
-	u_int tick;
+	u_long stick;
 
-	td = curthread;
-	thread_lock(td);
-	sched_bind(td, 0);
-	thread_unlock(td);
-
-	tick = tick_get_timecount_up(tc);
-
-	thread_lock(td);
-	sched_unbind(td);
-	thread_unlock(td);
+	sched_pin();
+	if (curcpu == 0)
+		stick = rdstick();
+	else
+		ipi_wait(ipi_rd(0, tl_ipi_stick_rd, &stick));
+	sched_unpin();
+	return (stick);
+}
 
+static u_int
+tick_get_timecount_mp(struct timecounter *tc)
+{
+	u_long tick;
+
+	sched_pin();
+	if (curcpu == 0)
+		tick = rd(tick);
+	else
+		ipi_wait(ipi_rd(0, tl_ipi_tick_rd, &tick));
+	sched_unpin();
 	return (tick);
 }
 #endif


More information about the svn-src-all mailing list