svn commit: r212695 - in stable/8/sys/sparc64: include sparc64
Marius Strobl
marius at FreeBSD.org
Wed Sep 15 20:17:18 UTC 2010
Author: marius
Date: Wed Sep 15 20:17:18 2010
New Revision: 212695
URL: http://svn.freebsd.org/changeset/base/212695
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/8/sys/sparc64/include/smp.h
stable/8/sys/sparc64/sparc64/genassym.c
stable/8/sys/sparc64/sparc64/mp_exception.S
stable/8/sys/sparc64/sparc64/mp_machdep.c
stable/8/sys/sparc64/sparc64/tick.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
Modified: stable/8/sys/sparc64/include/smp.h
==============================================================================
--- stable/8/sys/sparc64/include/smp.h Wed Sep 15 19:55:26 2010 (r212694)
+++ stable/8/sys/sparc64/include/smp.h Wed Sep 15 20:17:18 2010 (r212695)
@@ -79,6 +79,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;
@@ -103,6 +108,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;
@@ -117,6 +123,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[];
@@ -170,6 +180,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;
@@ -274,6 +300,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/8/sys/sparc64/sparc64/genassym.c
==============================================================================
--- stable/8/sys/sparc64/sparc64/genassym.c Wed Sep 15 19:55:26 2010 (r212694)
+++ stable/8/sys/sparc64/sparc64/genassym.c Wed Sep 15 20:17:18 2010 (r212695)
@@ -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/8/sys/sparc64/sparc64/mp_exception.S
==============================================================================
--- stable/8/sys/sparc64/sparc64/mp_exception.S Wed Sep 15 19:55:26 2010 (r212694)
+++ stable/8/sys/sparc64/sparc64/mp_exception.S Wed Sep 15 20:17:18 2010 (r212695)
@@ -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/8/sys/sparc64/sparc64/mp_machdep.c
==============================================================================
--- stable/8/sys/sparc64/sparc64/mp_machdep.c Wed Sep 15 19:55:26 2010 (r212694)
+++ stable/8/sys/sparc64/sparc64/mp_machdep.c Wed Sep 15 20:17:18 2010 (r212695)
@@ -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/8/sys/sparc64/sparc64/tick.c
==============================================================================
--- stable/8/sys/sparc64/sparc64/tick.c Wed Sep 15 19:55:26 2010 (r212694)
+++ stable/8/sys/sparc64/sparc64/tick.c Wed Sep 15 20:17:18 2010 (r212695)
@@ -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-stable-8
mailing list