linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Q] Is 64bit LVTT screwed
@ 2008-07-02 18:40 Cyrill Gorcunov
  2008-07-07 22:08 ` Maciej W. Rozycki
  0 siblings, 1 reply; 4+ messages in thread
From: Cyrill Gorcunov @ 2008-07-02 18:40 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: LKML

Hi Maciej,

while I'm in path of unification apic code I found a bit
strange code snippet

apic_32.c
---------
#define APIC_DIVISOR 16
static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
{
	...
	if (!oneshot)
		apic_write_around(APIC_TMICT, clocks / APIC_DIVISOR);

}

apic_64.c
---------
static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
{
        ...
	if (!oneshot)
		apic_write_around(APIC_TMICT, clocks);
}

but in both cases we use "divide by 16" in divide register. The only
explanation I imagine - for 64bit mode we are required to 'stuck'
for a bit longer (by 16 times longer to be precise). Am I right?
Or there is another reason why we dont use APIC_DIVISOR here. Actually,
as I see it not fair to a caller. For 64bit mode APIC timer is requested
to count 250000000 ticks but in real it will count 250000000 * 16.
Not sure who is right there. I think the better would be to
use 4000000000 and APIC_DIVISOR in 64bit mode. How do you think?

		- Cyrill -

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Q] Is 64bit LVTT screwed
  2008-07-02 18:40 [Q] Is 64bit LVTT screwed Cyrill Gorcunov
@ 2008-07-07 22:08 ` Maciej W. Rozycki
  2008-07-08 11:38   ` Cyrill Gorcunov
  2008-07-08 19:09   ` Cyrill Gorcunov
  0 siblings, 2 replies; 4+ messages in thread
From: Maciej W. Rozycki @ 2008-07-07 22:08 UTC (permalink / raw)
  To: Cyrill Gorcunov; +Cc: LKML

On Wed, 2 Jul 2008, Cyrill Gorcunov wrote:

> while I'm in path of unification apic code I found a bit
> strange code snippet
> 
> apic_32.c
> ---------
> #define APIC_DIVISOR 16
> static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
> {
> 	...
> 	if (!oneshot)
> 		apic_write_around(APIC_TMICT, clocks / APIC_DIVISOR);
> 
> }
> 
> apic_64.c
> ---------
> static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
> {
>         ...
> 	if (!oneshot)
> 		apic_write_around(APIC_TMICT, clocks);
> }
> 
> but in both cases we use "divide by 16" in divide register. The only
> explanation I imagine - for 64bit mode we are required to 'stuck'
> for a bit longer (by 16 times longer to be precise). Am I right?
> Or there is another reason why we dont use APIC_DIVISOR here. Actually,
> as I see it not fair to a caller. For 64bit mode APIC timer is requested
> to count 250000000 ticks but in real it will count 250000000 * 16.
> Not sure who is right there. I think the better would be to
> use 4000000000 and APIC_DIVISOR in 64bit mode. How do you think?

 The APIC clock varies across systems so the timer setup includes
calibration.  Which means both variations end up with the correct
interrupt rate probably, except using different divisors.  We used to
print the APIC clock rate and that would be off with one of the above, but
I don't we do this anymore.  We had a similar problem with the 82489DX
where the prescaler was bypassed altogether resulting in an incorrect 
clock rate printed, but the rate of timer interrupt was correctly 
calibrated regardless.

 This is of course merely an explanation why the code you quoted does not
explode spectacularly.  It does not make it correct.  If the prescaler is
indeed set to 16 for 64-bit systems, then APIC_DIVISOR should obviously be
used in the calculation above too.  And if not, then I think the prescaler 
should be set consistently across systems and then the setting reflected 
in the calculations accordingly.  Please note that only values between 2 
and 16 are supported in a uniform way across all the APIC models and using 
low values risks an overflow as clock rates are in the GHz range these 
days already.  The value of 16 seems a reasonable one.

  Maciej

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Q] Is 64bit LVTT screwed
  2008-07-07 22:08 ` Maciej W. Rozycki
@ 2008-07-08 11:38   ` Cyrill Gorcunov
  2008-07-08 19:09   ` Cyrill Gorcunov
  1 sibling, 0 replies; 4+ messages in thread
From: Cyrill Gorcunov @ 2008-07-08 11:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: LKML

On Tue, Jul 8, 2008 at 2:08 AM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
[...]
>>
>> but in both cases we use "divide by 16" in divide register. The only
>> explanation I imagine - for 64bit mode we are required to 'stuck'
>> for a bit longer (by 16 times longer to be precise). Am I right?
>> Or there is another reason why we dont use APIC_DIVISOR here. Actually,
>> as I see it not fair to a caller. For 64bit mode APIC timer is requested
>> to count 250000000 ticks but in real it will count 250000000 * 16.
>> Not sure who is right there. I think the better would be to
>> use 4000000000 and APIC_DIVISOR in 64bit mode. How do you think?
>
>  The APIC clock varies across systems so the timer setup includes
> calibration.  Which means both variations end up with the correct
> interrupt rate probably, except using different divisors.  We used to
> print the APIC clock rate and that would be off with one of the above, but
> I don't we do this anymore.  We had a similar problem with the 82489DX
> where the prescaler was bypassed altogether resulting in an incorrect
> clock rate printed, but the rate of timer interrupt was correctly
> calibrated regardless.
>
>  This is of course merely an explanation why the code you quoted does not
> explode spectacularly.  It does not make it correct.  If the prescaler is
> indeed set to 16 for 64-bit systems, then APIC_DIVISOR should obviously be
> used in the calculation above too.  And if not, then I think the prescaler
> should be set consistently across systems and then the setting reflected
> in the calculations accordingly.  Please note that only values between 2
> and 16 are supported in a uniform way across all the APIC models and using
> low values risks an overflow as clock rates are in the GHz range these
> days already.  The value of 16 seems a reasonable one.
>
>  Maciej
>

Thanks, Maciej, for explanation. Unfortunelly I'm quite busy now so
I stopped merging/research on apic code, as only get spare time - will
let you know my results.

- Cyrill -

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Q] Is 64bit LVTT screwed
  2008-07-07 22:08 ` Maciej W. Rozycki
  2008-07-08 11:38   ` Cyrill Gorcunov
@ 2008-07-08 19:09   ` Cyrill Gorcunov
  1 sibling, 0 replies; 4+ messages in thread
