lkml.org 
[lkml]   [1999]   [Jul]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectUsing the APIC timer of the 82489DX -- a proposal
Hi,

I've noticed the current APIC timer handling code does not handle the
82489DX well. In particular, the timer's base is initialized improperly
(the clock source bypassess the divider) and the divider's input is left
uninitialized. Also calibrating the APIC timer assumes TSC is available
while it may not be the case (and TSC is not mandatory for the function to
produce the result).

The following patch addresses these issues. Apart from fixing the code
it provides some missing macros for handling of 82489DX's registers.

Unfortunately I have only got a standard Pentium SMP machine and I cannot
properly test the fix in an 82489DX environment. Any feedback is
welcomed.

I tested the patch on a standard Pentium SMP machine and it has no
harmful side effects. I wouldn't expect any, even though register bits
the modified code accesses are marked as "reserved" for the integrated
APIC, because apart from some acceptably-documented changes, the
integrated APIC remains compatible to the 82489DX from a programmer's
point of view.

The patch applies cleanly to 2.2.10, too.

Maciej

--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: macro@ds2.pg.gda.pl, PGP key available +

diff -u --recursive --new-file linux-2.3.10.macro/arch/i386/kernel/smp.c linux-2.3.10/arch/i386/kernel/smp.c
--- linux-2.3.10.macro/arch/i386/kernel/smp.c Thu Jul 1 23:09:00 1999
+++ linux-2.3.10/arch/i386/kernel/smp.c Mon Jul 12 15:43:27 1999
@@ -30,6 +30,7 @@
* Alan Cox : Added EBDA scanning
* Ingo Molnar : various cleanups and rewrites
* Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug.
+ * Maciej W. Rozycki : Bits for genuine 82489DX timers.
*/

#include <linux/config.h>
@@ -1962,14 +1963,16 @@
* interrupt and broadcast it as an NMI to all CPUs, so no pain.
*/
tmp_value = apic_read(APIC_LVTT);
- lvtt1_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
- apic_write(APIC_LVTT , lvtt1_value);
+ lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV)
+ | APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
+ apic_write(APIC_LVTT, lvtt1_value);

/*
* Divide PICLK by 16
*/
tmp_value = apic_read(APIC_TDCR);
- apic_write(APIC_TDCR , (tmp_value & ~APIC_TDR_DIV_1 )
+ apic_write(APIC_TDCR, (tmp_value
+ & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
| APIC_TDR_DIV_16);

tmp_value = apic_read(APIC_TMICT);
@@ -2026,29 +2029,44 @@
*/
setup_APIC_timer(1000000000);

- /*
- * The timer chip counts down to zero. Let's wait
- * for a wraparound to start exact measurement:
- * (the current tick might have been already half done)
- */
+ if (cpu_data[smp_processor_id()].x86_capability & X86_FEATURE_TSC) {
+ /*
+ * The timer chip counts down to zero. Let's wait
+ * for a wraparound to start exact measurement:
+ * (the current tick might have been already half done)
+ */

- wait_8254_wraparound ();
+ wait_8254_wraparound ();

- /*
- * We wrapped around just now. Let's start:
- */
- rdtscll(t1);
- tt1=apic_read(APIC_TMCCT);
+ /*
+ * We wrapped around just now. Let's start:
+ */
+ rdtscll(t1);
+ tt1=apic_read(APIC_TMCCT);

#define LOOPS (HZ/10)
- /*
- * Let's wait LOOPS wraprounds:
- */
- for (i=0; i<LOOPS; i++)
+ /*
+ * Let's wait LOOPS wraprounds:
+ */
+ for (i=0; i<LOOPS; i++)
+ wait_8254_wraparound ();
+
+ tt2=apic_read(APIC_TMCCT);
+ rdtscll(t2);
+ } else {
+ /*
+ * Same as above but without TSC.
+ */
+
wait_8254_wraparound ();

- tt2=apic_read(APIC_TMCCT);
- rdtscll(t2);
+ tt1=apic_read(APIC_TMCCT);
+
+ for (i=0; i<LOOPS; i++)
+ wait_8254_wraparound ();
+
+ tt2=apic_read(APIC_TMCCT);
+ }

/*
* The APIC bus clock counter is 32 bits only, it
@@ -2060,16 +2078,18 @@

calibration_result = (tt1-tt2)*APIC_DIVISOR/LOOPS;

- SMP_PRINTK(("\n..... %ld CPU clocks in 1 timer chip tick.",
- (unsigned long)(t2-t1)/LOOPS));
+ if (cpu_data[smp_processor_id()].x86_capability & X86_FEATURE_TSC)
+ SMP_PRINTK(("\n..... %ld CPU clocks in 1 timer chip tick.",
+ (unsigned long)(t2-t1)/LOOPS));

SMP_PRINTK(("\n..... %ld APIC bus clocks in 1 timer chip tick.",
calibration_result));


- printk("\n..... CPU clock speed is %ld.%04ld MHz.\n",
- ((long)(t2-t1)/LOOPS)/(1000000/HZ),
- ((long)(t2-t1)/LOOPS)%(1000000/HZ) );
+ if (cpu_data[smp_processor_id()].x86_capability & X86_FEATURE_TSC)
+ printk("\n..... CPU clock speed is %ld.%04ld MHz.\n",
+ ((long)(t2-t1)/LOOPS)/(1000000/HZ),
+ ((long)(t2-t1)/LOOPS)%(1000000/HZ) );

printk("..... system bus clock speed is %ld.%04ld MHz.\n",
calibration_result/(1000000/HZ),
diff -u --recursive --new-file linux-2.3.10.macro/include/asm-i386/i82489.h linux-2.3.10/include/asm-i386/i82489.h
--- linux-2.3.10.macro/include/asm-i386/i82489.h Tue Jan 26 23:33:51 1999
+++ linux-2.3.10/include/asm-i386/i82489.h Sun Jul 11 21:55:42 1999
@@ -5,6 +5,7 @@
* Offsets for programming the 82489 and Pentium integrated APIC
*
* Alan Cox <Alan.Cox@linux.org>, 1995.
+ * Maciej W. Rozycki <macro@ds2.pg.gda.pl>, 1999.
*/
#define APIC_PHYS_BASE 0xfee00000 /* IA s/w dev Vol 3, Section 7.4 */

@@ -62,8 +63,14 @@
#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF)
#define SET_APIC_DEST_FIELD(x) ((x)<<24)
#define APIC_LVTT 0x320
-#define APIC_LVT0 0x350
+#define APIC_LVT_TIMER_BASE_MASK (0x3<<18)
+#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3)
+#define SET_APIC_TIMER_BASE(x) (((x)<<18))
+#define APIC_TIMER_BASE_CLKIN 0x0
+#define APIC_TIMER_BASE_TMBASE 0x1
+#define APIC_TIMER_BASE_DIV 0x2
#define APIC_LVT_TIMER_PERIODIC (1<<17)
+#define APIC_LVT0 0x350
#define APIC_LVT_MASKED (1<<16)
#define APIC_LVT_LEVEL_TRIGGER (1<<15)
#define APIC_LVT_REMOTE_IRR (1<<14)
@@ -79,6 +86,7 @@
#define APIC_TMICT 0x380
#define APIC_TMCCT 0x390
#define APIC_TDCR 0x3E0
+#define APIC_TDR_DIV_TMBASE (1<<2)
#define APIC_TDR_DIV_1 0xB
#define APIC_TDR_DIV_2 0x0
#define APIC_TDR_DIV_4 0x1

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.027 / U:1.984 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site