From owner-svn-src-stable-8@FreeBSD.ORG Wed Sep 15 20:17:18 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 97ECA106566C; Wed, 15 Sep 2010 20:17:18 +0000 (UTC) (envelope-from marius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 8546E8FC12; Wed, 15 Sep 2010 20:17:18 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o8FKHILJ049398; Wed, 15 Sep 2010 20:17:18 GMT (envelope-from marius@svn.freebsd.org) Received: (from marius@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o8FKHI6l049392; Wed, 15 Sep 2010 20:17:18 GMT (envelope-from marius@svn.freebsd.org) Message-Id: <201009152017.o8FKHI6l049392@svn.freebsd.org> From: Marius Strobl Date: Wed, 15 Sep 2010 20:17:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212695 - in stable/8/sys/sparc64: include sparc64 X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Sep 2010 20:17:18 -0000 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 +#include +#include + #include #include #include +#include #include #include @@ -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