From: Cyrill Gorcunov @ 2008-07-08 19:09 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: LKML

[Maciej W. Rozycki - Mon, Jul 07, 2008 at 11:08:57PM +0100]
[...]
| > 
| > but in both cases we use "divide by 16" in divide register. The only
| > explanation I imagine - for 64bit mode we are required to 'stuck'
| > for a bit longer (by 16 times longer to be precise). Am I right?
| > Or there is another reason why we dont use APIC_DIVISOR here. Actually,
| > as I see it not fair to a caller. For 64bit mode APIC timer is requested
| > to count 250000000 ticks but in real it will count 250000000 * 16.
| > Not sure who is right there. I think the better would be to
| > use 4000000000 and APIC_DIVISOR in 64bit mode. How do you think?
| 
|  The APIC clock varies across systems so the timer setup includes
| calibration.  Which means both variations end up with the correct
| interrupt rate probably, except using different divisors.  We used to
| print the APIC clock rate and that would be off with one of the above, but
| I don't we do this anymore.  We had a similar problem with the 82489DX
| where the prescaler was bypassed altogether resulting in an incorrect 
| clock rate printed, but the rate of timer interrupt was correctly 
| calibrated regardless.
| 
|  This is of course merely an explanation why the code you quoted does not
| explode spectacularly.  It does not make it correct.  If the prescaler is
| indeed set to 16 for 64-bit systems, then APIC_DIVISOR should obviously be
| used in the calculation above too.  And if not, then I think the prescaler 
| should be set consistently across systems and then the setting reflected 
| in the calculations accordingly.  Please note that only values between 2 
| and 16 are supported in a uniform way across all the APIC models and using 
| low values risks an overflow as clock rates are in the GHz range these 
| days already.  The value of 16 seems a reasonable one.
| 
|   Maciej
|

Maciej, I think the right soulution is the next:

Index: linux-2.6.git/arch/x86/kernel/apic_64.c
===================================================================
--- linux-2.6.git.orig/arch/x86/kernel/apic_64.c	2008-07-08 22:52:24.000000000 +0400
+++ linux-2.6.git/arch/x86/kernel/apic_64.c	2008-07-08 23:00:24.000000000 +0400
@@ -165,6 +165,9 @@ int lapic_get_maxlvt(void)
 	return maxlvt;
 }
 
+/* Clock divisor is set to 16 */
+#define APIC_DIVISOR 16
+
 /*
  * This function sets up the local APIC timer, with a timeout of
  * 'clocks' APIC bus clock. During calibration we actually call
@@ -197,7 +200,7 @@ static void __setup_APIC_LVTT(unsigned i
 				| APIC_TDR_DIV_16);
 
 	if (!oneshot)
-		apic_write(APIC_TMICT, clocks);
+		apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
 }
 
 /*
@@ -329,7 +332,7 @@ static void __init calibrate_APIC_clock(
 	 *
 	 * No interrupt enable !
 	 */
-	__setup_APIC_LVTT(250000000, 0, 0);
+	__setup_APIC_LVTT(4000000000, 0, 0);
 
 	apic_start = apic_read(APIC_TMCCT);
 #ifdef CONFIG_X86_PM_TIMER

So we remain behaviour the same (ie calibrating duration remains the same)
but it has touched lapic_timer_setup. Will take a look into this more closer
soon.

		- Cyrill -

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-07-08 19:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-02 18:40 [Q] Is 64bit LVTT screwed Cyrill Gorcunov
2008-07-07 22:08 ` Maciej W. Rozycki
2008-07-08 11:38   ` Cyrill Gorcunov
2008-07-08 19:09   ` Cyrill Gorcunov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).