[ltt-dev] trace-clock-userspace.patch for ARM/PowerPC ?

Mathieu Desnoyers compudj at krystal.dyndns.org
Tue Aug 16 06:55:21 EDT 2011


Just to make sure this email did not get lost, I'm still waiting on the
OK to use this code under LGPLv2.1/GPLv2 dual-license.

Thanks,

Mathieu

* Abbas Raza (abbas_raza at mentor.com) wrote:
> On 07/28/2011 10:26 PM, Mathieu Desnoyers wrote:
>> * Abbas Raza (abbas_raza at mentor.com) wrote:
>>> On 07/26/2011 11:02 PM, Mathieu Desnoyers wrote:
>>>> * Abbas Raza (abbas_raza at mentor.com) wrote:
>>>>> On 07/26/2011 10:17 PM, Mathieu Desnoyers wrote:
>>>>>> * Abbas Raza (abbas_raza at mentor.com) 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 <Abbas_Raza at mentor.com>
> 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 <Abbas_Raza at mentor.com>
> ---
>  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 <Abbas_Raza at mentor.com>
> 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 <Abbas_Raza at mentor.com>
> ---
>  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 <Abbas_Raza at mentor.com>, 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 at h	/* want nanoseconds */
>  	ori	r7,r7,NSEC_PER_SEC at l
>  50:	bl	__do_get_tspec at 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 at local	/* get data page */
> +	mr	r9,r3			/* datapage ptr in r9 */
> +
> +	bl	__do_get_tb at 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 at 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
> 


-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com




More information about the lttng-dev mailing list