s390/debug: make debug event time stamps relative to the boot TOD clock
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 16 Nov 2016 08:48:41 +0000 (09:48 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 7 Feb 2017 06:27:13 +0000 (07:27 +0100)
The debug features currently uses absolute TOD time stamps for the
debug events. Given that the TOD clock can jump forward and backward
due to STP sync checks the order of debug events can get obfuscated.

Replace the absolute TOD time stamps with a delta to the IPL time
stamp. On a STP sync check the TOD clock correction is added to
the IPL time stamp as well to make the deltas unaffected by STP
sync check.

The readout of the debug feature entries will convert the deltas
back to absolute time stamps based on the Unix epoch.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/timex.h
arch/s390/kernel/debug.c
arch/s390/kernel/time.c

index de829880072245585895846e1dfed1731e66663c..354344dcc19898bb647722db24f49733b28793c6 100644 (file)
@@ -178,14 +178,6 @@ int get_phys_clock(unsigned long long *clock);
 void init_cpu_timer(void);
 unsigned long long monotonic_clock(void);
 
-void tod_to_timeval(__u64 todval, struct timespec64 *xt);
-
-static inline
-void stck_to_timespec64(unsigned long long stck, struct timespec64 *ts)
-{
-       tod_to_timeval(stck - TOD_UNIX_EPOCH, ts);
-}
-
 extern u64 sched_clock_base_cc;
 
 /**
index 79f8ae9335204dfcc25a1b8d9e07e8934b4c3bfb..20a5a4286368f4290583a6e9c54459d7f07b97e9 100644 (file)
@@ -866,7 +866,7 @@ static inline void
 debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
                        int exception)
 {
-       active->id.stck = get_tod_clock_fast();
+       active->id.stck = get_tod_clock_fast() - sched_clock_base_cc;
        active->id.fields.cpuid = smp_processor_id();
        active->caller = __builtin_return_address(0);
        active->id.fields.exception = exception;
@@ -1455,23 +1455,24 @@ int
 debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
                         int area, debug_entry_t * entry, char *out_buf)
 {
-       struct timespec64 time_spec;
+       unsigned long sec, usec;
        char *except_str;
        unsigned long caller;
        int rc = 0;
        unsigned int level;
 
        level = entry->id.fields.level;
-       stck_to_timespec64(entry->id.stck, &time_spec);
+       sec = (entry->id.stck >> 12) + (sched_clock_base_cc >> 12);
+       sec = sec - (TOD_UNIX_EPOCH >> 12);
+       usec = do_div(sec, USEC_PER_SEC);
 
        if (entry->id.fields.exception)
                except_str = "*";
        else
                except_str = "-";
        caller = (unsigned long) entry->caller;
-       rc += sprintf(out_buf, "%02i %011lld:%06lu %1u %1s %02i %p  ",
-                     area, (long long)time_spec.tv_sec,
-                     time_spec.tv_nsec / 1000, level, except_str,
+       rc += sprintf(out_buf, "%02i %011ld:%06lu %1u %1s %02i %p  ",
+                     area, sec, usec, level, except_str,
                      entry->id.fields.cpuid, (void *)caller);
        return rc;
 }
index eebbd6adc6c502ad76b869dd7f7c0040a56a95cd..546e513a0271780ff164c2668b54dba5dea072d7 100644 (file)
@@ -110,7 +110,7 @@ unsigned long long monotonic_clock(void)
 }
 EXPORT_SYMBOL(monotonic_clock);
 
-void tod_to_timeval(__u64 todval, struct timespec64 *xt)
+static void tod_to_timeval(__u64 todval, struct timespec64 *xt)
 {
        unsigned long long sec;
 
@@ -120,7 +120,6 @@ void tod_to_timeval(__u64 todval, struct timespec64 *xt)
        todval -= (sec * 1000000) << 12;
        xt->tv_nsec = ((todval * 1000) >> 12);
 }
-EXPORT_SYMBOL(tod_to_timeval);
 
 void clock_comparator_work(void)
 {