Re: [PATCH] LTT for SH4

"Giuseppe Cavallaro" <[email protected]>
Newsgroups gmane.linux.kernel.tracing
Message-ID <[email protected]>
Mathieu,

On 04/07/07, Mathieu Desnoyers <[email protected]> wrote:
>
> Hi Giuseppe,
>
> >
> > Does this timer stop once it reaches the underflow ?
> >
> >
> > Yes it does.
>
> Hrm, here you seems to say that the timer stops, while right after you
> say that it stops... so, what happens ? :)


Sorry, I  was not so clear in my previous email; after an underflow the TMU
counter register (TCNT) is reloaded with the start value (TCOR register) by
the HW  and the counter is not stopped.

In attachment you will find the new patches.

This new ltt.h file should be good also if you are using the latest TMU
infrastructure (included in the timer-tmu.c file). Indeed, I've decided to
"hack" my timer-tmu.c file adding the new functions for the tmu1.
Looking at the new timer-tmu.c (tmu1_clk_init etc...), the TMU channel 1 is
initialized and started during the kernel boot (and no interrupt handler is
installed for this TMU channel).
In my opinion, we can actually re-use this infrastructure without modifying
the configuration.
In the end, I've also reviewed the get_timestamp functions (following your
advice) and all seems to start working.

Let me know and welcome advice.
Ciao
Giuseppe

_______________________________________________
Ltt-dev mailing list
[email protected]
http://listserv.shafik.org/mailman/listinfo/ltt-dev
lttng-0.9.5-sh_ptrace.patch (application/octet-stream, 1.5 KB)
This marks the do_syscall_trace function within the ptrace.c file

Signed-off by Giuseppe Cavallaro <[email protected]>

--- linux-2.6.21/arch/sh/kernel/ptrace.c.orig	2007-07-03 15:49:05.000000000 +0200
+++ linux-2.6.21/arch/sh/kernel/ptrace.c	2007-07-03 15:50:14.000000000 +0200
@@ -264,10 +264,23 @@ long arch_ptrace(struct task_struct *chi
 	return ret;
 }
 
+#ifdef CONFIG_LTT
+asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
+#else
 asmlinkage void do_syscall_trace(void)
+#endif
 {
 	struct task_struct *tsk = current;
 
+#ifdef CONFIG_LTT
+	if (entryexit) {
+		MARK(kernel_arch_syscall_entry, "%d %ld", regs->regs[3],
+			instruction_pointer(regs));
+	} else {
+		MARK(kernel_arch_syscall_exit, MARK_NOARGS);
+	}
+#endif
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
 	    !test_thread_flag(TIF_SINGLESTEP))
 		return;
--- linux-2.6.21/arch/sh/kernel/entry-common.S.orig	2007-07-03 15:48:10.000000000 +0200
+++ linux-2.6.21/arch/sh/kernel/entry-common.S	2007-07-03 15:48:58.000000000 +0200
@@ -234,6 +234,10 @@ syscall_exit_work:
 #endif
 	sti
 	! XXX setup arguments...
+#ifdef CONFIG_LTT
+	mov     r15, r4
+	mov     #0, r5			! trace entry [0]
+#endif
 	mov.l	4f, r0			! do_syscall_trace
 	jsr	@r0
 	 nop
@@ -242,6 +246,10 @@ syscall_exit_work:
 
 	.align	2
 syscall_trace_entry:
+#ifdef CONFIG_LTT
+	mov     r15, r4		! pass stacked regs as arg
+	mov     #1, r5		! trace entry [1]
+#endif
 	!                     	Yes it is traced.
 	! XXX setup arguments...
 	mov.l	4f, r11		! Call do_syscall_trace which notifies
lttng-sh_timestamp.patch (application/octet-stream, 2 KB)
This patch adds the timestamping mechanism in the ltt.h arch header file.
The new timestamp functions use the TMU channel 1.

This code only works if the TMU channel 1 is initialized during the kernel boot

