patch-2.4.18 linux/arch/s390x/kernel/time.c
Next file: linux/arch/s390x/kernel/traps.c
Previous file: linux/arch/s390x/kernel/smp.c
Back to the patch index
Back to the overall index
- Lines: 222
- Date:
Mon Feb 4 16:55:13 2002
- Orig file:
linux.orig/arch/s390x/kernel/time.c
- Orig date:
Mon Feb 18 20:18:39 2002
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/time.c linux/arch/s390x/kernel/time.c
@@ -33,65 +33,33 @@
#include <asm/irq.h>
#include <asm/s390_ext.h>
-
/* change this if you have some constant time drift */
-#define USECS_PER_JIFFY ((signed long)1000000/HZ)
-#define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12)
+#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
+#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
#define TICK_SIZE tick
-static uint64_t init_timer_cc, last_timer_cc;
+static uint64_t init_timer_cc;
extern rwlock_t xtime_lock;
extern unsigned long wall_jiffies;
-void tod_to_timeval(uint64_t todval, struct timeval *xtime)
+void tod_to_timeval(__u64 todval, struct timeval *xtime)
{
-#if 0
- const int high_bit = 0x80000000L;
- const int c_f4240 = 0xf4240L;
- const int c_7a120 = 0x7a120;
- /* We have to divide the 64 bit value todval by 4096
- * (because the 2^12 bit is the one that changes every
- * microsecond) and then split it into seconds and
- * microseconds. A value of max (2^52-1) divided by
- * the value 0xF4240 can yield a max result of approx
- * (2^32.068). Thats to big to fit into a signed int
- * ... hacking time!
- */
- asm volatile ("L 2,%1\n\t"
- "LR 3,2\n\t"
- "SRL 2,12\n\t"
- "SLL 3,20\n\t"
- "L 4,%O1+4(%R1)\n\t"
- "SRL 4,12\n\t"
- "OR 3,4\n\t" /* now R2/R3 contain (todval >> 12) */
- "SR 4,4\n\t"
- "CL 2,%2\n\t"
- "JL .+12\n\t"
- "S 2,%2\n\t"
- "L 4,%3\n\t"
- "D 2,%4\n\t"
- "OR 3,4\n\t"
- "ST 2,%O0+4(%R0)\n\t"
- "ST 3,%0"
- : "=m" (*xtime) : "m" (todval),
- "m" (c_7a120), "m" (high_bit), "m" (c_f4240)
- : "cc", "memory", "2", "3", "4" );
-#else
- todval >>= 12;
- xtime->tv_sec = todval / 1000000;
- xtime->tv_usec = todval % 1000000;
-#endif
+ todval >>= 12;
+ xtime->tv_sec = todval / 1000000;
+ xtime->tv_usec = todval % 1000000;
}
-unsigned long do_gettimeoffset(void)
+static inline unsigned long do_gettimeoffset(void)
{
- __u64 timer_cc;
+ __u64 now;
- asm volatile ("STCK %0" : "=m" (timer_cc));
- /* We require the offset from the previous interrupt */
- return ((unsigned long)((timer_cc - last_timer_cc)>>12));
+ asm ("STCK %0" : "=m" (now));
+ now = (now - init_timer_cc) >> 12;
+ /* We require the offset from the latest update of xtime */
+ now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
+ return (unsigned long) now;
}
/*
@@ -101,15 +69,10 @@
{
unsigned long flags;
unsigned long usec, sec;
- unsigned long lost_ticks;
read_lock_irqsave(&xtime_lock, flags);
- lost_ticks = jiffies - wall_jiffies;
- usec = do_gettimeoffset();
- if (lost_ticks)
- usec +=(USECS_PER_JIFFY*lost_ticks);
sec = xtime.tv_sec;
- usec += xtime.tv_usec;
+ usec = xtime.tv_usec + do_gettimeoffset();
read_unlock_irqrestore(&xtime_lock, flags);
while (usec >= 1000000) {
@@ -155,51 +118,31 @@
extern __u16 boot_cpu_addr;
#endif
-void do_timer_interrupt(struct pt_regs *regs, __u16 error_code)
+static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code)
{
int cpu = smp_processor_id();
irq_enter(cpu, 0);
- /*
- * reset timer to 10ms minus time already elapsed
- * since timer-interrupt pending
- */
+ /*
+ * set clock comparator for next tick
+ */
+ S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
+ asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
+
#ifdef CONFIG_SMP
- if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) {
+ if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr)
write_lock(&xtime_lock);
- last_timer_cc = S390_lowcore.jiffy_timer_cc;
- }
-#else
- last_timer_cc = S390_lowcore.jiffy_timer_cc;
-#endif
- /* set clock comparator */
- S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
- asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
-/*
- * In the SMP case we use the local timer interrupt to do the
- * profiling, except when we simulate SMP mode on a uniprocessor
- * system, in that case we have to call the local interrupt handler.
- */
-#ifdef CONFIG_SMP
- /* when SMP, do smp_local_timer_interrupt for *all* CPUs,
- but only do the rest for the boot CPU */
- smp_local_timer_interrupt(regs);
-#else
- if (!user_mode(regs))
- s390_do_profile(regs->psw.addr);
-#endif
+ update_process_times(user_mode(regs));
-#ifdef CONFIG_SMP
- if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr)
-#endif
- {
+ if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) {
do_timer(regs);
-#ifdef CONFIG_SMP
write_unlock(&xtime_lock);
-#endif
}
+#else
+ do_timer(regs);
+#endif
irq_exit(cpu, 0);
}
@@ -207,19 +150,17 @@
/*
* Start the clock comparator on the current CPU
*/
-static unsigned long cr0 __attribute__ ((aligned (8)));
-
-void init_100hz_timer(void)
+void init_cpu_timer(void)
{
+ unsigned long cr0;
+
/* allow clock comparator timer interrupt */
asm volatile ("STCTG 0,0,%0" : "=m" (cr0) : : "memory");
cr0 |= 0x800;
asm volatile ("LCTLG 0,0,%0" : : "m" (cr0) : "memory");
- /* set clock comparator */
- /* read the TOD clock */
- asm volatile ("STCK %0" : "=m" (S390_lowcore.jiffy_timer_cc));
- S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
- asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
+ S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY;
+ S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY;
+ asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
}
/*
@@ -228,6 +169,7 @@
*/
void __init time_init(void)
{
+ __u64 set_time_cc;
int cc;
/* kick the TOD clock */
@@ -247,15 +189,16 @@
printk("time_init: TOD clock stopped/non-operational\n");
break;
}
+
+ /* set xtime */
+ set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
+ (0x3c26700LL*1000000*4096);
+ tod_to_timeval(set_time_cc, &xtime);
+
/* request the 0x1004 external interrupt */
- if (register_external_interrupt(0x1004, do_timer_interrupt) != 0)
- panic("Couldn't request external interrupts 0x1004");
- init_100hz_timer();
- init_timer_cc = S390_lowcore.jiffy_timer_cc;
- init_timer_cc -= 0x8126d60e46000000LL -
- (0x3c26700LL*1000000*4096);
- tod_to_timeval(init_timer_cc, &xtime);
+ if (register_external_interrupt(0x1004, do_comparator_interrupt) != 0)
+ panic("Couldn't request external interrupt 0x1004");
- /* Set do_get_fast_time function pointer. */
- do_get_fast_time = do_gettimeofday;
+ /* init CPU timer */
+ init_cpu_timer();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)