From: Jes Sorensen <jes@wildopensource.com>
To: linux-ia64@vger.kernel.org
Subject: Re: [Linux-ia64] [patch] 2.4 timer_interrupt/gettimeoffset machvec
Date: Thu, 17 Apr 2003 23:02:26 +0000 [thread overview]
Message-ID: <marc-linux-ia64-105590723705549@msgid-missing> (raw)
In-Reply-To: <marc-linux-ia64-105590723705438@msgid-missing>
>>>>> "David" = David Mosberger <davidm@napali.hpl.hp.com> writes:
>>>>> On Tue, 8 Apr 2003 14:49:25 -0700, Jesse Barnes <jbarnes@sgi.com> said:
Jesse> The problem is that we want high resolution gettimeofday, which
Jesse> means that we need to know how long its been since wall time
Jesse> was updated when gettimeoffset is called. We do that right now
Jesse> by snapshoting the RTC in timer_interrupt...
David> Clearly you need to establish the relationship between the
David> external clock and time-of-day somewhere, but I'm not so sure
David> this should be done in the arch-specific timer interrupt
David> handler. I suspect you really want to do it where the
David> time-of-day gets updated. Also, I think this should be treated
David> much more as a driver issue rather than a platform-issue
David> (suppose someone plugged in an adapter card providing a
David> low-latency, atomic accurracy & high precision lock, you'd
David> presumably want to be able to use that card in favor of
David> whatever other hardware might be there.
Hi David,
Here is an attempt to do just that using the SN2 RTC timer by
providing a hook one can plug into where wall time is updated. This
patch is against Bjorn's tree as of a little while ago and leaves the
old concept in place for the ITC codepath - not sure if we want to try
and convert that over.
Comments? If you think this is a better solution, I'll go ahead and
forward port it to 2.5 as well.
Cheers,
Jes
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/arch/ia64/kernel/time.c linux-2.4.21-hack-timer/arch/ia64/kernel/time.c
--- linux-2.4.21-pre5-cset-1.1020/arch/ia64/kernel/time.c Thu Nov 28 18:53:09 2002
+++ linux-2.4.21-hack-timer/arch/ia64/kernel/time.c Thu Apr 17 13:06:14 2003
@@ -61,8 +61,8 @@
* Return the number of micro-seconds that elapsed since the last update to jiffy. The
* xtime_lock must be at least read-locked when calling this routine.
*/
-static inline unsigned long
-gettimeoffset (void)
+unsigned long
+__ia64_gettimeoffset (void)
{
unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
unsigned long now, last_tick;
@@ -102,6 +102,9 @@
tv->tv_sec--;
}
+ if (update_wall_time_plug)
+ update_wall_time_plug();
+
xtime = *tv;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/arch/ia64/sn/kernel/setup.c linux-2.4.21-hack-timer/arch/ia64/sn/kernel/setup.c
--- linux-2.4.21-pre5-cset-1.1020/arch/ia64/sn/kernel/setup.c Sun Apr 6 17:14:59 2003
+++ linux-2.4.21-hack-timer/arch/ia64/sn/kernel/setup.c Thu Apr 17 17:26:09 2003
@@ -76,6 +76,7 @@
extern void bte_init_node (nodepda_t *, cnodeid_t);
extern void bte_init_cpu (void);
+extern void sn_timer_init (void);
unsigned long sn_rtc_cycles_per_second;
unsigned long sn_rtc_usec_per_cyc;
@@ -313,6 +314,8 @@
* Turn off "floating-point assist fault" warnings by default.
*/
current->thread.flags |= IA64_THREAD_FPEMU_NOPRINT;
+
+ sn_timer_init();
}
/**
@@ -510,54 +513,6 @@
return GET_RTC_COUNTER();
}
-/**
- * gettimeoffset - number of usecs elapsed since &xtime was last updated
- *
- * This function is used by do_gettimeofday() to determine the number
- * of usecs that have elapsed since the last update to &xtime. On SN
- * this is accomplished using the RTC built in to each Hub chip; each
- * is guaranteed to be synchronized by the PROM, so a local read will
- * suffice (get_cycles() does this for us). A snapshot of the RTC value
- * is taken on every timer interrupt and this function more or less
- * subtracts that snapshot value from the current value.
- *
- * Note that if a lot of processing was done during the last timer
- * interrupt then &xtime may be some number of jiffies out of date.
- * This function must account for that.
- */
-unsigned long
-gettimeoffset(void)
-{
- unsigned long current_rtc_val, local_last_rtc_val;
- unsigned long usec;
-
- local_last_rtc_val = last_rtc_val;
- current_rtc_val = get_cycles();
- usec = last_itc_lost_usec;
-
- /* If the RTC has wrapped around, compensate */
- if (unlikely(current_rtc_val < local_last_rtc_val)) {
- printk(KERN_NOTICE "RTC wrapped cpu:%d current:0x%lx last:0x%lx\n",
- smp_processor_id(), current_rtc_val,
- local_last_rtc_val);
- current_rtc_val += RTC_MASK;
- }
-
- usec += ((current_rtc_val - local_last_rtc_val)*sn_rtc_usec_per_cyc) >>
- IA64_USEC_PER_CYC_SHIFT;
-
- /*
- * usec is the number of microseconds into the current clock interval. Every
- * clock tick, xtime is advanced by "tick" microseconds. If "usec"
- * is allowed to get larger than "tick", the time value returned by gettimeofday
- * will go backward.
- */
- if (usec >= tick)
- usec = tick-1;
-
- return usec;
-}
-
#ifdef II_PRTE_TLB_WAR
long iiprt_lock[16*64] __cacheline_aligned; /* allow for NASIDs up to 64 */
#endif
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/arch/ia64/sn/kernel/sn2/Makefile linux-2.4.21-hack-timer/arch/ia64/sn/kernel/sn2/Makefile
--- linux-2.4.21-pre5-cset-1.1020/arch/ia64/sn/kernel/sn2/Makefile Sun Apr 6 17:14:59 2003
+++ linux-2.4.21-hack-timer/arch/ia64/sn/kernel/sn2/Makefile Tue Apr 15 19:37:40 2003
@@ -42,6 +42,6 @@
O_TARGET = sn2.o
-obj-y = cache.o iomv.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o
+obj-y = cache.o iomv.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o timer.o
include $(TOPDIR)/Rules.make
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/arch/ia64/sn/kernel/sn2/timer.c linux-2.4.21-hack-timer/arch/ia64/sn/kernel/sn2/timer.c
--- linux-2.4.21-pre5-cset-1.1020/arch/ia64/sn/kernel/sn2/timer.c Wed Dec 31 19:00:00 1969
+++ linux-2.4.21-hack-timer/arch/ia64/sn/kernel/sn2/timer.c Thu Apr 17 17:30:42 2003
@@ -0,0 +1,83 @@
+/*
+ * linux/arch/ia64/sn/kernel/sn2/timer.c
+ *
+ * Copyright (C) 2003 Silicon Graphics, Inc.
+ */
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/efi.h>
+
+#include <asm/delay.h>
+#include <asm/hw_irq.h>
+#include <asm/ptrace.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+
+#include <asm/sn/leds.h>
+#include <asm/sn/clksupport.h>
+
+extern rwlock_t xtime_lock;
+
+extern unsigned long sn_rtc_cycles_per_second;
+extern unsigned long sn_rtc_usec_per_cyc;
+static unsigned long sn_rtc_per_itc;
+static unsigned long sn_rtc_delta;
+static volatile unsigned long last_rtc_val;
+
+/**
+ * gettimeoffset - number of usecs elapsed since &xtime was last updated
+ *
+ * This function is used by do_gettimeofday() to determine the number
+ * of usecs that have elapsed since the last update to &xtime. On SN
+ * this is accomplished using the RTC built in to each Hub chip; each
+ * is guaranteed to be synchronized by the PROM, so a local read will
+ * suffice (GET_RTC_COUNTER() does this for us). A snapshot of the RTC
+ * value is taken every time wall_jiffies is updated by the
+ * update_wall_time_plug (sn2_update_wall_time) which means we don't
+ * have to adjust for lost jiffies ticks or anything like that.
+ */
+unsigned long
+sn_gettimeoffset(void)
+{
+ unsigned long current_rtc;
+ long elapsed_rtc;
+
+ current_rtc = GET_RTC_COUNTER();
+
+ /*
+ * Need to address wrapping here!
+ */
+ elapsed_rtc = (long)(current_rtc - last_wall_rtc);
+
+ if (elapsed_rtc < 0) {
+ printk(KERN_INFO "sn_gettimeoffset(): time goes backwards! "
+ "current_rtc 0x%016lx, last_wall_rtc 0x%016lx\n",
+ current_rtc, last_wall_rtc);
+ }
+
+ return (elapsed_rtc * (long)sn_rtc_usec_per_cyc) >>
+ IA64_USEC_PER_CYC_SHIFT;
+}
+
+
+void sn2_update_wall_time()
+{
+ last_wall_rtc = GET_RTC();
+}
+
+
+void __init
+sn_timer_init (void)
+{
+ sn_rtc_per_itc = (sn_rtc_cycles_per_second << SN_RTC_PER_ITC_SHIFT) /
+ local_cpu_data->itc_freq;
+ sn_rtc_delta = local_cpu_data->itm_delta * sn_rtc_per_itc;
+
+ last_wall_rtc = GET_RTC_COUNTER();
+ update_wall_time_plug = sn2_update_wall_time;
+}
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/machvec.h linux-2.4.21-hack-timer/include/asm-ia64/machvec.h
--- linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/machvec.h Sun Apr 6 17:37:58 2003
+++ linux-2.4.21-hack-timer/include/asm-ia64/machvec.h Tue Apr 15 19:37:40 2003
@@ -63,6 +63,7 @@
typedef void ia64_mv_outb_t (unsigned char, unsigned long);
typedef void ia64_mv_outw_t (unsigned short, unsigned long);
typedef void ia64_mv_outl_t (unsigned int, unsigned long);
+typedef unsigned long ia64_mv_gettimeoffset_t (void);
extern void machvec_noop (void);
@@ -113,6 +114,7 @@
# define platform_outb ia64_mv.outb
# define platform_outw ia64_mv.outw
# define platform_outl ia64_mv.outl
+# define platform_gettimeoffset ia64_mv.gettimeoffset
# endif
struct ia64_machine_vector {
@@ -148,6 +150,7 @@
ia64_mv_outb_t *outb;
ia64_mv_outw_t *outw;
ia64_mv_outl_t *outl;
+ ia64_mv_gettimeoffset_t *gettimeoffset;
};
#define MACHVEC_INIT(name) \
@@ -183,7 +186,8 @@
platform_inl, \
platform_outb, \
platform_outw, \
- platform_outl \
+ platform_outl, \
+ platform_gettimeoffset \
}
extern struct ia64_machine_vector ia64_mv;
@@ -206,6 +210,7 @@
extern ia64_mv_pci_dma_sync_single swiotlb_sync_single;
extern ia64_mv_pci_dma_sync_sg swiotlb_sync_sg;
extern ia64_mv_pci_dma_supported swiotlb_pci_dma_supported;
+extern ia64_mv_gettimeoffset_t __ia64_gettimeoffset;
/*
* Define default versions so we can extend machvec for new platforms without having
@@ -301,5 +306,8 @@
#ifndef platform_outl
# define platform_outl __ia64_outl
#endif
+#ifndef platform_gettimeoffset
+# define platform_gettimeoffset __ia64_gettimeoffset
+#endif
#endif /* _ASM_IA64_MACHVEC_H */
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/machvec_sn2.h linux-2.4.21-hack-timer/include/asm-ia64/machvec_sn2.h
--- linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/machvec_sn2.h Sun Apr 6 17:15:02 2003
+++ linux-2.4.21-hack-timer/include/asm-ia64/machvec_sn2.h Tue Apr 15 19:37:40 2003
@@ -58,6 +58,7 @@
extern ia64_mv_pci_dma_sync_single sn_pci_dma_sync_single;
extern ia64_mv_pci_dma_sync_sg sn_pci_dma_sync_sg;
extern ia64_mv_pci_dma_supported sn_pci_dma_supported;
+extern ia64_mv_gettimeoffset_t sn_gettimeoffset;
/*
* This stuff has dual use!
@@ -93,5 +94,6 @@
#define platform_pci_dma_sync_single sn_pci_dma_sync_single
#define platform_pci_dma_sync_sg sn_pci_dma_sync_sg
#define platform_pci_dma_supported sn_pci_dma_supported
+#define platform_gettimeoffset sn_gettimeoffset
#endif /* _ASM_IA64_MACHVEC_SN2_H */
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/sn/clksupport.h linux-2.4.21-hack-timer/include/asm-ia64/sn/clksupport.h
--- linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/sn/clksupport.h Sun Apr 6 17:15:02 2003
+++ linux-2.4.21-hack-timer/include/asm-ia64/sn/clksupport.h Tue Apr 15 19:37:40 2003
@@ -38,7 +38,7 @@
extern nasid_t master_nasid;
-#define RTC_MASK (0x007fffffffffffff)
+#define RTC_MASK 0x007fffffffffffffUL
/* clocks are not synchronized yet on SN1 - used node 0 (problem if no NASID 0) */
#define RTC_COUNTER_ADDR ((clkreg_t*)REMOTE_HUB_ADDR(master_nasid, PI_RT_COUNTER))
#define RTC_COMPARE_A_ADDR ((clkreg_t*)REMOTE_HUB_ADDR(master_nasid, PI_RT_COMPARE_A))
@@ -52,7 +52,7 @@
#include <asm/sn/sn2/addrs.h>
#include <asm/sn/sn2/shubio.h>
#include <asm/sn/sn2/shub_mmr.h>
-#define RTC_MASK (SH_RTC_MASK)
+#define RTC_MASK SH_RTC_MASK
#define RTC_COUNTER_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
#define RTC_COMPARE_A_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
#define RTC_COMPARE_B_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
@@ -62,7 +62,7 @@
#define RTC_INT_ENABLED_B_ADDR ((clkreg_t*)LOCAL_MMR_ADDR(SH_RTC))
#endif /* CONFIG_IA64_SGI_SN1 */
-
+#define SN_RTC_PER_ITC_SHIFT 34
#define GET_RTC_COUNTER() (*RTC_COUNTER_ADDR)
#define rtc_time() GET_RTC_COUNTER()
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/timex.h linux-2.4.21-hack-timer/include/asm-ia64/timex.h
--- linux-2.4.21-pre5-cset-1.1020/include/asm-ia64/timex.h Thu Nov 28 18:53:15 2002
+++ linux-2.4.21-hack-timer/include/asm-ia64/timex.h Tue Apr 15 19:37:40 2003
@@ -24,4 +24,6 @@
#define vxtime_lock() do {} while (0)
#define vxtime_unlock() do {} while (0)
+#define gettimeoffset() platform_gettimeoffset()
+
#endif /* _ASM_IA64_TIMEX_H */
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/include/linux/timex.h linux-2.4.21-hack-timer/include/linux/timex.h
--- linux-2.4.21-pre5-cset-1.1020/include/linux/timex.h Sun Apr 6 17:37:58 2003
+++ linux-2.4.21-hack-timer/include/linux/timex.h Thu Apr 17 13:07:29 2003
@@ -286,6 +286,12 @@
extern long pps_errcnt; /* calibration errors */
extern long pps_stbcnt; /* stability limit exceeded */
+/*
+ * Call-back for high precision timer sources to snapshot every time
+ * wall_jiffies is updated.
+ */
+extern void (*update_wall_time_plug)(void);
+
#endif /* KERNEL */
#endif /* LINUX_TIMEX_H */
diff -X /home/jes/exclude-linux -urN linux-2.4.21-pre5-cset-1.1020/kernel/timer.c linux-2.4.21-hack-timer/kernel/timer.c
--- linux-2.4.21-pre5-cset-1.1020/kernel/timer.c Sun Apr 6 17:17:16 2003
+++ linux-2.4.21-hack-timer/kernel/timer.c Tue Apr 15 19:28:54 2003
@@ -514,6 +514,14 @@
}
/*
+ * Hook for using external high precision timers for the system clock.
+ * On systems where the CPU clock isn't synchronized between CPUs,
+ * it is necessary to use an external source such as an RTC to obtain
+ * precision in gettimeofday().
+ */
+void (*update_wall_time_plug)(void) = NULL;
+
+/*
* Using a loop looks inefficient, but "ticks" is
* usually just one (we shouldn't be losing ticks,
* we're doing this this way mainly for interrupt
@@ -522,6 +530,9 @@
*/
static void update_wall_time(unsigned long ticks)
{
+ if (update_wall_time_plug)
+ update_wall_time_plug();
+
do {
ticks--;
update_wall_time_one_tick();
next prev parent reply other threads:[~2003-04-17 23:02 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-04-08 20:35 [Linux-ia64] [patch] 2.4 timer_interrupt/gettimeoffset machvec Jes Sorensen
2003-04-08 21:41 ` David Mosberger
2003-04-08 21:49 ` Jesse Barnes
2003-04-09 17:53 ` David Mosberger
2003-04-09 18:43 ` Grant Grundler
2003-04-14 23:22 ` Jesse Barnes
2003-04-17 23:02 ` Jes Sorensen [this message]
2003-04-17 23:43 ` David Mosberger
2003-04-18 0:00 ` Jes Sorensen
2003-04-18 1:21 ` Jes Sorensen
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=marc-linux-ia64-105590723705549@msgid-missing \
--to=jes@wildopensource.com \
--cc=linux-ia64@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.