Signed-off by Giuseppe Cavallaro <[email protected]>

--- linux/include/asm-sh/ltt.h.orig	2007-07-03 15:45:55.000000000 +0200
+++ linux/include/asm-sh/ltt.h	2007-07-05 13:50:36.343575000 +0200
@@ -1,14 +1,44 @@
 /*
- * linux/include/asm-sh/ltt.h
- *
- * Copyright (C) 2002, Karim Yaghmour
- *
- * SuperH definitions for tracing system
+ * SH definitions for tracing system
+ * Author Giuseppe Cavallaro <[email protected]>
  */
 
 #ifndef _ASM_SH_LTT_H
 #define _ASM_SH_LTT_H
 
-#include <asm-generic/ltt.h>
+#include <linux/ltt-core.h>
+#include <asm/timer.h>
+#include <asm/clock.h>
 
+#define LTT_ARCH_TYPE LTT_ARCH_TYPE_SH
+#define LTT_ARCH_VARIANT LTT_ARCH_VARIANT_NONE
+
+#define LTT_HAS_TSC
+u64 ltt_heartbeat_read_synthetic_tsc(void);
+
+static inline u32 ltt_get_timestamp32(void)
+{
+	return get_cycles();
+}
+
+static inline u64 ltt_get_timestamp64(void)
+{
+	return (ltt_heartbeat_read_synthetic_tsc());
+}
+
+static inline unsigned int ltt_frequency(void)
+{
+	unsigned long rate;
+	struct clk *tmu1_clk;
+
+	tmu1_clk = clk_get(NULL, "tmu1_clk");
+	rate = (clk_get_rate(tmu1_clk));
+
+	return (unsigned int)(rate);
+}
+
+static inline u32 ltt_freq_scale(void)
+{
+	return 1;
+}
 #endif
--- linux/include/asm-sh/timex.h.orig	2007-07-05 11:46:26.000000000 +0200
+++ linux/include/asm-sh/timex.h	2007-07-05 10:34:55.888930000 +0200
@@ -5,13 +5,20 @@
  */
 #ifndef __ASM_SH_TIMEX_H
 #define __ASM_SH_TIMEX_H
+#ifdef CONFIG_LTT
+#include <asm/cpu/timer.h>
+#include <asm/io.h>
+#endif
 
-#define CLOCK_TICK_RATE		(CONFIG_SH_PCLK_FREQ / 4) /* Underlying HZ */
+#define CLOCK_TICK_RATE		(HZ * 100000UL)
 
 typedef unsigned long long cycles_t;
 
 static __inline__ cycles_t get_cycles (void)
 {
+#ifdef CONFIG_LTT
+	return (0xffffffff - ctrl_inl(TMU1_TCNT));
+#endif
 	return 0;
 }
lttng-0.9.5-probe-kernel_arch_sh.patch (application/octet-stream, 3.7 KB)
This adds the kernel_arch probe functions for SH architecture.
Indeed, it is the same code used for other architectures (i.e. arm).
Moreover, it also enables the LTT_HEARTBEAT support for SUPERH architecture.
That is for overcoming 64 timestamp limit.

Signed-off by Giuseppe Cavallaro <[email protected]>

