public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: john stultz <johnstul@us.ibm.com>
To: marcelo <marcelo@conectiva.com.br>
Cc: lkml <linux-kernel@vger.kernel.org>,
	Leah Cunningham <leahc@us.ibm.com>,
	wilhelm.nuesser@sap.com, paramjit@us.ibm.com, msw@redhat.com,
	James <jamesclv@us.ibm.com>
Subject: [PATCH] cyclone-timer_A9
Date: 07 Aug 2002 19:15:56 -0700	[thread overview]
Message-ID: <1028772956.22920.207.camel@cog> (raw)
In-Reply-To: <1028771615.22918.188.camel@cog>

Marcelo,
	This patch (which applies on top of my tsc-disable_B9 patch as well as
James Cleverdon's summit patch), is a performance improvement for
multi-CEC IBM x440 systems which suffer from drifting TSCs. Rather then
forcing do_gettimeofday to call do_slow_gettimeoffset and access the PIT
(as my tsc-disable patch does), passing "cyclone" as a boot option will
make do_gettimeofday use a 100Mhz performance counter found in the
Summit chipset.

This patch does not effect/correct userspace access to the unsynced TSC
registers via the rdtsc call.

Comments, flames, etc welcome.

thanks
-john

diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help
--- a/Documentation/Configure.help	Wed Aug  7 19:00:21 2002
+++ b/Documentation/Configure.help	Wed Aug  7 19:00:21 2002
@@ -252,6 +252,14 @@
   You will need a new lynxer.elf file to flash your firmware with - send
   email to Martin.Bligh@us.ibm.com
 
+IBM x440 Summit support
+CONFIG_X86_SUMMIT_NUMA
+  This option enables support for the IBM x440 and related multi-CEC 
+  systems based on the Summit chipset. This options allows you to pass
+  "cyclone" as a boot option to make use of a performance counter on 
+  the Cyclone chipset for calculating do_gettimeofday, greatly 
+  improving performance when compared to the PIT based method. 
+
 IO-APIC support on uniprocessors
 CONFIG_X86_UP_IOAPIC
   An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
--- a/arch/i386/config.in	Wed Aug  7 19:00:20 2002
+++ b/arch/i386/config.in	Wed Aug  7 19:00:20 2002
@@ -205,6 +205,7 @@
    bool 'Multi-node NUMA system support' CONFIG_X86_NUMA
    if [ "$CONFIG_X86_NUMA" = "y" ]; then
       bool '  Multiquad (IBM/Sequent) NUMAQ support' CONFIG_MULTIQUAD
+      bool '  IBM x440 Summit support' CONFIG_X86_SUMMIT_NUMA
    fi
 fi
 
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c	Wed Aug  7 19:00:20 2002
+++ b/arch/i386/kernel/time.c	Wed Aug  7 19:00:21 2002
@@ -256,6 +256,138 @@
 
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
 
+
+
+#ifdef CONFIG_X86_SUMMIT_NUMA
+
+#define CYCLONE_CBAR_ADDR 0xFEB00CD0
+#define CYCLONE_PMCC_OFFSET 0x51A0
+#define CYCLONE_MPMC_OFFSET 0x51D0
+#define CYCLONE_MPCS_OFFSET 0x51A8
+#define CYCLONE_TIMER_FREQ 100000000
+
+static int use_cyclone __initdata = 0;
+static int __init cyclone_setup(char *str)
+{
+	bad_tsc = 1;
+	use_cyclone = 1;
+	return 1;
+}
+__setup("cyclone", cyclone_setup);
+
+
+static u32* cyclone_timer;	/*Cyclone MPMC0 register*/
+static u32 last_cyclone_timer;
+
+static inline void mark_timeoffset_cyclone(void)
+{
+	int count;
+
+	/*quickly read the cyclone timer*/
+	if(cyclone_timer)
+		last_cyclone_timer = cyclone_timer[0];
+
+	/*calculate delay_at_last_interrupt*/
+	spin_lock(&i8253_lock);
+	outb_p(0x00, 0x43);     /* latch the count ASAP */
+
+	count = inb_p(0x40);    /* read the latched count */
+	count |= inb(0x40) << 8;
+	spin_unlock(&i8253_lock);
+
+	count = ((LATCH-1) - count) * TICK_SIZE;
+	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
+}
+
+static unsigned long do_gettimeoffset_cyclone(void)
+{
+	u32 offset;
+
+	if(!cyclone_timer)
+		return delay_at_last_interrupt;
+
+	/* Read the cyclone timer */
+	offset = cyclone_timer[0];
+
+	/* .. relative to previous jiffy*/
+	offset = offset - last_cyclone_timer;
+
+	/*convert cyclone ticks to microseconds*/	
+	offset = offset/100;	/*XXX slow, can we speed this up?*/
+
+	/* our adjusted time offset in microseconds */
+	return delay_at_last_interrupt + offset;
+}
+
+static void init_cyclone_clock(void)
+{
+	u32* reg;	
+	u32 base;	/*saved cyclone base address*/
+	u32 pageaddr; /*page that contains cyclone_timer register*/
+	u32 offset;	/*offset from pageaddr to cyclone_timer register*/
+
+	printk("Summit chipset: Starting Cyclone Clock.\n");
+
+	/*find base address*/
+	pageaddr = (CYCLONE_CBAR_ADDR)&PAGE_MASK;
+	offset = (CYCLONE_CBAR_ADDR)&(~PAGE_MASK);
+	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
+	reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
+	if(!reg){
+		printk("Summit chipset: Could not find valid CBAR register.\n");
+		return;
+	}
+	base = *reg;	
+	if(!base){
+		printk("Summit chipset: Could not find valid CBAR value.\n");
+		return;
+	}
+	
+	/*setup PMCC*/
+	pageaddr = (base + CYCLONE_PMCC_OFFSET)&PAGE_MASK;
+	offset = (base + CYCLONE_PMCC_OFFSET)&(~PAGE_MASK);
+	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
+	reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
+	if(!reg){
+		printk("Summit chipset: Could not find valid PMCC register.\n");
+		return;
+	}
+	reg[0] = 0x00000001;
+
+	/*setup MPCS*/
+	pageaddr = (base + CYCLONE_MPCS_OFFSET)&PAGE_MASK;
+	offset = (base + CYCLONE_MPCS_OFFSET)&(~PAGE_MASK);
+	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
+	reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
+	if(!reg){
+		printk("Summit chipset: Could not find valid MPCS register.\n");
+		return;
+	}
+	reg[0] = 0x00000001;
+
+	/*map in cyclone_timer*/
+	pageaddr = (base + CYCLONE_MPMC_OFFSET)&PAGE_MASK;
+	offset = (base + CYCLONE_MPMC_OFFSET)&(~PAGE_MASK);
+	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
+	cyclone_timer = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
+	if(!cyclone_timer){
+		printk("Summit chipset: Could not find valid MPMC register.\n");
+		return;
+	}
+
+	/* Everything looks good, so set do_gettimeoffset*/
+	do_gettimeoffset = do_gettimeoffset_cyclone;	
+}
+
+#else /*CONFIG_X86_SUMMIT_NUMA*/
+
+#define use_cyclone 0
+static void mark_timeoffset_cyclone(void) {}
+static unsigned long do_gettimeoffset_cyclone(void) {return 0;}
+static void init_cyclone_clock(void) {}
+
+#endif /*CONFIG_X86_SUMMIT_NUMA*/
+
 #else
 
 #define do_gettimeoffset()	do_fast_gettimeoffset()
@@ -481,8 +613,7 @@
 	 */
 	write_lock(&xtime_lock);
 
-	if (use_tsc)
-	{
+	if (use_tsc) {
 		/*
 		 * It is important that these two operations happen almost at
 		 * the same time. We do the RDTSC stuff first, since it's
@@ -508,8 +639,11 @@
 
 		count = ((LATCH-1) - count) * TICK_SIZE;
 		delay_at_last_interrupt = (count + LATCH/2) / LATCH;
-	}
- 
+	} else {
+		if(use_cyclone)
+			mark_timeoffset_cyclone();
+ 	}
+	
 	do_timer_interrupt(irq, NULL, regs);
 
 	write_unlock(&xtime_lock);
@@ -709,6 +843,9 @@
 			}
 		}
 	}
+
+ 	if((!use_tsc) && use_cyclone)
+		init_cyclone_clock();
 
 #ifdef CONFIG_VISWS
 	printk("Starting Cobalt Timer system clock\n");
diff -Nru a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
--- a/include/asm-i386/fixmap.h	Wed Aug  7 19:00:20 2002
+++ b/include/asm-i386/fixmap.h	Wed Aug  7 19:00:20 2002
@@ -61,6 +61,9 @@
 	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
 	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
 #endif
+#ifdef CONFIG_X86_SUMMIT_NUMA
+	FIX_CYCLONE_TIMER, /*cyclone timer register*/
+#endif 
 #ifdef CONFIG_HIGHMEM
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,



  reply	other threads:[~2002-08-08  2:26 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-08-08  1:53 [PATCH] tsc-disable_B9 john stultz
2002-08-08  2:15 ` john stultz [this message]
2002-08-08 13:18   ` [PATCH] cyclone-timer_A9 Alan Cox
2002-08-09  2:03     ` john stultz
2002-08-08 13:17 ` [PATCH] tsc-disable_B9 Alan Cox
2002-08-09  2:30   ` john stultz
2002-08-09  9:17     ` Alan Cox
2002-08-09 17:46       ` john stultz
2002-08-09 18:49         ` george anzinger
2002-08-09 20:58           ` john stultz
2002-08-13  1:23             ` James Cleverdon
2002-08-11 20:16         ` Alan Cox
2002-08-15 16:56     ` Andrea Arcangeli
2002-08-16 11:15       ` Alan Cox
2002-08-16 13:19         ` Mikael Pettersson
2002-08-21 13:12           ` Andrea Arcangeli
2002-08-21 14:10             ` Alan Cox
2002-08-21 14:33               ` Andrea Arcangeli
2002-08-21 15:01                 ` Alan Cox
2002-08-21 16:13                   ` Andrea Arcangeli
2002-08-21 16:25                     ` Alan Cox
2002-08-21 17:17                       ` Andrea Arcangeli
2002-08-21 17:34                         ` Alan Cox
2002-08-26 16:10                     ` Pavel Machek
2002-08-26 18:45                       ` Martin J. Bligh
2002-08-26 19:00                         ` Pavel Machek
2002-08-26 19:05                         ` Alan Cox
2002-08-26 20:19                           ` Martin J. Bligh
2002-08-26 19:18                         ` Richard B. Johnson
2002-08-26 19:42                           ` Pavel Machek
2002-08-26 20:23                           ` Alan Cox
2002-08-26 22:49                         ` Andrea Arcangeli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1028772956.22920.207.camel@cog \
    --to=johnstul@us.ibm.com \
    --cc=jamesclv@us.ibm.com \
    --cc=leahc@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marcelo@conectiva.com.br \
    --cc=msw@redhat.com \
    --cc=paramjit@us.ibm.com \
    --cc=wilhelm.nuesser@sap.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox