On 07/28/2011 10:26 PM, Mathieu Desnoyers wrote:
* Abbas Raza ([email protected]) wrote:
On 07/26/2011 11:02 PM, Mathieu Desnoyers wrote:
* Abbas Raza ([email protected]) wrote:
On 07/26/2011 10:17 PM, Mathieu Desnoyers wrote:
* Abbas Raza ([email protected]) wrote:
[...]
Hi Mathieu,
Some confusion here :(
In case of LTTng 0.x, when we take kernel traces then timestamps for
these traces is based on TSC/TB . So after that we view these traces by
lttv and it shows timestamps with all events which occurred.
I print the timestamp in kernel ltt function 'ltt_trace_alloc()' and it
comes out to be 22944596907 (by calling trace_clock_read64() ). While
lttv show Birth sec of first event to 367 second. How this conversion is
made from TSC to the Birth sec/nsec value displayed in lttv? just want
to confirm that whether timestamps shown in lttv (Birth sec/nsec) are
based on TSC values... if yes then how TSC values are converted to Birth
sec/nsec and i no then from where lttv gets timestamps to be displayed?
Or in simple words, do kernel traces which we get contain timestamps
based simply on TSC values or it is something else?
Yes, we write, in the lttng 0.x headers, the following information:
struct ltt_subbuffer_header {
[...]
uint64_t start_freq; /*
* Frequency at trace start,
* used all along the trace.
*/
uint32_t freq_scale; /* Frequency scaling (divisor) */
[...]
}
so by using the start frequency and the scale, we can convert from TSC
values to nanoseconds. Please note that LTTng 0.x requires the clock
source to appear as if it has a constant rate.
These values map to trace_clock_frequency() and trace_clock_freq_scale()
trace clock functions.
Best regards,
Mathieu
Thanks a lot again for help :)
Abbas Raza
Just to confirm that TSC's just have raw values of clock cycles and lttv
converts these values into sec/nsec by reading ltt_subbuffer_header ?
Yes, that's it.
Thanks,
Mathieu
Thanks!
Abbas Raza
Hello Mathieu,
Just wanted to ask that trace clock userspace patch for x86 adds
functionality to register posix clocks like
register_posix_clock(CLOCK_TRACE,&clock_trace);
register_posix_clock(CLOCK_TRACE_FREQ,&clock_trace_freq);
What we understood is that these clocks are registered to provide system
call functionality for CLOCK_TRACE and CLOCK_TRACE_FREQ clocks just like
other posix clocks. Right?
And same we will have to do for powerpc (even if we have got vdso
functionality for these clocks)?
Yes, exactly. The kernel always needs to provide a system call fallback
for vDSO, just in case the vDSO cannot be used.
Thanks
Mathieu
Thanks !
--
Abbas Raza
Hello Mathieu,
We have added userspace trace clock support for powerpc architecture. We
have verified our changes and userspace, kernel traces appear to be in
sync for powerpc now. Patches are attached for kernel and UST.
Thanks!
Abbas Raza
From 018e85ce1a15b9c02719de29663824e1e4f8bc2b Mon Sep 17 00:00:00 2001
From: Abbas Raza<[email protected]>
Date: Thu, 4 Aug 2011 16:16:28 +0500
Subject: [PATCH] Make use of TRACE_CLOCK_FREQ functionality provided by
clock_gettime for powerpc.
Signed-off-by: Abbas Raza<[email protected]>
---
include/ust/clock.h | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/ust/clock.h b/include/ust/clock.h
index 5e8f755..13e49ab 100644
--- a/include/ust/clock.h
+++ b/include/ust/clock.h
@@ -41,7 +41,7 @@
precision and monotonicity.
*/
-/* Only available for x86 arch */
+/* Only available for x86/powerpc arch */
#define CLOCK_TRACE_FREQ 14
#define CLOCK_TRACE 15
union lttng_timespec {
@@ -76,7 +76,7 @@ static __inline__ uint64_t trace_clock_read64(void)
return retval;
}
-#if __i386__ || __x86_64__
+#if __i386__ || __x86_64__ || __powerpc__
static __inline__ uint64_t trace_clock_frequency(void)
{
struct timespec ts;
@@ -88,12 +88,12 @@ static __inline__ uint64_t trace_clock_frequency(void)
}
return 1000000000LL;
}
-#else /* #if __i386__ || __x86_64__ */
+#else /* #if __i386__ || __x86_64__ || __powerpc__ */
static __inline__ uint64_t trace_clock_frequency(void)
{
return 1000000000LL;
}
-#endif /* #else #if __i386__ || __x86_64__ */
+#endif /* #else #if __i386__ || __x86_64__ || __powerpc__ */
static __inline__ uint32_t trace_clock_freq_scale(void)
{
--
1.7.0.4
From ac11b1d5235216be99d25f95da30c8b1e2dbb8ee Mon Sep 17 00:00:00 2001
From: Abbas Raza<[email protected]>
Date: Thu, 4 Aug 2011 16:05:49 +0500
Subject: [PATCH] TRACE_CLOCK and TRACE_CLOCK_FREQ in clock_gettime for powerpc
These new options to clock_gettime allows the user to retreive the TB frequency
and the current TB from userspace.
Signed-off-by: Abbas Raza<[email protected]>
---
arch/powerpc/include/asm/trace-clock.h | 8 +++
arch/powerpc/kernel/Makefile | 2 +-
arch/powerpc/kernel/asm-offsets.c | 2 +
arch/powerpc/kernel/trace-clock.c | 56 ++++++++++++++++++++++++
arch/powerpc/kernel/vdso32/gettimeofday.S | 67 ++++++++++++++++++++++++++---
5 files changed, 127 insertions(+), 8 deletions(-)
create mode 100644 arch/powerpc/kernel/trace-clock.c
diff --git a/arch/powerpc/include/asm/trace-clock.h
b/arch/powerpc/include/asm/trace-clock.h
index 05facc3..9ed1108 100644
--- a/arch/powerpc/include/asm/trace-clock.h
+++ b/arch/powerpc/include/asm/trace-clock.h
@@ -13,6 +13,14 @@
#include<linux/time.h>
#include<asm/time.h>
+#define TRACE_CLOCK_MIN_PROBE_DURATION 200
+#define TRACE_CLOCK_RES TRACE_CLOCK_MIN_PROBE_DURATION
+
+union lttng_timespec {
+ struct timespec ts;
+ u64 lttng_ts;
+};
+
static inline u32 trace_clock_read32(void)
{
return get_tbl();
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 3bb2a3e..788a96d 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -120,7 +120,7 @@ obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o
ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
obj-y += iomap.o
endif
-
+obj-$(CONFIG_HAVE_TRACE_CLOCK) += trace-clock.o
obj-$(CONFIG_PPC64) += $(obj64-y)
obj-$(CONFIG_PPC32) += $(obj32-y)
diff --git a/arch/powerpc/kernel/asm-offsets.c
b/arch/powerpc/kernel/asm-offsets.c
index 23e6a93..efb7ead 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -370,6 +370,8 @@ int main(void)
/* Other bits used by the vdso */
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+ DEFINE(CLOCK_TRACE, CLOCK_TRACE);
+ DEFINE(CLOCK_TRACE_FREQ, CLOCK_TRACE_FREQ);
DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
diff --git a/arch/powerpc/kernel/trace-clock.c
b/arch/powerpc/kernel/trace-clock.c
new file mode 100644
index 0000000..5592416
--- /dev/null
+++ b/arch/powerpc/kernel/trace-clock.c
@@ -0,0 +1,56 @@
+/*
+ * arch/powerpc/kernel/trace-clock.c
+ *
+ * Trace clock for powerpc.
+ *
+ * Abbas Raza<[email protected]>, July 2011
+ */
+
+#include<linux/module.h>
+#include<linux/trace-clock.h>
+#include<linux/timer.h>
+#include<linux/posix-timers.h>
+
+static int posix_get_trace(clockid_t which_clock, struct timespec *tp)
+{
+ union lttng_timespec *lts = (union lttng_timespec *) tp;
+
+ lts->lttng_ts = trace_clock_read64();
+ return 0;
+}
+
+static int posix_get_trace_freq(clockid_t which_clock, struct timespec *tp)
+{
+ union lttng_timespec *lts = (union lttng_timespec *) tp;
+
+ lts->lttng_ts = trace_clock_frequency();
+ return 0;
+}
+
+static int posix_get_trace_res(const clockid_t which_clock, struct timespec
*tp)
+{
+ union lttng_timespec *lts = (union lttng_timespec *) tp;
+
+ lts->lttng_ts = TRACE_CLOCK_RES;
+ return 0;
+}
+
+static __init int init_trace_clock(void)
+{
+
+ struct k_clock clock_trace = {
+ .clock_getres = posix_get_trace_res,
+ .clock_get = posix_get_trace,
+ };
+ struct k_clock clock_trace_freq = {
+ .clock_getres = posix_get_trace_res,
+ .clock_get = posix_get_trace_freq,
+ };
+
+ register_posix_clock(CLOCK_TRACE,&clock_trace);
+ register_posix_clock(CLOCK_TRACE_FREQ,&clock_trace_freq);
+
+ return 0;
+}
+
+early_initcall(init_trace_clock);
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S
b/arch/powerpc/kernel/vdso32/gettimeofday.S
index 4ee09ee..dce1344 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -75,7 +75,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
cmpli cr0,r3,CLOCK_REALTIME
cmpli cr1,r3,CLOCK_MONOTONIC
cror cr0*4+eq,cr0*4+eq,cr1*4+eq
- bne cr0,99f
+ bne cr0,80f
mflr r12 /* r12 saves lr */
.cfi_register lr,r12
@@ -85,7 +85,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
lis r7,NSEC_PER_SEC@h /* want nanoseconds */
ori r7,r7,NSEC_PER_SEC@l
50: bl __do_get_tspec@local /* get sec/nsec from tb& kernel */
- bne cr1,80f /* not monotonic -> all done */
+ bne cr1,99f /* not monotonic -> all done */
/*
* CLOCK_MONOTONIC
@@ -122,25 +122,53 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
blt 1f
subf r4,r7,r4
addi r3,r3,1
-1: bge cr1,80f
+1: bge cr1,99f
addi r3,r3,-1
add r4,r4,r7
+ b 99f
+
+80:
+ cmpli cr0,r3,CLOCK_TRACE
+ bne cr0,85f
+
+ mflr r12 /* r12 saves lr */
+ .cfi_register lr,r12
+ mr r11,r4 /* r11 saves tp */
+ bl __get_datapage@local /* get data page */
+ mr r9,r3 /* datapage ptr in r9 */
+
+ bl __do_get_tb@local /* get sec/nsec from tb& kernel */
+ b 99f
+
+85:
+ cmpli cr0,r3,CLOCK_TRACE_FREQ
+ bne cr0,100f
-80: stw r3,TSPC32_TV_SEC(r11)
+ mflr r5
+ .cfi_register lr,r5
+
+ mr r11,r4
+ bl __kernel_get_tbfreq@local
+ mr r12,r5
+
+99:
+ stw r3,TSPC32_TV_SEC(r11)
stw r4,TSPC32_TV_NSEC(r11)
mtlr r12
crclr cr0*4+so
li r3,0
+
blr
/*
* syscall fallback
*/
-99:
- li r0,__NR_clock_gettime
+100:
+
+ li r0,__NR_clock_gettime
sc
- blr
+ blr
.cfi_endproc
V_FUNCTION_END(__kernel_clock_gettime)
@@ -264,3 +292,28 @@ __do_get_tspec:
blr
.cfi_endproc
+
+__do_get_tb:
+ .cfi_startproc
+ /* Check for update count& load values. We use the low
+ * order 32 bits of the update count
+ */
+1: lwz r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
+ andi. r0,r8,1 /* pending update ? loop */
+ bne- 1b
+ xor r0,r8,r8 /* create dependency */
+ add r9,r9,r0
+
+ /* Load orig stamp (offset to TB) */
+ lwz r5,CFG_TB_ORIG_STAMP(r9)
+ lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
+
+ /* Get a stable TB value */
+2: mftbu r3
+ mftbl r4
+ mftbu r0
+ cmpl cr0,r3,r0
+ bne- 2b
+
+ blr
+ .cfi_endproc
--
1.7.0.4