--- /dev/null	2007-07-03 15:14:15.628235594 +0200
+++ linux/ltt/probes/ltt-probe-kernel_arch_sh.c	2007-06-26 09:06:04.574112000 +0200
@@ -0,0 +1,106 @@
+/*
+ * ltt-probe-kernel_arch_arm.c
+ *
+ * kernel_arch probe
+ *
+ * Part of LTTng
+ *
+ * Licensed under the GPLv2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/crc32.h>
+#include <linux/marker.h>
+#include <linux/ltt-facilities.h>
+#include <linux/ltt-tracer.h>
+
+
+#define FACILITY_NAME "kernel_arch"
+
+static struct ltt_probe_data probe_array[] =
+{
+	{ "kernel_arch_trap_entry", "%ld %ld", GET_CHANNEL_INDEX(cpu) },
+	{ "kernel_arch_trap_exit", MARK_NOARGS, GET_CHANNEL_INDEX(cpu) },
+	{ "kernel_arch_syscall_entry", "%d %ld", GET_CHANNEL_INDEX(cpu) },
+	{ "kernel_arch_syscall_exit", MARK_NOARGS, GET_CHANNEL_INDEX(cpu) },
+	{ "kernel_arch_ipc_call", "%u %d", GET_CHANNEL_INDEX(cpu) },
+	{ "kernel_arch_kthread_create", "%ld %p",
+		GET_CHANNEL_INDEX(processes) },
+};
+
+
+#define NUM_PROBES (sizeof(probe_array) / sizeof(struct ltt_probe_data))
+
+static struct ltt_facility facility = {
+	.name = FACILITY_NAME,
+	.num_events = NUM_PROBES,
+	.checksum = 0,
+	.id = 0xFF,
+	.alignment = 1,	/* 1: true, 0: false */
+};
+
+static int __init arch_probe_init(void)
+{
+	int result;
+	uint8_t eID;
+	int ret;
+
+	/* FIXME : LTTV is unable to compute this CRC (for now) */
+	for (eID = 0; eID < NUM_PROBES; eID++) {
+		facility.checksum =
+			crc32(facility.checksum, probe_array[eID].name,
+				strlen(probe_array[eID].name));
+		facility.checksum =
+			crc32(facility.checksum, probe_array[eID].format,
+				strlen(probe_array[eID].format));
+
+	}
+	ret = ltt_facility_kernel_register(&facility);
+	if (ret < 0) {
+		printk(KERN_WARNING "%s LTT : Error in registering facility %s\n",
+			"SH", facility.name);
+		return ret;
+	}
+	facility.id = (uint8_t)ret;
+
+	printk("%s LTT : Facility %s registered with id %hu\n", "SH", facility.name,
+		facility.id);
+
+	for (eID = 0; eID < NUM_PROBES; eID++) {
+		probe_array[eID].fID = facility.id;
+		probe_array[eID].eID = eID;
+		probe_array[eID].align = facility.alignment;
+		probe_array[eID].callbacks[0] = ltt_serialize_data;
+		result = marker_set_probe(probe_array[eID].name,
+				probe_array[eID].format,
+				ltt_trace, &probe_array[eID]);
+		if (!result)
+			printk(KERN_INFO "%s LTT unable to register probe %s\n",
+				"SH", probe_array[eID].name);
+	}
+	return 0;
+}
+
+static void __exit arch_probe_exit(void)
+{
+	uint8_t eID;
+	int err;
+
+	for (eID = 0; eID < NUM_PROBES; eID++) {
+		marker_remove_probe(probe_array[eID].name);
+	}
+	synchronize_sched();	/* Wait for probes to finish */
+	err = ltt_facility_unregister(facility.id);
+	if (err)
+		printk(KERN_WARNING
+			"%s LTT : Error in unregistering facility %s\n",
+			"SH", facility.name);
+}
+
+module_init(arch_probe_init);
+module_exit(arch_probe_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION(FACILITY_NAME " probe");
--- linux/ltt/Kconfig.orig	2007-07-05 11:39:57.000000000 +0200
+++ linux/ltt/Kconfig	2007-07-05 11:41:00.000000000 +0200
@@ -2,8 +2,8 @@ config LTT
 	bool "Linux Trace Toolkit Instrumentation Support"
 	depends on EXPERIMENTAL
 	depends on MARKERS
-	select LTT_HEARTBEAT if MIPS
-	select LTT_SYNTHETIC_TSC if MIPS
+	select LTT_HEARTBEAT if MIPS || SUPERH
+	select LTT_SYNTHETIC_TSC if MIPS || SUPERH
 	default n
 	help
 	  It is possible for the kernel to log important events to a trace
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.