Re: Using %stick where available

Takeshi Nakayama <[email protected]>
Newsgroups gmane.os.netbsd.ports.sparc64
Message-ID <[email protected]>
Hello,

>>> Michael <[email protected]> wrote

> Hello,
> 
> On Nov 7, 2012, at 7:04 AM, Takeshi Nakayama wrote:
> 
> >>>> Michael <[email protected]> wrote
> >
> >> Hello,
> >>
> >> the attached patch adds support for the system timer interrupt  
> >> present
> >> in UltraSPARC-III and some later II ( like IIe and IIi with on chip
> >> ecache ). It hasn't seen much testing beyond 'works on my Blade  
> >> 2500'.
> >> The purpose is to have a timer interrupt / time counter that's
> >> independent of the CPU's clock rate, so we can change it without
> >> worrying about time keeping.
> >
> > It looks ok to me, but as Eric reported it needs some fix.
> 
> Yeah, I have no US-IIe hardware so I couldn't test it there, which is  
> one of the reasons why I posted the patch here first.
> 
> >> +	struct cpu_info *ci = curcpu();
> >
> > Replace the following curcpu()s with ci.
> 
> Done.

Thanks, but there are some left.

> > I think the following is better for consistency.
> >
> > -	long clk;
> > +	long clk, sclk;
> 
> Yeah, I left it an int because that's what we get from the PROM, but  
> you're right, they should be the same type.
> 
> >> +	sclk = prom_getpropint(findroot(), "stick-frequency", 0);
> >> +	ci->ci_system_clockrate[0] = sclk;
> >> +	ci->ci_system_clockrate[1] = sclk / 1000000;
> >
> > US-IIe has system tick register, but its implementation is
> > different to US-III one.  It can be used via memory mapped system
> > registers, not via ancillary state register (%asr24).
> 
> Seriously?
> I expected trouble with US-IIe but not quite like that.

They are described in section 2.3 and 4.3.4 in "UltraSPARC IIe
Processor User's Manual".  64-bit stick register is splited to two
32-bit registers, so using it is more complex.

> > So, I suggest not to use it on US-IIe as below.
> >
> > 	if (!CPU_IS_HUMMINGBIRD()) {
> > 		sclk = prom_getpropint(findroot(), "stick-frequency", 0);
> > 		ci->ci_system_clockrate[0] = sclk;
> > 		ci->ci_system_clockrate[1] = sclk / 1000000;
> > 	}
> 
> Done, slightly changed to make sure ci_system_clockrate[] is 0 if we  
> don't have %stick.

cpu_info structure is zero cleared in alloc_cpuinfo(), but yes
it's more readable to clear it explicitly.


> Attached is the revised patch, thanks for looking at this!

You're welcome.  I wrote one more comment, please see below.


> Index: sparc64/clock.c
> ===================================================================
> RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/clock.c,v
> retrieving revision 1.106
> diff -u -w -r1.106 clock.c
> --- sparc64/clock.c	4 Sep 2011 12:17:46 -0000	1.106
> +++ sparc64/clock.c	7 Nov 2012 17:26:58 -0000
(snip)
> @@ -338,6 +378,7 @@
>  void
>  cpu_initclocks(void)
>  {
> +	struct cpu_info *ci = curcpu();
>  #ifndef MULTIPROCESSOR
>  	int statint, minint;
>  #endif
> @@ -361,17 +402,24 @@
>  	}
>  
>  	/* Make sure we have a sane cpu_clockrate -- we'll need it */
> -	if (!curcpu()->ci_cpu_clockrate[0]) {
> +	if (!ci->ci_cpu_clockrate[0]) {
>  		/* Default to 200MHz clock XXXXX */
> -		curcpu()->ci_cpu_clockrate[0] = 200000000;
> -		curcpu()->ci_cpu_clockrate[1] = 200000000 / 1000000;
> +		ci->ci_cpu_clockrate[0] = 200000000;
> +		ci->ci_cpu_clockrate[1] = 200000000 / 1000000;
>  	}
>  
>  	/* Initialize the %tick register */
>  	settick(0);
>  
> +	if (ci->ci_system_clockrate[0] == 0) {
>  	tick_timecounter.tc_frequency = curcpu()->ci_cpu_clockrate[0];
                                        ~~~~~~~~
>  	tc_init(&tick_timecounter);
> +	} else {
> +		setstick(0);
> +		stick_timecounter.tc_frequency = 
> +		    ci->ci_system_clockrate[0];
> +		tc_init(&stick_timecounter);
> +	}
>  
>  	/*
>  	 * Now handle machines w/o counter-timers.
> @@ -379,13 +427,21 @@
>  
>  	if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr) {
>  
> -		aprint_normal("No counter-timer -- using %%tick at %luMHz as "
> -			"system clock.\n",
> +		if (ci->ci_system_clockrate[0] == 0) {
> +			aprint_normal("No counter-timer -- using %%tick "
> +			    "at %luMHz as system clock.\n",
>  			(unsigned long)curcpu()->ci_cpu_clockrate[1]);
                                       ~~~~~~~~
>  
>  		/* We don't have a counter-timer -- use %tick */
>  		tickintr_establish(PIL_CLOCK, tickintr);
> +		} else {
> +			aprint_normal("No counter-timer -- using %%stick "
> +			    "at %luMHz as system clock.\n",
> +			    (unsigned long)ci->ci_system_clockrate[1]);
>  
> +			/* We don't have a counter-timer -- use %stick */
> +			stickintr_establish(PIL_CLOCK, stickintr);
> +		}
>  		/* We only have one timer so we have no statclock */
>  		stathz = 0;
>  
(snip)
> Index: sparc64/locore.s
> ===================================================================
> RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/locore.s,v
> retrieving revision 1.341
> diff -u -w -r1.341 locore.s
> --- sparc64/locore.s	17 Mar 2012 22:19:53 -0000	1.341
> +++ sparc64/locore.s	7 Nov 2012 17:26:59 -0000
> @@ -3270,13 +3270,18 @@
>  	wrpr	%g0, PSTATE_KERN|PSTATE_IG, %pstate	! DEBUG
>  #endif
>  	/*
> -	 * If this is a %tick softint, clear it then call interrupt_vector.
> +	 * If this is a %tick or %stick softint, clear it then call
> +	 * interrupt_vector. Only one of them should be enabled at any given
> +	 * time.
>  	 */
>  	rd	SOFTINT, %g1
> -	btst	1, %g1
> +	mov	1, %g5
> +	sllx	%g5, 16, %g3
> +	or	%g5, %g3, %g5

Only "set 0x1001, %g5" is faster.

> +	andcc	%g5, %g1, %g5
>  	bz,pt	%icc, 0f
>  	 sethi	%hi(CPUINFO_VA+CI_TICK_IH), %g3
> -	wr	%g0, 1, CLEAR_SOFTINT
> +	wr	%g0, %g5, CLEAR_SOFTINT
>  	ba,pt	%icc, setup_sparcintr
>  	 LDPTR	[%g3 + %lo(CPUINFO_VA+CI_TICK_IH)], %g5
>  0:
(snip)


-- Takeshi Nakayama
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.