* [PATCH] Tracing events with GPIOs @ 2013-12-17 0:22 Jean-Jacques Hiblot 2013-12-17 1:16 ` Masami Hiramatsu 2013-12-19 6:52 ` Alexandre Courbot 0 siblings, 2 replies; 15+ messages in thread From: Jean-Jacques Hiblot @ 2013-12-17 0:22 UTC (permalink / raw) To: rostedt, masami.hiramatsu.pt Cc: linux-gpio, linux-kernel, Jean-Jacques Hiblot This patch implements a new tracing mechanism based on kprobes and using GPIO. Debugging with GPIO is very common in the embedded world. At least for those of us fortunate enough to have an oscilloscope or a logic analyzer on their bench... This is especially true if the issue results of a hardware/sofware interaction. Typical use cases are : * mixed software/hardware debugging. For example when the software detects a situation of interest (typically an error) it toggles a GPIO to trigger the oscilloscope acquisition. * direct latency/duration measurements. examples: To trig the oscilloscope whenever a mmc command error: echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com> --- kernel/trace/Kconfig | 12 ++++ kernel/trace/trace_kprobe.c | 167 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 177 insertions(+), 2 deletions(-) diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 015f85a..4228768 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -420,6 +420,18 @@ config KPROBE_EVENT This option is also required by perf-probe subcommand of perf tools. If you want to use perf tools, this option is strongly recommended. +config KPROBE_EVENT_GPIO + depends on KPROBE_EVENT + depends on GPIOLIB + bool "Enable kprobes-based tracing of events via GPIO" + default n + help + This allows the user to use GPIOs as a tracing tool.The primary + purpose of this option is to allow the user to trigger an + oscilloscope on software events. + The GPIO can be set, cleared, toggled, or pulsed when the event + is hit. + config UPROBE_EVENT bool "Enable uprobes-based dynamic events" depends on ARCH_SUPPORTS_UPROBES diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index dae9541..5d297f5 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/uaccess.h> +#include <linux/gpio.h> #include "trace_probe.h" @@ -27,6 +28,33 @@ /** * Kprobe event core functions */ +#ifdef CONFIG_KPROBE_EVENT_GPIO +#define TP_GPIO_UNDEFINED 0 +#define TP_GPIO_CMD_SET 1 +#define TP_GPIO_CMD_CLEAR 2 +#define TP_GPIO_CMD_TOGGLE 3 +#define TP_GPIO_CMD_PULSE 4 +#define TP_GPIO_CMD_PULSE_HIGH 5 +#define TP_GPIO_CMD_PULSE_LOW 6 + +static const struct { + const char *name; + int action; +} gpio_actions[] = { + {"gpioset", TP_GPIO_CMD_SET}, + {"gpioclear", TP_GPIO_CMD_CLEAR}, + {"gpiotoggle", TP_GPIO_CMD_TOGGLE}, + {"gpiopulse", TP_GPIO_CMD_PULSE}, + {"gpiopulsehigh", TP_GPIO_CMD_PULSE_HIGH}, + {"gpiopulselow", TP_GPIO_CMD_PULSE_LOW}, +}; + +struct gpio_trace { + int gpio; + int action; +}; +#endif + struct trace_probe { struct list_head list; struct kretprobe rp; /* Use rp.kp for kprobe use */ @@ -38,6 +66,9 @@ struct trace_probe { struct list_head files; ssize_t size; /* trace entry size */ unsigned int nr_args; +#ifdef CONFIG_KPROBE_EVENT_GPIO + struct gpio_trace gpio_trace; +#endif struct probe_arg args[]; }; @@ -164,10 +195,24 @@ error: return ERR_PTR(ret); } +static struct trace_probe *find_gpio_probe(int gpio) +{ + struct trace_probe *tp; + + list_for_each_entry(tp, &probe_list, list) + if ((tp->gpio_trace.action) && (tp->gpio_trace.gpio == gpio)) + return tp; + return NULL; +} + static void free_trace_probe(struct trace_probe *tp) { int i; +#ifdef CONFIG_KPROBE_EVENT_GPIO + if (tp->gpio_trace.action && !find_gpio_probe(tp->gpio_trace.gpio)) + gpio_free(tp->gpio_trace.gpio); +#endif for (i = 0; i < tp->nr_args; i++) traceprobe_free_probe_arg(&tp->args[i]); @@ -435,8 +480,14 @@ static int create_trace_probe(int argc, char **argv) { /* * Argument syntax: - * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS] - * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS] + * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR + * [GPIOACTION@GPIONUM] [FETCHARGS] + * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] + * [GPIOACTION@GPIONUM] [FETCHARGS] + * Gpio tracing: + * gpio action can be : gpioset, gpioclear, gpiotoggle, gpiopulse, + * gpiopulsehigh and gpiopulselow + * gpionum is the id of the gpio * Fetch args: * $retval : fetch return value * $stack : fetch stack address @@ -459,6 +510,9 @@ static int create_trace_probe(int argc, char **argv) unsigned long offset = 0; void *addr = NULL; char buf[MAX_EVENT_NAME_LEN]; +#ifdef CONFIG_KPROBE_EVENT_GPIO + int len; +#endif /* argc must be >= 1 */ if (argv[0][0] == 'p') @@ -541,6 +595,7 @@ static int create_trace_probe(int argc, char **argv) return -EINVAL; } } + argc -= 2; argv += 2; /* setup a probe */ @@ -562,6 +617,66 @@ static int create_trace_probe(int argc, char **argv) return PTR_ERR(tp); } +#ifdef CONFIG_KPROBE_EVENT_GPIO + /* parse the optionnal gpio action argument */ + for (i = 0; argc && (i < ARRAY_SIZE(gpio_actions)); i++) { + len = strlen(gpio_actions[i].name); + if (strncmp(argv[0], gpio_actions[i].name, len) == 0) + break; + } + + if (argc && (i < ARRAY_SIZE(gpio_actions))) { + int gpio; + unsigned long ul; + int gpio_requested = 0; + ret = -EINVAL; + if (argv[0][len] != '@') { + pr_info("Syntax error. wrong gpio syntax\n"); + goto error; + } + + if (kstrtoul(&argv[0][len+1], 0, &ul)) { + pr_info("Failed to parse gpio number.\n"); + goto error; + } + gpio = ul; + + if (!gpio_is_valid(gpio)) { + pr_info("gpio %d is not valid.\n", gpio); + goto error; + } + + if (gpio_cansleep(gpio)) + pr_info("gpio %d can sleep. This may break your" + "kernel!!!!!!\n", gpio); + + if (!find_gpio_probe(gpio)) { + ret = gpio_request(gpio, event); + if (ret) { + pr_info("can't request gpio %d.\n", gpio); + goto error; + } + gpio_requested = 1; + } + + if ((gpio_actions[i].action == TP_GPIO_CMD_CLEAR) || + (gpio_actions[i].action == TP_GPIO_CMD_PULSE_LOW)) + ret = gpio_direction_output(gpio, 1); + else + ret = gpio_direction_output(gpio, 0); + if (ret) { + pr_info("can't make gpio %d an output.\n", gpio); + if (gpio_requested) + gpio_free(gpio); + goto error; + } + + tp->gpio_trace.gpio = gpio; + tp->gpio_trace.action = gpio_actions[i].action; + argc -= 1; argv += 1; + } +#endif + /* parse arguments */ ret = 0; for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { @@ -1145,12 +1260,54 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, } #endif /* CONFIG_PERF_EVENTS */ +#ifdef CONFIG_KPROBE_EVENT_GPIO +static __kprobes void kprobe_gpio_take_action(int gpio, int action) +{ + int val; + switch (action) { + case TP_GPIO_CMD_PULSE_HIGH: + gpio_set_value(gpio, 1); + /* intentionnaly don't break here */ + case TP_GPIO_CMD_CLEAR: + gpio_set_value(gpio, 0); + break; + + case TP_GPIO_CMD_PULSE_LOW: + gpio_set_value(gpio, 0); + /* intentionnaly don't break here */ + case TP_GPIO_CMD_SET: + gpio_set_value(gpio, 1); + break; + + case TP_GPIO_CMD_TOGGLE: + val = gpio_get_value(gpio); + gpio_set_value(gpio, val ? 0 : 1); + break; + + case TP_GPIO_CMD_PULSE: + val = gpio_get_value(gpio); + gpio_set_value(gpio, val ? 0 : 1); + gpio_set_value(gpio, val); + break; + } +} + /* * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. * * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe * lockless, but we can't race with this __init function. */ +/* Kprobe gpio handler */ +static inline __kprobes void kprobe_gpio_func(struct trace_probe *tp, + struct pt_regs *regs) +{ + if (tp->gpio_trace.action) + kprobe_gpio_take_action(tp->gpio_trace.gpio, + tp->gpio_trace.action); +} +#endif /* CONFIG_KPROBE_EVENT_GPIO */ + static __kprobes int kprobe_register(struct ftrace_event_call *event, enum trace_reg type, void *data) @@ -1186,6 +1343,9 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) tp->nhit++; +#ifdef CONFIG_KPROBE_EVENT_GPIO + kprobe_gpio_func(tp, regs); +#endif if (tp->flags & TP_FLAG_TRACE) kprobe_trace_func(tp, regs); #ifdef CONFIG_PERF_EVENTS @@ -1202,6 +1362,9 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) tp->nhit++; +#ifdef CONFIG_KPROBE_EVENT_GPIO + kprobe_gpio_func(tp, regs); +#endif if (tp->flags & TP_FLAG_TRACE) kretprobe_trace_func(tp, ri, regs); #ifdef CONFIG_PERF_EVENTS -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-17 0:22 [PATCH] Tracing events with GPIOs Jean-Jacques Hiblot @ 2013-12-17 1:16 ` Masami Hiramatsu 2013-12-17 17:22 ` Jean-Jacques Hiblot 2013-12-19 6:52 ` Alexandre Courbot 1 sibling, 1 reply; 15+ messages in thread From: Masami Hiramatsu @ 2013-12-17 1:16 UTC (permalink / raw) To: Jean-Jacques Hiblot, tom.zanussi; +Cc: rostedt, linux-gpio, linux-kernel (2013/12/17 9:22), Jean-Jacques Hiblot wrote: > This patch implements a new tracing mechanism based on kprobes and using GPIO. > Debugging with GPIO is very common in the embedded world. At least for those of us > fortunate enough to have an oscilloscope or a logic analyzer on their bench... > This is especially true if the issue results of a hardware/sofware interaction. > > Typical use cases are : > * mixed software/hardware debugging. For example when the software detects a > situation of interest (typically an error) it toggles a GPIO to trigger the > oscilloscope acquisition. > * direct latency/duration measurements. Ah, it's interesting to me :) And I think this feature should be built on the event triggers which Tom is working on, instead of kprobes directly, because it allows you to take gpio actions on normal tracepoints, and uprobes too :) Thank you! > > examples: > To trig the oscilloscope whenever a mmc command error: > echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events > echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable > > Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com> > --- > kernel/trace/Kconfig | 12 ++++ > kernel/trace/trace_kprobe.c | 167 +++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 177 insertions(+), 2 deletions(-) > > diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig > index 015f85a..4228768 100644 > --- a/kernel/trace/Kconfig > +++ b/kernel/trace/Kconfig > @@ -420,6 +420,18 @@ config KPROBE_EVENT > This option is also required by perf-probe subcommand of perf tools. > If you want to use perf tools, this option is strongly recommended. > > +config KPROBE_EVENT_GPIO > + depends on KPROBE_EVENT > + depends on GPIOLIB > + bool "Enable kprobes-based tracing of events via GPIO" > + default n > + help > + This allows the user to use GPIOs as a tracing tool.The primary > + purpose of this option is to allow the user to trigger an > + oscilloscope on software events. > + The GPIO can be set, cleared, toggled, or pulsed when the event > + is hit. > + > config UPROBE_EVENT > bool "Enable uprobes-based dynamic events" > depends on ARCH_SUPPORTS_UPROBES > diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c > index dae9541..5d297f5 100644 > --- a/kernel/trace/trace_kprobe.c > +++ b/kernel/trace/trace_kprobe.c > @@ -19,6 +19,7 @@ > > #include <linux/module.h> > #include <linux/uaccess.h> > +#include <linux/gpio.h> > > #include "trace_probe.h" > > @@ -27,6 +28,33 @@ > /** > * Kprobe event core functions > */ > +#ifdef CONFIG_KPROBE_EVENT_GPIO > +#define TP_GPIO_UNDEFINED 0 > +#define TP_GPIO_CMD_SET 1 > +#define TP_GPIO_CMD_CLEAR 2 > +#define TP_GPIO_CMD_TOGGLE 3 > +#define TP_GPIO_CMD_PULSE 4 > +#define TP_GPIO_CMD_PULSE_HIGH 5 > +#define TP_GPIO_CMD_PULSE_LOW 6 > + > +static const struct { > + const char *name; > + int action; > +} gpio_actions[] = { > + {"gpioset", TP_GPIO_CMD_SET}, > + {"gpioclear", TP_GPIO_CMD_CLEAR}, > + {"gpiotoggle", TP_GPIO_CMD_TOGGLE}, > + {"gpiopulse", TP_GPIO_CMD_PULSE}, > + {"gpiopulsehigh", TP_GPIO_CMD_PULSE_HIGH}, > + {"gpiopulselow", TP_GPIO_CMD_PULSE_LOW}, > +}; > + > +struct gpio_trace { > + int gpio; > + int action; > +}; > +#endif > + > struct trace_probe { > struct list_head list; > struct kretprobe rp; /* Use rp.kp for kprobe use */ > @@ -38,6 +66,9 @@ struct trace_probe { > struct list_head files; > ssize_t size; /* trace entry size */ > unsigned int nr_args; > +#ifdef CONFIG_KPROBE_EVENT_GPIO > + struct gpio_trace gpio_trace; > +#endif > struct probe_arg args[]; > }; > > @@ -164,10 +195,24 @@ error: > return ERR_PTR(ret); > } > > +static struct trace_probe *find_gpio_probe(int gpio) > +{ > + struct trace_probe *tp; > + > + list_for_each_entry(tp, &probe_list, list) > + if ((tp->gpio_trace.action) && (tp->gpio_trace.gpio == gpio)) > + return tp; > + return NULL; > +} > + > static void free_trace_probe(struct trace_probe *tp) > { > int i; > > +#ifdef CONFIG_KPROBE_EVENT_GPIO > + if (tp->gpio_trace.action && !find_gpio_probe(tp->gpio_trace.gpio)) > + gpio_free(tp->gpio_trace.gpio); > +#endif > for (i = 0; i < tp->nr_args; i++) > traceprobe_free_probe_arg(&tp->args[i]); > > @@ -435,8 +480,14 @@ static int create_trace_probe(int argc, char **argv) > { > /* > * Argument syntax: > - * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS] > - * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS] > + * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR > + * [GPIOACTION@GPIONUM] [FETCHARGS] > + * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] > + * [GPIOACTION@GPIONUM] [FETCHARGS] > + * Gpio tracing: > + * gpio action can be : gpioset, gpioclear, gpiotoggle, gpiopulse, > + * gpiopulsehigh and gpiopulselow > + * gpionum is the id of the gpio > * Fetch args: > * $retval : fetch return value > * $stack : fetch stack address > @@ -459,6 +510,9 @@ static int create_trace_probe(int argc, char **argv) > unsigned long offset = 0; > void *addr = NULL; > char buf[MAX_EVENT_NAME_LEN]; > +#ifdef CONFIG_KPROBE_EVENT_GPIO > + int len; > +#endif > > /* argc must be >= 1 */ > if (argv[0][0] == 'p') > @@ -541,6 +595,7 @@ static int create_trace_probe(int argc, char **argv) > return -EINVAL; > } > } > + > argc -= 2; argv += 2; > > /* setup a probe */ > @@ -562,6 +617,66 @@ static int create_trace_probe(int argc, char **argv) > return PTR_ERR(tp); > } > > +#ifdef CONFIG_KPROBE_EVENT_GPIO > + /* parse the optionnal gpio action argument */ > + for (i = 0; argc && (i < ARRAY_SIZE(gpio_actions)); i++) { > + len = strlen(gpio_actions[i].name); > + if (strncmp(argv[0], gpio_actions[i].name, len) == 0) > + break; > + } > + > + if (argc && (i < ARRAY_SIZE(gpio_actions))) { > + int gpio; > + unsigned long ul; > + int gpio_requested = 0; > + ret = -EINVAL; > + if (argv[0][len] != '@') { > + pr_info("Syntax error. wrong gpio syntax\n"); > + goto error; > + } > + > + if (kstrtoul(&argv[0][len+1], 0, &ul)) { > + pr_info("Failed to parse gpio number.\n"); > + goto error; > + } > + gpio = ul; > + > + if (!gpio_is_valid(gpio)) { > + pr_info("gpio %d is not valid.\n", gpio); > + goto error; > + } > + > + if (gpio_cansleep(gpio)) > + pr_info("gpio %d can sleep. This may break your" > + "kernel!!!!!!\n", gpio); > + > + if (!find_gpio_probe(gpio)) { > + ret = gpio_request(gpio, event); > + if (ret) { > + pr_info("can't request gpio %d.\n", gpio); > + goto error; > + } > + gpio_requested = 1; > + } > + > + if ((gpio_actions[i].action == TP_GPIO_CMD_CLEAR) || > + (gpio_actions[i].action == TP_GPIO_CMD_PULSE_LOW)) > + ret = gpio_direction_output(gpio, 1); > + else > + ret = gpio_direction_output(gpio, 0); > + if (ret) { > + pr_info("can't make gpio %d an output.\n", gpio); > + if (gpio_requested) > + gpio_free(gpio); > + goto error; > + } > + > + tp->gpio_trace.gpio = gpio; > + tp->gpio_trace.action = gpio_actions[i].action; > + argc -= 1; argv += 1; > + } > +#endif > + > /* parse arguments */ > ret = 0; > for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { > @@ -1145,12 +1260,54 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, > } > #endif /* CONFIG_PERF_EVENTS */ > > +#ifdef CONFIG_KPROBE_EVENT_GPIO > +static __kprobes void kprobe_gpio_take_action(int gpio, int action) > +{ > + int val; > + switch (action) { > + case TP_GPIO_CMD_PULSE_HIGH: > + gpio_set_value(gpio, 1); > + /* intentionnaly don't break here */ > + case TP_GPIO_CMD_CLEAR: > + gpio_set_value(gpio, 0); > + break; > + > + case TP_GPIO_CMD_PULSE_LOW: > + gpio_set_value(gpio, 0); > + /* intentionnaly don't break here */ > + case TP_GPIO_CMD_SET: > + gpio_set_value(gpio, 1); > + break; > + > + case TP_GPIO_CMD_TOGGLE: > + val = gpio_get_value(gpio); > + gpio_set_value(gpio, val ? 0 : 1); > + break; > + > + case TP_GPIO_CMD_PULSE: > + val = gpio_get_value(gpio); > + gpio_set_value(gpio, val ? 0 : 1); > + gpio_set_value(gpio, val); > + break; > + } > +} > + > /* > * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. > * > * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe > * lockless, but we can't race with this __init function. > */ > +/* Kprobe gpio handler */ > +static inline __kprobes void kprobe_gpio_func(struct trace_probe *tp, > + struct pt_regs *regs) > +{ > + if (tp->gpio_trace.action) > + kprobe_gpio_take_action(tp->gpio_trace.gpio, > + tp->gpio_trace.action); > +} > +#endif /* CONFIG_KPROBE_EVENT_GPIO */ > + > static __kprobes > int kprobe_register(struct ftrace_event_call *event, > enum trace_reg type, void *data) > @@ -1186,6 +1343,9 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) > > tp->nhit++; > > +#ifdef CONFIG_KPROBE_EVENT_GPIO > + kprobe_gpio_func(tp, regs); > +#endif > if (tp->flags & TP_FLAG_TRACE) > kprobe_trace_func(tp, regs); > #ifdef CONFIG_PERF_EVENTS > @@ -1202,6 +1362,9 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) > > tp->nhit++; > > +#ifdef CONFIG_KPROBE_EVENT_GPIO > + kprobe_gpio_func(tp, regs); > +#endif > if (tp->flags & TP_FLAG_TRACE) > kretprobe_trace_func(tp, ri, regs); > #ifdef CONFIG_PERF_EVENTS > -- Masami HIRAMATSU IT Management Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: masami.hiramatsu.pt@hitachi.com ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-17 1:16 ` Masami Hiramatsu @ 2013-12-17 17:22 ` Jean-Jacques Hiblot 2013-12-17 18:29 ` Tom Zanussi 2013-12-31 10:16 ` Jean-Jacques Hiblot 0 siblings, 2 replies; 15+ messages in thread From: Jean-Jacques Hiblot @ 2013-12-17 17:22 UTC (permalink / raw) To: Masami Hiramatsu, tom.zanussi Cc: Jean-Jacques Hiblot, rostedt, linux-gpio, linux-kernel 2013/12/17 Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>: > (2013/12/17 9:22), Jean-Jacques Hiblot wrote: >> This patch implements a new tracing mechanism based on kprobes and using GPIO. >> Debugging with GPIO is very common in the embedded world. At least for those of us >> fortunate enough to have an oscilloscope or a logic analyzer on their bench... >> This is especially true if the issue results of a hardware/sofware interaction. >> >> Typical use cases are : >> * mixed software/hardware debugging. For example when the software detects a >> situation of interest (typically an error) it toggles a GPIO to trigger the >> oscilloscope acquisition. >> * direct latency/duration measurements. > > Ah, it's interesting to me :) > > And I think this feature should be built on the event triggers which > Tom is working on, instead of kprobes directly, because it allows > you to take gpio actions on normal tracepoints, and uprobes too :) > I'll make a version that uses this framework then. When it's ready I'll make some measurements to check the overhead of both solutions. Tom, is git://git.yoctoproject.org/linux-yocto-contrib tzanussi/event-triggers-v11 the right starting point ? Thanks, Jean-Jacques > Thank you! > >> >> examples: >> To trig the oscilloscope whenever a mmc command error: >> echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events >> echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable >> >> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com> >> --- >> kernel/trace/Kconfig | 12 ++++ >> kernel/trace/trace_kprobe.c | 167 +++++++++++++++++++++++++++++++++++++++++++- >> 2 files changed, 177 insertions(+), 2 deletions(-) >> >> diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig >> index 015f85a..4228768 100644 >> --- a/kernel/trace/Kconfig >> +++ b/kernel/trace/Kconfig >> @@ -420,6 +420,18 @@ config KPROBE_EVENT >> This option is also required by perf-probe subcommand of perf tools. >> If you want to use perf tools, this option is strongly recommended. >> >> +config KPROBE_EVENT_GPIO >> + depends on KPROBE_EVENT >> + depends on GPIOLIB >> + bool "Enable kprobes-based tracing of events via GPIO" >> + default n >> + help >> + This allows the user to use GPIOs as a tracing tool.The primary >> + purpose of this option is to allow the user to trigger an >> + oscilloscope on software events. >> + The GPIO can be set, cleared, toggled, or pulsed when the event >> + is hit. >> + >> config UPROBE_EVENT >> bool "Enable uprobes-based dynamic events" >> depends on ARCH_SUPPORTS_UPROBES >> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c >> index dae9541..5d297f5 100644 >> --- a/kernel/trace/trace_kprobe.c >> +++ b/kernel/trace/trace_kprobe.c >> @@ -19,6 +19,7 @@ >> >> #include <linux/module.h> >> #include <linux/uaccess.h> >> +#include <linux/gpio.h> >> >> #include "trace_probe.h" >> >> @@ -27,6 +28,33 @@ >> /** >> * Kprobe event core functions >> */ >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> +#define TP_GPIO_UNDEFINED 0 >> +#define TP_GPIO_CMD_SET 1 >> +#define TP_GPIO_CMD_CLEAR 2 >> +#define TP_GPIO_CMD_TOGGLE 3 >> +#define TP_GPIO_CMD_PULSE 4 >> +#define TP_GPIO_CMD_PULSE_HIGH 5 >> +#define TP_GPIO_CMD_PULSE_LOW 6 >> + >> +static const struct { >> + const char *name; >> + int action; >> +} gpio_actions[] = { >> + {"gpioset", TP_GPIO_CMD_SET}, >> + {"gpioclear", TP_GPIO_CMD_CLEAR}, >> + {"gpiotoggle", TP_GPIO_CMD_TOGGLE}, >> + {"gpiopulse", TP_GPIO_CMD_PULSE}, >> + {"gpiopulsehigh", TP_GPIO_CMD_PULSE_HIGH}, >> + {"gpiopulselow", TP_GPIO_CMD_PULSE_LOW}, >> +}; >> + >> +struct gpio_trace { >> + int gpio; >> + int action; >> +}; >> +#endif >> + >> struct trace_probe { >> struct list_head list; >> struct kretprobe rp; /* Use rp.kp for kprobe use */ >> @@ -38,6 +66,9 @@ struct trace_probe { >> struct list_head files; >> ssize_t size; /* trace entry size */ >> unsigned int nr_args; >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> + struct gpio_trace gpio_trace; >> +#endif >> struct probe_arg args[]; >> }; >> >> @@ -164,10 +195,24 @@ error: >> return ERR_PTR(ret); >> } >> >> +static struct trace_probe *find_gpio_probe(int gpio) >> +{ >> + struct trace_probe *tp; >> + >> + list_for_each_entry(tp, &probe_list, list) >> + if ((tp->gpio_trace.action) && (tp->gpio_trace.gpio == gpio)) >> + return tp; >> + return NULL; >> +} >> + >> static void free_trace_probe(struct trace_probe *tp) >> { >> int i; >> >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> + if (tp->gpio_trace.action && !find_gpio_probe(tp->gpio_trace.gpio)) >> + gpio_free(tp->gpio_trace.gpio); >> +#endif >> for (i = 0; i < tp->nr_args; i++) >> traceprobe_free_probe_arg(&tp->args[i]); >> >> @@ -435,8 +480,14 @@ static int create_trace_probe(int argc, char **argv) >> { >> /* >> * Argument syntax: >> - * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS] >> - * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS] >> + * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR >> + * [GPIOACTION@GPIONUM] [FETCHARGS] >> + * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] >> + * [GPIOACTION@GPIONUM] [FETCHARGS] >> + * Gpio tracing: >> + * gpio action can be : gpioset, gpioclear, gpiotoggle, gpiopulse, >> + * gpiopulsehigh and gpiopulselow >> + * gpionum is the id of the gpio >> * Fetch args: >> * $retval : fetch return value >> * $stack : fetch stack address >> @@ -459,6 +510,9 @@ static int create_trace_probe(int argc, char **argv) >> unsigned long offset = 0; >> void *addr = NULL; >> char buf[MAX_EVENT_NAME_LEN]; >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> + int len; >> +#endif >> >> /* argc must be >= 1 */ >> if (argv[0][0] == 'p') >> @@ -541,6 +595,7 @@ static int create_trace_probe(int argc, char **argv) >> return -EINVAL; >> } >> } >> + >> argc -= 2; argv += 2; >> >> /* setup a probe */ >> @@ -562,6 +617,66 @@ static int create_trace_probe(int argc, char **argv) >> return PTR_ERR(tp); >> } >> >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> + /* parse the optionnal gpio action argument */ >> + for (i = 0; argc && (i < ARRAY_SIZE(gpio_actions)); i++) { >> + len = strlen(gpio_actions[i].name); >> + if (strncmp(argv[0], gpio_actions[i].name, len) == 0) >> + break; >> + } >> + >> + if (argc && (i < ARRAY_SIZE(gpio_actions))) { >> + int gpio; >> + unsigned long ul; >> + int gpio_requested = 0; >> + ret = -EINVAL; >> + if (argv[0][len] != '@') { >> + pr_info("Syntax error. wrong gpio syntax\n"); >> + goto error; >> + } >> + >> + if (kstrtoul(&argv[0][len+1], 0, &ul)) { >> + pr_info("Failed to parse gpio number.\n"); >> + goto error; >> + } >> + gpio = ul; >> + >> + if (!gpio_is_valid(gpio)) { >> + pr_info("gpio %d is not valid.\n", gpio); >> + goto error; >> + } >> + >> + if (gpio_cansleep(gpio)) >> + pr_info("gpio %d can sleep. This may break your" >> + "kernel!!!!!!\n", gpio); >> + >> + if (!find_gpio_probe(gpio)) { >> + ret = gpio_request(gpio, event); >> + if (ret) { >> + pr_info("can't request gpio %d.\n", gpio); >> + goto error; >> + } >> + gpio_requested = 1; >> + } >> + >> + if ((gpio_actions[i].action == TP_GPIO_CMD_CLEAR) || >> + (gpio_actions[i].action == TP_GPIO_CMD_PULSE_LOW)) >> + ret = gpio_direction_output(gpio, 1); >> + else >> + ret = gpio_direction_output(gpio, 0); >> + if (ret) { >> + pr_info("can't make gpio %d an output.\n", gpio); >> + if (gpio_requested) >> + gpio_free(gpio); >> + goto error; >> + } >> + >> + tp->gpio_trace.gpio = gpio; >> + tp->gpio_trace.action = gpio_actions[i].action; >> + argc -= 1; argv += 1; >> + } >> +#endif >> + >> /* parse arguments */ >> ret = 0; >> for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { >> @@ -1145,12 +1260,54 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, >> } >> #endif /* CONFIG_PERF_EVENTS */ >> >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> +static __kprobes void kprobe_gpio_take_action(int gpio, int action) >> +{ >> + int val; >> + switch (action) { >> + case TP_GPIO_CMD_PULSE_HIGH: >> + gpio_set_value(gpio, 1); >> + /* intentionnaly don't break here */ >> + case TP_GPIO_CMD_CLEAR: >> + gpio_set_value(gpio, 0); >> + break; >> + >> + case TP_GPIO_CMD_PULSE_LOW: >> + gpio_set_value(gpio, 0); >> + /* intentionnaly don't break here */ >> + case TP_GPIO_CMD_SET: >> + gpio_set_value(gpio, 1); >> + break; >> + >> + case TP_GPIO_CMD_TOGGLE: >> + val = gpio_get_value(gpio); >> + gpio_set_value(gpio, val ? 0 : 1); >> + break; >> + >> + case TP_GPIO_CMD_PULSE: >> + val = gpio_get_value(gpio); >> + gpio_set_value(gpio, val ? 0 : 1); >> + gpio_set_value(gpio, val); >> + break; >> + } >> +} >> + >> /* >> * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. >> * >> * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe >> * lockless, but we can't race with this __init function. >> */ >> +/* Kprobe gpio handler */ >> +static inline __kprobes void kprobe_gpio_func(struct trace_probe *tp, >> + struct pt_regs *regs) >> +{ >> + if (tp->gpio_trace.action) >> + kprobe_gpio_take_action(tp->gpio_trace.gpio, >> + tp->gpio_trace.action); >> +} >> +#endif /* CONFIG_KPROBE_EVENT_GPIO */ >> + >> static __kprobes >> int kprobe_register(struct ftrace_event_call *event, >> enum trace_reg type, void *data) >> @@ -1186,6 +1343,9 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) >> >> tp->nhit++; >> >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> + kprobe_gpio_func(tp, regs); >> +#endif >> if (tp->flags & TP_FLAG_TRACE) >> kprobe_trace_func(tp, regs); >> #ifdef CONFIG_PERF_EVENTS >> @@ -1202,6 +1362,9 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) >> >> tp->nhit++; >> >> +#ifdef CONFIG_KPROBE_EVENT_GPIO >> + kprobe_gpio_func(tp, regs); >> +#endif >> if (tp->flags & TP_FLAG_TRACE) >> kretprobe_trace_func(tp, ri, regs); >> #ifdef CONFIG_PERF_EVENTS >> > > > -- > Masami HIRAMATSU > IT Management Research Dept. Linux Technology Center > Hitachi, Ltd., Yokohama Research Laboratory > E-mail: masami.hiramatsu.pt@hitachi.com > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-gpio" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-17 17:22 ` Jean-Jacques Hiblot @ 2013-12-17 18:29 ` Tom Zanussi 2013-12-17 19:05 ` Steven Rostedt 2013-12-31 10:16 ` Jean-Jacques Hiblot 1 sibling, 1 reply; 15+ messages in thread From: Tom Zanussi @ 2013-12-17 18:29 UTC (permalink / raw) To: Jean-Jacques Hiblot; +Cc: Masami Hiramatsu, rostedt, linux-gpio, linux-kernel Hi Jean-Jacques, On Tue, 2013-12-17 at 18:22 +0100, Jean-Jacques Hiblot wrote: > 2013/12/17 Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>: > > (2013/12/17 9:22), Jean-Jacques Hiblot wrote: > >> This patch implements a new tracing mechanism based on kprobes and using GPIO. > >> Debugging with GPIO is very common in the embedded world. At least for those of us > >> fortunate enough to have an oscilloscope or a logic analyzer on their bench... > >> This is especially true if the issue results of a hardware/sofware interaction. > >> > >> Typical use cases are : > >> * mixed software/hardware debugging. For example when the software detects a > >> situation of interest (typically an error) it toggles a GPIO to trigger the > >> oscilloscope acquisition. > >> * direct latency/duration measurements. > > > > Ah, it's interesting to me :) > > > > And I think this feature should be built on the event triggers which > > Tom is working on, instead of kprobes directly, because it allows > > you to take gpio actions on normal tracepoints, and uprobes too :) > > > > I'll make a version that uses this framework then. When it's ready > I'll make some measurements to check the overhead of both solutions. > Yeah, this does look like an interesting application for event triggers - looking forward to seeing what you come up with... > Tom, > is git://git.yoctoproject.org/linux-yocto-contrib > tzanussi/event-triggers-v11 the right starting point ? > Yep, that's the last iteration - I haven't changed anything since then. Tom > Thanks, > > Jean-Jacques > > > Thank you! > > > >> > >> examples: > >> To trig the oscilloscope whenever a mmc command error: > >> echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events > >> echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable > >> > >> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com> > >> --- > >> kernel/trace/Kconfig | 12 ++++ > >> kernel/trace/trace_kprobe.c | 167 +++++++++++++++++++++++++++++++++++++++++++- > >> 2 files changed, 177 insertions(+), 2 deletions(-) > >> > >> diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig > >> index 015f85a..4228768 100644 > >> --- a/kernel/trace/Kconfig > >> +++ b/kernel/trace/Kconfig > >> @@ -420,6 +420,18 @@ config KPROBE_EVENT > >> This option is also required by perf-probe subcommand of perf tools. > >> If you want to use perf tools, this option is strongly recommended. > >> > >> +config KPROBE_EVENT_GPIO > >> + depends on KPROBE_EVENT > >> + depends on GPIOLIB > >> + bool "Enable kprobes-based tracing of events via GPIO" > >> + default n > >> + help > >> + This allows the user to use GPIOs as a tracing tool.The primary > >> + purpose of this option is to allow the user to trigger an > >> + oscilloscope on software events. > >> + The GPIO can be set, cleared, toggled, or pulsed when the event > >> + is hit. > >> + > >> config UPROBE_EVENT > >> bool "Enable uprobes-based dynamic events" > >> depends on ARCH_SUPPORTS_UPROBES > >> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c > >> index dae9541..5d297f5 100644 > >> --- a/kernel/trace/trace_kprobe.c > >> +++ b/kernel/trace/trace_kprobe.c > >> @@ -19,6 +19,7 @@ > >> > >> #include <linux/module.h> > >> #include <linux/uaccess.h> > >> +#include <linux/gpio.h> > >> > >> #include "trace_probe.h" > >> > >> @@ -27,6 +28,33 @@ > >> /** > >> * Kprobe event core functions > >> */ > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> +#define TP_GPIO_UNDEFINED 0 > >> +#define TP_GPIO_CMD_SET 1 > >> +#define TP_GPIO_CMD_CLEAR 2 > >> +#define TP_GPIO_CMD_TOGGLE 3 > >> +#define TP_GPIO_CMD_PULSE 4 > >> +#define TP_GPIO_CMD_PULSE_HIGH 5 > >> +#define TP_GPIO_CMD_PULSE_LOW 6 > >> + > >> +static const struct { > >> + const char *name; > >> + int action; > >> +} gpio_actions[] = { > >> + {"gpioset", TP_GPIO_CMD_SET}, > >> + {"gpioclear", TP_GPIO_CMD_CLEAR}, > >> + {"gpiotoggle", TP_GPIO_CMD_TOGGLE}, > >> + {"gpiopulse", TP_GPIO_CMD_PULSE}, > >> + {"gpiopulsehigh", TP_GPIO_CMD_PULSE_HIGH}, > >> + {"gpiopulselow", TP_GPIO_CMD_PULSE_LOW}, > >> +}; > >> + > >> +struct gpio_trace { > >> + int gpio; > >> + int action; > >> +}; > >> +#endif > >> + > >> struct trace_probe { > >> struct list_head list; > >> struct kretprobe rp; /* Use rp.kp for kprobe use */ > >> @@ -38,6 +66,9 @@ struct trace_probe { > >> struct list_head files; > >> ssize_t size; /* trace entry size */ > >> unsigned int nr_args; > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> + struct gpio_trace gpio_trace; > >> +#endif > >> struct probe_arg args[]; > >> }; > >> > >> @@ -164,10 +195,24 @@ error: > >> return ERR_PTR(ret); > >> } > >> > >> +static struct trace_probe *find_gpio_probe(int gpio) > >> +{ > >> + struct trace_probe *tp; > >> + > >> + list_for_each_entry(tp, &probe_list, list) > >> + if ((tp->gpio_trace.action) && (tp->gpio_trace.gpio == gpio)) > >> + return tp; > >> + return NULL; > >> +} > >> + > >> static void free_trace_probe(struct trace_probe *tp) > >> { > >> int i; > >> > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> + if (tp->gpio_trace.action && !find_gpio_probe(tp->gpio_trace.gpio)) > >> + gpio_free(tp->gpio_trace.gpio); > >> +#endif > >> for (i = 0; i < tp->nr_args; i++) > >> traceprobe_free_probe_arg(&tp->args[i]); > >> > >> @@ -435,8 +480,14 @@ static int create_trace_probe(int argc, char **argv) > >> { > >> /* > >> * Argument syntax: > >> - * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS] > >> - * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS] > >> + * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR > >> + * [GPIOACTION@GPIONUM] [FETCHARGS] > >> + * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] > >> + * [GPIOACTION@GPIONUM] [FETCHARGS] > >> + * Gpio tracing: > >> + * gpio action can be : gpioset, gpioclear, gpiotoggle, gpiopulse, > >> + * gpiopulsehigh and gpiopulselow > >> + * gpionum is the id of the gpio > >> * Fetch args: > >> * $retval : fetch return value > >> * $stack : fetch stack address > >> @@ -459,6 +510,9 @@ static int create_trace_probe(int argc, char **argv) > >> unsigned long offset = 0; > >> void *addr = NULL; > >> char buf[MAX_EVENT_NAME_LEN]; > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> + int len; > >> +#endif > >> > >> /* argc must be >= 1 */ > >> if (argv[0][0] == 'p') > >> @@ -541,6 +595,7 @@ static int create_trace_probe(int argc, char **argv) > >> return -EINVAL; > >> } > >> } > >> + > >> argc -= 2; argv += 2; > >> > >> /* setup a probe */ > >> @@ -562,6 +617,66 @@ static int create_trace_probe(int argc, char **argv) > >> return PTR_ERR(tp); > >> } > >> > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> + /* parse the optionnal gpio action argument */ > >> + for (i = 0; argc && (i < ARRAY_SIZE(gpio_actions)); i++) { > >> + len = strlen(gpio_actions[i].name); > >> + if (strncmp(argv[0], gpio_actions[i].name, len) == 0) > >> + break; > >> + } > >> + > >> + if (argc && (i < ARRAY_SIZE(gpio_actions))) { > >> + int gpio; > >> + unsigned long ul; > >> + int gpio_requested = 0; > >> + ret = -EINVAL; > >> + if (argv[0][len] != '@') { > >> + pr_info("Syntax error. wrong gpio syntax\n"); > >> + goto error; > >> + } > >> + > >> + if (kstrtoul(&argv[0][len+1], 0, &ul)) { > >> + pr_info("Failed to parse gpio number.\n"); > >> + goto error; > >> + } > >> + gpio = ul; > >> + > >> + if (!gpio_is_valid(gpio)) { > >> + pr_info("gpio %d is not valid.\n", gpio); > >> + goto error; > >> + } > >> + > >> + if (gpio_cansleep(gpio)) > >> + pr_info("gpio %d can sleep. This may break your" > >> + "kernel!!!!!!\n", gpio); > >> + > >> + if (!find_gpio_probe(gpio)) { > >> + ret = gpio_request(gpio, event); > >> + if (ret) { > >> + pr_info("can't request gpio %d.\n", gpio); > >> + goto error; > >> + } > >> + gpio_requested = 1; > >> + } > >> + > >> + if ((gpio_actions[i].action == TP_GPIO_CMD_CLEAR) || > >> + (gpio_actions[i].action == TP_GPIO_CMD_PULSE_LOW)) > >> + ret = gpio_direction_output(gpio, 1); > >> + else > >> + ret = gpio_direction_output(gpio, 0); > >> + if (ret) { > >> + pr_info("can't make gpio %d an output.\n", gpio); > >> + if (gpio_requested) > >> + gpio_free(gpio); > >> + goto error; > >> + } > >> + > >> + tp->gpio_trace.gpio = gpio; > >> + tp->gpio_trace.action = gpio_actions[i].action; > >> + argc -= 1; argv += 1; > >> + } > >> +#endif > >> + > >> /* parse arguments */ > >> ret = 0; > >> for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { > >> @@ -1145,12 +1260,54 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, > >> } > >> #endif /* CONFIG_PERF_EVENTS */ > >> > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> +static __kprobes void kprobe_gpio_take_action(int gpio, int action) > >> +{ > >> + int val; > >> + switch (action) { > >> + case TP_GPIO_CMD_PULSE_HIGH: > >> + gpio_set_value(gpio, 1); > >> + /* intentionnaly don't break here */ > >> + case TP_GPIO_CMD_CLEAR: > >> + gpio_set_value(gpio, 0); > >> + break; > >> + > >> + case TP_GPIO_CMD_PULSE_LOW: > >> + gpio_set_value(gpio, 0); > >> + /* intentionnaly don't break here */ > >> + case TP_GPIO_CMD_SET: > >> + gpio_set_value(gpio, 1); > >> + break; > >> + > >> + case TP_GPIO_CMD_TOGGLE: > >> + val = gpio_get_value(gpio); > >> + gpio_set_value(gpio, val ? 0 : 1); > >> + break; > >> + > >> + case TP_GPIO_CMD_PULSE: > >> + val = gpio_get_value(gpio); > >> + gpio_set_value(gpio, val ? 0 : 1); > >> + gpio_set_value(gpio, val); > >> + break; > >> + } > >> +} > >> + > >> /* > >> * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. > >> * > >> * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe > >> * lockless, but we can't race with this __init function. > >> */ > >> +/* Kprobe gpio handler */ > >> +static inline __kprobes void kprobe_gpio_func(struct trace_probe *tp, > >> + struct pt_regs *regs) > >> +{ > >> + if (tp->gpio_trace.action) > >> + kprobe_gpio_take_action(tp->gpio_trace.gpio, > >> + tp->gpio_trace.action); > >> +} > >> +#endif /* CONFIG_KPROBE_EVENT_GPIO */ > >> + > >> static __kprobes > >> int kprobe_register(struct ftrace_event_call *event, > >> enum trace_reg type, void *data) > >> @@ -1186,6 +1343,9 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) > >> > >> tp->nhit++; > >> > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> + kprobe_gpio_func(tp, regs); > >> +#endif > >> if (tp->flags & TP_FLAG_TRACE) > >> kprobe_trace_func(tp, regs); > >> #ifdef CONFIG_PERF_EVENTS > >> @@ -1202,6 +1362,9 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) > >> > >> tp->nhit++; > >> > >> +#ifdef CONFIG_KPROBE_EVENT_GPIO > >> + kprobe_gpio_func(tp, regs); > >> +#endif > >> if (tp->flags & TP_FLAG_TRACE) > >> kretprobe_trace_func(tp, ri, regs); > >> #ifdef CONFIG_PERF_EVENTS > >> > > > > > > -- > > Masami HIRAMATSU > > IT Management Research Dept. Linux Technology Center > > Hitachi, Ltd., Yokohama Research Laboratory > > E-mail: masami.hiramatsu.pt@hitachi.com > > > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-gpio" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-17 18:29 ` Tom Zanussi @ 2013-12-17 19:05 ` Steven Rostedt 2013-12-17 20:45 ` Tom Zanussi 0 siblings, 1 reply; 15+ messages in thread From: Steven Rostedt @ 2013-12-17 19:05 UTC (permalink / raw) To: Tom Zanussi Cc: Jean-Jacques Hiblot, Masami Hiramatsu, linux-gpio, linux-kernel On Tue, 17 Dec 2013 12:29:30 -0600 Tom Zanussi <tom.zanussi@linux.intel.com> wrote: > > Tom, > > is git://git.yoctoproject.org/linux-yocto-contrib > > tzanussi/event-triggers-v11 the right starting point ? > > > > Yep, that's the last iteration - I haven't changed anything since then. > Is this the same as the last patch series you sent out? I started testing them again last week, but they failed some of my tests. Unfortunately, I didn't get a chance to look into why. I'm hoping to get that series out to my for-next branch by end of the week, as I'll be taking two weeks off starting next week. Year end crap is piling up, preventing me from getting real work done ;-) -- Steve ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-17 19:05 ` Steven Rostedt @ 2013-12-17 20:45 ` Tom Zanussi 0 siblings, 0 replies; 15+ messages in thread From: Tom Zanussi @ 2013-12-17 20:45 UTC (permalink / raw) To: Steven Rostedt Cc: Jean-Jacques Hiblot, Masami Hiramatsu, linux-gpio, linux-kernel On Tue, 2013-12-17 at 14:05 -0500, Steven Rostedt wrote: > On Tue, 17 Dec 2013 12:29:30 -0600 > Tom Zanussi <tom.zanussi@linux.intel.com> wrote: > > > > Tom, > > > is git://git.yoctoproject.org/linux-yocto-contrib > > > tzanussi/event-triggers-v11 the right starting point ? > > > > > > > Yep, that's the last iteration - I haven't changed anything since then. > > > > Is this the same as the last patch series you sent out? I started > testing them again last week, but they failed some of my tests. Yeah, that's the same patchset. I tested it here and didn't see any problems but I guess your tests must be different/more rigorous - it would be good to know what failed. I could also run your test suite here if that would help. > Unfortunately, I didn't get a chance to look into why. I'm hoping to > get that series out to my for-next branch by end of the week, as I'll > be taking two weeks off starting next week. > > Year end crap is piling up, preventing me from getting real work > done ;-) I know what you mean, same here. ;-) > > -- Steve ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-17 17:22 ` Jean-Jacques Hiblot 2013-12-17 18:29 ` Tom Zanussi @ 2013-12-31 10:16 ` Jean-Jacques Hiblot 1 sibling, 0 replies; 15+ messages in thread From: Jean-Jacques Hiblot @ 2013-12-31 10:16 UTC (permalink / raw) To: Jean-Jacques Hiblot Cc: Masami Hiramatsu, Tom Zanussi, Steven Rostedt, linux-gpio@vger.kernel.org, Linux Kernel Mailing List 2013/12/17 Jean-Jacques Hiblot <jjhiblot@traphandler.com>: > 2013/12/17 Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>: >> (2013/12/17 9:22), Jean-Jacques Hiblot wrote: >>> This patch implements a new tracing mechanism based on kprobes and using GPIO. >>> Debugging with GPIO is very common in the embedded world. At least for those of us >>> fortunate enough to have an oscilloscope or a logic analyzer on their bench... >>> This is especially true if the issue results of a hardware/sofware interaction. >>> >>> Typical use cases are : >>> * mixed software/hardware debugging. For example when the software detects a >>> situation of interest (typically an error) it toggles a GPIO to trigger the >>> oscilloscope acquisition. >>> * direct latency/duration measurements. >> >> Ah, it's interesting to me :) >> >> And I think this feature should be built on the event triggers which >> Tom is working on, instead of kprobes directly, because it allows >> you to take gpio actions on normal tracepoints, and uprobes too :) >> > > I'll make a version that uses this framework then. When it's ready > I'll make some measurements to check the overhead of both solutions. Here are the results. The test is run on an old ARM9 platform (at91sam9261ek) running at 200MHz The test consists in setting the GPIO when entering handle_IRQ() and clearing the GPIO when entering handle_fasteoi_irq(), and measuring the width of the pulse with an oscilloscope. 1) manual method (modification of the code to insert gpio_set_value() at the top of each probed function). This is our baseline min : 2.76 us mean : 3.22 us max : 6.80 us 2) pure kprobe (patch v1) echo "" > /sys/kernel/debug/tracing/kprobe_events echo "p:b handle_IRQ gpioset@13" > /sys/kernel/debug/tracing/kprobe_events echo "p:a handle_fasteoi_irq gpioclear@13" >> /sys/kernel/debug/tracing/kprobe_events echo 1 > /sys/kernel/debug/tracing/events/kprobes/a/enable echo 1 > /sys/kernel/debug/tracing/events/kprobes/b/enable min : 18.2 us mean 19.2 us max : 34.0 us 3) event trigger (patch v2) echo "" > /sys/kernel/debug/tracing/kprobe_events echo "p:b handle_IRQ" > /sys/kernel/debug/tracing/kprobe_events echo "p:a handle_fasteoi_irq" >> /sys/kernel/debug/tracing/kprobe_events echo 'gpio:clear:13' > /sys/kernel/debug/tracing/events/kprobes/a/trigger echo 'gpio:set:13' > /sys/kernel/debug/tracing/events/kprobes/b/trigger min : 7.36 us mean : 8.32 us max : 14.8 us >From those numbers we deduce the cost of an event triggered gpio probe : (8.32 - 3.22)/2 = 2.55 us (max 4 us). > > Tom, > is git://git.yoctoproject.org/linux-yocto-contrib > tzanussi/event-triggers-v11 the right starting point ? > > Thanks, > > Jean-Jacques > >> Thank you! >> >>> >>> examples: >>> To trig the oscilloscope whenever a mmc command error: >>> echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events >>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable >>> >>> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com> >>> --- >>> kernel/trace/Kconfig | 12 ++++ >>> kernel/trace/trace_kprobe.c | 167 +++++++++++++++++++++++++++++++++++++++++++- >>> 2 files changed, 177 insertions(+), 2 deletions(-) >>> >>> diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig >>> index 015f85a..4228768 100644 >>> --- a/kernel/trace/Kconfig >>> +++ b/kernel/trace/Kconfig >>> @@ -420,6 +420,18 @@ config KPROBE_EVENT >>> This option is also required by perf-probe subcommand of perf tools. >>> If you want to use perf tools, this option is strongly recommended. >>> >>> +config KPROBE_EVENT_GPIO >>> + depends on KPROBE_EVENT >>> + depends on GPIOLIB >>> + bool "Enable kprobes-based tracing of events via GPIO" >>> + default n >>> + help >>> + This allows the user to use GPIOs as a tracing tool.The primary >>> + purpose of this option is to allow the user to trigger an >>> + oscilloscope on software events. >>> + The GPIO can be set, cleared, toggled, or pulsed when the event >>> + is hit. >>> + >>> config UPROBE_EVENT >>> bool "Enable uprobes-based dynamic events" >>> depends on ARCH_SUPPORTS_UPROBES >>> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c >>> index dae9541..5d297f5 100644 >>> --- a/kernel/trace/trace_kprobe.c >>> +++ b/kernel/trace/trace_kprobe.c >>> @@ -19,6 +19,7 @@ >>> >>> #include <linux/module.h> >>> #include <linux/uaccess.h> >>> +#include <linux/gpio.h> >>> >>> #include "trace_probe.h" >>> >>> @@ -27,6 +28,33 @@ >>> /** >>> * Kprobe event core functions >>> */ >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> +#define TP_GPIO_UNDEFINED 0 >>> +#define TP_GPIO_CMD_SET 1 >>> +#define TP_GPIO_CMD_CLEAR 2 >>> +#define TP_GPIO_CMD_TOGGLE 3 >>> +#define TP_GPIO_CMD_PULSE 4 >>> +#define TP_GPIO_CMD_PULSE_HIGH 5 >>> +#define TP_GPIO_CMD_PULSE_LOW 6 >>> + >>> +static const struct { >>> + const char *name; >>> + int action; >>> +} gpio_actions[] = { >>> + {"gpioset", TP_GPIO_CMD_SET}, >>> + {"gpioclear", TP_GPIO_CMD_CLEAR}, >>> + {"gpiotoggle", TP_GPIO_CMD_TOGGLE}, >>> + {"gpiopulse", TP_GPIO_CMD_PULSE}, >>> + {"gpiopulsehigh", TP_GPIO_CMD_PULSE_HIGH}, >>> + {"gpiopulselow", TP_GPIO_CMD_PULSE_LOW}, >>> +}; >>> + >>> +struct gpio_trace { >>> + int gpio; >>> + int action; >>> +}; >>> +#endif >>> + >>> struct trace_probe { >>> struct list_head list; >>> struct kretprobe rp; /* Use rp.kp for kprobe use */ >>> @@ -38,6 +66,9 @@ struct trace_probe { >>> struct list_head files; >>> ssize_t size; /* trace entry size */ >>> unsigned int nr_args; >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> + struct gpio_trace gpio_trace; >>> +#endif >>> struct probe_arg args[]; >>> }; >>> >>> @@ -164,10 +195,24 @@ error: >>> return ERR_PTR(ret); >>> } >>> >>> +static struct trace_probe *find_gpio_probe(int gpio) >>> +{ >>> + struct trace_probe *tp; >>> + >>> + list_for_each_entry(tp, &probe_list, list) >>> + if ((tp->gpio_trace.action) && (tp->gpio_trace.gpio == gpio)) >>> + return tp; >>> + return NULL; >>> +} >>> + >>> static void free_trace_probe(struct trace_probe *tp) >>> { >>> int i; >>> >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> + if (tp->gpio_trace.action && !find_gpio_probe(tp->gpio_trace.gpio)) >>> + gpio_free(tp->gpio_trace.gpio); >>> +#endif >>> for (i = 0; i < tp->nr_args; i++) >>> traceprobe_free_probe_arg(&tp->args[i]); >>> >>> @@ -435,8 +480,14 @@ static int create_trace_probe(int argc, char **argv) >>> { >>> /* >>> * Argument syntax: >>> - * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS] >>> - * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS] >>> + * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR >>> + * [GPIOACTION@GPIONUM] [FETCHARGS] >>> + * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] >>> + * [GPIOACTION@GPIONUM] [FETCHARGS] >>> + * Gpio tracing: >>> + * gpio action can be : gpioset, gpioclear, gpiotoggle, gpiopulse, >>> + * gpiopulsehigh and gpiopulselow >>> + * gpionum is the id of the gpio >>> * Fetch args: >>> * $retval : fetch return value >>> * $stack : fetch stack address >>> @@ -459,6 +510,9 @@ static int create_trace_probe(int argc, char **argv) >>> unsigned long offset = 0; >>> void *addr = NULL; >>> char buf[MAX_EVENT_NAME_LEN]; >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> + int len; >>> +#endif >>> >>> /* argc must be >= 1 */ >>> if (argv[0][0] == 'p') >>> @@ -541,6 +595,7 @@ static int create_trace_probe(int argc, char **argv) >>> return -EINVAL; >>> } >>> } >>> + >>> argc -= 2; argv += 2; >>> >>> /* setup a probe */ >>> @@ -562,6 +617,66 @@ static int create_trace_probe(int argc, char **argv) >>> return PTR_ERR(tp); >>> } >>> >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> + /* parse the optionnal gpio action argument */ >>> + for (i = 0; argc && (i < ARRAY_SIZE(gpio_actions)); i++) { >>> + len = strlen(gpio_actions[i].name); >>> + if (strncmp(argv[0], gpio_actions[i].name, len) == 0) >>> + break; >>> + } >>> + >>> + if (argc && (i < ARRAY_SIZE(gpio_actions))) { >>> + int gpio; >>> + unsigned long ul; >>> + int gpio_requested = 0; >>> + ret = -EINVAL; >>> + if (argv[0][len] != '@') { >>> + pr_info("Syntax error. wrong gpio syntax\n"); >>> + goto error; >>> + } >>> + >>> + if (kstrtoul(&argv[0][len+1], 0, &ul)) { >>> + pr_info("Failed to parse gpio number.\n"); >>> + goto error; >>> + } >>> + gpio = ul; >>> + >>> + if (!gpio_is_valid(gpio)) { >>> + pr_info("gpio %d is not valid.\n", gpio); >>> + goto error; >>> + } >>> + >>> + if (gpio_cansleep(gpio)) >>> + pr_info("gpio %d can sleep. This may break your" >>> + "kernel!!!!!!\n", gpio); >>> + >>> + if (!find_gpio_probe(gpio)) { >>> + ret = gpio_request(gpio, event); >>> + if (ret) { >>> + pr_info("can't request gpio %d.\n", gpio); >>> + goto error; >>> + } >>> + gpio_requested = 1; >>> + } >>> + >>> + if ((gpio_actions[i].action == TP_GPIO_CMD_CLEAR) || >>> + (gpio_actions[i].action == TP_GPIO_CMD_PULSE_LOW)) >>> + ret = gpio_direction_output(gpio, 1); >>> + else >>> + ret = gpio_direction_output(gpio, 0); >>> + if (ret) { >>> + pr_info("can't make gpio %d an output.\n", gpio); >>> + if (gpio_requested) >>> + gpio_free(gpio); >>> + goto error; >>> + } >>> + >>> + tp->gpio_trace.gpio = gpio; >>> + tp->gpio_trace.action = gpio_actions[i].action; >>> + argc -= 1; argv += 1; >>> + } >>> +#endif >>> + >>> /* parse arguments */ >>> ret = 0; >>> for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { >>> @@ -1145,12 +1260,54 @@ kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, >>> } >>> #endif /* CONFIG_PERF_EVENTS */ >>> >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> +static __kprobes void kprobe_gpio_take_action(int gpio, int action) >>> +{ >>> + int val; >>> + switch (action) { >>> + case TP_GPIO_CMD_PULSE_HIGH: >>> + gpio_set_value(gpio, 1); >>> + /* intentionnaly don't break here */ >>> + case TP_GPIO_CMD_CLEAR: >>> + gpio_set_value(gpio, 0); >>> + break; >>> + >>> + case TP_GPIO_CMD_PULSE_LOW: >>> + gpio_set_value(gpio, 0); >>> + /* intentionnaly don't break here */ >>> + case TP_GPIO_CMD_SET: >>> + gpio_set_value(gpio, 1); >>> + break; >>> + >>> + case TP_GPIO_CMD_TOGGLE: >>> + val = gpio_get_value(gpio); >>> + gpio_set_value(gpio, val ? 0 : 1); >>> + break; >>> + >>> + case TP_GPIO_CMD_PULSE: >>> + val = gpio_get_value(gpio); >>> + gpio_set_value(gpio, val ? 0 : 1); >>> + gpio_set_value(gpio, val); >>> + break; >>> + } >>> +} >>> + >>> /* >>> * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex. >>> * >>> * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe >>> * lockless, but we can't race with this __init function. >>> */ >>> +/* Kprobe gpio handler */ >>> +static inline __kprobes void kprobe_gpio_func(struct trace_probe *tp, >>> + struct pt_regs *regs) >>> +{ >>> + if (tp->gpio_trace.action) >>> + kprobe_gpio_take_action(tp->gpio_trace.gpio, >>> + tp->gpio_trace.action); >>> +} >>> +#endif /* CONFIG_KPROBE_EVENT_GPIO */ >>> + >>> static __kprobes >>> int kprobe_register(struct ftrace_event_call *event, >>> enum trace_reg type, void *data) >>> @@ -1186,6 +1343,9 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) >>> >>> tp->nhit++; >>> >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> + kprobe_gpio_func(tp, regs); >>> +#endif >>> if (tp->flags & TP_FLAG_TRACE) >>> kprobe_trace_func(tp, regs); >>> #ifdef CONFIG_PERF_EVENTS >>> @@ -1202,6 +1362,9 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) >>> >>> tp->nhit++; >>> >>> +#ifdef CONFIG_KPROBE_EVENT_GPIO >>> + kprobe_gpio_func(tp, regs); >>> +#endif >>> if (tp->flags & TP_FLAG_TRACE) >>> kretprobe_trace_func(tp, ri, regs); >>> #ifdef CONFIG_PERF_EVENTS >>> >> >> >> -- >> Masami HIRAMATSU >> IT Management Research Dept. Linux Technology Center >> Hitachi, Ltd., Yokohama Research Laboratory >> E-mail: masami.hiramatsu.pt@hitachi.com >> >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-gpio" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-17 0:22 [PATCH] Tracing events with GPIOs Jean-Jacques Hiblot 2013-12-17 1:16 ` Masami Hiramatsu @ 2013-12-19 6:52 ` Alexandre Courbot 2013-12-19 11:38 ` Jean-Jacques Hiblot 2014-01-02 12:43 ` Linus Walleij 1 sibling, 2 replies; 15+ messages in thread From: Alexandre Courbot @ 2013-12-19 6:52 UTC (permalink / raw) To: Jean-Jacques Hiblot, Linus Walleij Cc: Steven Rostedt, masami.hiramatsu.pt, linux-gpio@vger.kernel.org, Linux Kernel Mailing List On Tue, Dec 17, 2013 at 9:22 AM, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote: > > This patch implements a new tracing mechanism based on kprobes and using GPIO. > Debugging with GPIO is very common in the embedded world. At least for those of us > fortunate enough to have an oscilloscope or a logic analyzer on their bench... > This is especially true if the issue results of a hardware/sofware interaction. > > Typical use cases are : > * mixed software/hardware debugging. For example when the software detects a > situation of interest (typically an error) it toggles a GPIO to trigger the > oscilloscope acquisition. > * direct latency/duration measurements. > > examples: > To trig the oscilloscope whenever a mmc command error: > echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events > echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable I do like this idea, however I wonder if you could try and make it use the new gpio descriptor API (see Documentation/gpio/) instead of the GPIO integers we are trying to deprecate (well ok, we just *started* claiming they are deprecated). This would probably make things a little bit more complicated on your side, due to the fact the gpiod API is new and probably does not cover all your needs. But it would also make your approach safer and more future proof, on top of helping us refine gpiod for various use cases. The problems I can see so far: - Using gpiod, GPIOs are not specified as integers, but are typically mapped to a given (device, function) pair (device can be NULL) using device tree/platform data/ACPI and obtained by the corresponding device driver through gpiod_get(). You would need to find a different way to specify GPIOs, maybe using the gpio_chip's label and the GPIO hardware number. - Even if you do so, there is currently no way to arbitrarily obtain a GPIO that has not been explicitly mapped to a (device, function), and IIUC you need to specify the tracing GPIO freely from user-space. This hints that we will need to add a function that is sensibly the same as gpio_request_one() to the gpiod API, but I wonder if that does not defeats the purpose somehow. So using gpiod we would have the dual problem of how to represent the GPIO you need from user-space, and how you can safely obtain it. It would be interesting to hear what Linus thinks about it, and if he has better ideas about how we could solve these issues (as he usually has ;) ). (note that it is *not* a hard requirement to use gpiod over the legacy integer API, but considering this is the direction we are taking, it would be nice to consider it and see how we could solve the issues mentioned above) Thanks, Alex. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-19 6:52 ` Alexandre Courbot @ 2013-12-19 11:38 ` Jean-Jacques Hiblot 2013-12-20 7:33 ` Alexandre Courbot 2014-01-02 12:43 ` Linus Walleij 1 sibling, 1 reply; 15+ messages in thread From: Jean-Jacques Hiblot @ 2013-12-19 11:38 UTC (permalink / raw) To: Alexandre Courbot Cc: Jean-Jacques Hiblot, Linus Walleij, Steven Rostedt, Masami Hiramatsu, linux-gpio@vger.kernel.org, Linux Kernel Mailing List 2013/12/19 Alexandre Courbot <gnurou@gmail.com>: > On Tue, Dec 17, 2013 at 9:22 AM, Jean-Jacques Hiblot > <jjhiblot@traphandler.com> wrote: >> >> This patch implements a new tracing mechanism based on kprobes and using GPIO. >> Debugging with GPIO is very common in the embedded world. At least for those of us >> fortunate enough to have an oscilloscope or a logic analyzer on their bench... >> This is especially true if the issue results of a hardware/sofware interaction. >> >> Typical use cases are : >> * mixed software/hardware debugging. For example when the software detects a >> situation of interest (typically an error) it toggles a GPIO to trigger the >> oscilloscope acquisition. >> * direct latency/duration measurements. >> >> examples: >> To trig the oscilloscope whenever a mmc command error: >> echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events >> echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable > > I do like this idea, however I wonder if you could try and make it use > the new gpio descriptor API (see Documentation/gpio/) instead of the > GPIO integers we are trying to deprecate (well ok, we just *started* > claiming they are deprecated). > I'll make the gpio event trigger work with the old API first. Then I'll adapt it to use the gpio descriptor interface. > This would probably make things a little bit more complicated on your > side, due to the fact the gpiod API is new and probably does not cover > all your needs. But it would also make your approach safer and more > future proof, on top of helping us refine gpiod for various use cases. > > The problems I can see so far: > > - Using gpiod, GPIOs are not specified as integers, but are typically > mapped to a given (device, function) pair (device can be NULL) using > device tree/platform data/ACPI and obtained by the corresponding > device driver through gpiod_get(). You would need to find a different > way to specify GPIOs, maybe using the gpio_chip's label and the GPIO > hardware number. > > - Even if you do so, there is currently no way to arbitrarily obtain a > GPIO that has not been explicitly mapped to a (device, function), and > IIUC you need to specify the tracing GPIO freely from user-space. This > hints that we will need to add a function that is sensibly the same as > gpio_request_one() to the gpiod API, but I wonder if that does not > defeats the purpose somehow. This is something I was wondering about for another reason. In many cases the GPIOs that are physically available for probing will be limited to the GPIOs already assigned a function (backlight control for example), others are usually not routed except in eval boards or early prototypes. And consequently those GPIOs will be requested by a driver long before a probe is set. It would be nice not to have to remove the driver to be able to use this GPIO as a probe. Maybe a gpiod_steal() interface and a flag indicating that the GPIO can be safely stolen? > > So using gpiod we would have the dual problem of how to represent the > GPIO you need from user-space, and how you can safely obtain it. It > would be interesting to hear what Linus thinks about it, and if he has > better ideas about how we could solve these issues (as he usually has > ;) ). > > (note that it is *not* a hard requirement to use gpiod over the legacy > integer API, but considering this is the direction we are taking, it > would be nice to consider it and see how we could solve the issues > mentioned above) > > Thanks, > Alex. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-19 11:38 ` Jean-Jacques Hiblot @ 2013-12-20 7:33 ` Alexandre Courbot 2013-12-20 8:40 ` Jean-Jacques Hiblot 0 siblings, 1 reply; 15+ messages in thread From: Alexandre Courbot @ 2013-12-20 7:33 UTC (permalink / raw) To: Jean-Jacques Hiblot Cc: Linus Walleij, Steven Rostedt, Masami Hiramatsu, linux-gpio@vger.kernel.org, Linux Kernel Mailing List On Thu, Dec 19, 2013 at 8:38 PM, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote: > 2013/12/19 Alexandre Courbot <gnurou@gmail.com>: >> The problems I can see so far: >> >> - Using gpiod, GPIOs are not specified as integers, but are typically >> mapped to a given (device, function) pair (device can be NULL) using >> device tree/platform data/ACPI and obtained by the corresponding >> device driver through gpiod_get(). You would need to find a different >> way to specify GPIOs, maybe using the gpio_chip's label and the GPIO >> hardware number. >> >> - Even if you do so, there is currently no way to arbitrarily obtain a >> GPIO that has not been explicitly mapped to a (device, function), and >> IIUC you need to specify the tracing GPIO freely from user-space. This >> hints that we will need to add a function that is sensibly the same as >> gpio_request_one() to the gpiod API, but I wonder if that does not >> defeats the purpose somehow. > > This is something I was wondering about for another reason. In many > cases the GPIOs that are physically available for probing will be > limited to the GPIOs already assigned a function (backlight control > for example), others are usually not routed except in eval boards or > early prototypes. And consequently those GPIOs will be requested by a > driver long before a probe is set. > It would be nice not to have to remove the driver to be able to use > this GPIO as a probe. Maybe a gpiod_steal() interface and a flag > indicating that the GPIO can be safely stolen? Mmm an explicit way to hijack a GPIO does not sound very safe. Do you have concrete cases where you need to do so? I guess most boards you may want to use this patch with would have at least some spare GPIOs with pins somewhere on the board for this kind of purpose. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-20 7:33 ` Alexandre Courbot @ 2013-12-20 8:40 ` Jean-Jacques Hiblot 2014-01-03 10:50 ` Alexandre Courbot 0 siblings, 1 reply; 15+ messages in thread From: Jean-Jacques Hiblot @ 2013-12-20 8:40 UTC (permalink / raw) To: Alexandre Courbot Cc: Jean-Jacques Hiblot, Linus Walleij, Steven Rostedt, Masami Hiramatsu, linux-gpio@vger.kernel.org, Linux Kernel Mailing List 2013/12/20 Alexandre Courbot <gnurou@gmail.com>: > On Thu, Dec 19, 2013 at 8:38 PM, Jean-Jacques Hiblot > <jjhiblot@traphandler.com> wrote: >> 2013/12/19 Alexandre Courbot <gnurou@gmail.com>: >>> The problems I can see so far: >>> >>> - Using gpiod, GPIOs are not specified as integers, but are typically >>> mapped to a given (device, function) pair (device can be NULL) using >>> device tree/platform data/ACPI and obtained by the corresponding >>> device driver through gpiod_get(). You would need to find a different >>> way to specify GPIOs, maybe using the gpio_chip's label and the GPIO >>> hardware number. >>> >>> - Even if you do so, there is currently no way to arbitrarily obtain a >>> GPIO that has not been explicitly mapped to a (device, function), and >>> IIUC you need to specify the tracing GPIO freely from user-space. This >>> hints that we will need to add a function that is sensibly the same as >>> gpio_request_one() to the gpiod API, but I wonder if that does not >>> defeats the purpose somehow. >> >> This is something I was wondering about for another reason. In many >> cases the GPIOs that are physically available for probing will be >> limited to the GPIOs already assigned a function (backlight control >> for example), others are usually not routed except in eval boards or >> early prototypes. And consequently those GPIOs will be requested by a >> driver long before a probe is set. >> It would be nice not to have to remove the driver to be able to use >> this GPIO as a probe. Maybe a gpiod_steal() interface and a flag >> indicating that the GPIO can be safely stolen? > > Mmm an explicit way to hijack a GPIO does not sound very safe. Do you > have concrete cases where you need to do so? I guess most boards you > may want to use this patch with would have at least some spare GPIOs > with pins somewhere on the board for this kind of purpose. It's not always true. There are quite a few platforms where GPIOs is a scarce resource (ppc for example). For example, the board I'm working on at the moment is built around a APM powerpc which has only 16 GPIOs. Of those 16 GPIOS, some are not routed and most of the others are hidden by the shielding so that I can probe only those that go to external connectors. IMHO it's probably the case for most of the boards that go into a final product where EMI and space constraints are tight. But I agree that's not safe. I thought that maybe a flag indicating when it is safe would help (on my board that would be : ok to use the GPIO that turns on or off the backlight, not ok to use the GPIO that controls the power supply) ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-20 8:40 ` Jean-Jacques Hiblot @ 2014-01-03 10:50 ` Alexandre Courbot 2014-01-03 16:39 ` Jean-Jacques Hiblot 0 siblings, 1 reply; 15+ messages in thread From: Alexandre Courbot @ 2014-01-03 10:50 UTC (permalink / raw) To: Jean-Jacques Hiblot Cc: Linus Walleij, Steven Rostedt, Masami Hiramatsu, linux-gpio@vger.kernel.org, Linux Kernel Mailing List On Fri, Dec 20, 2013 at 5:40 PM, Jean-Jacques Hiblot <jjhiblot@traphandler.com> wrote: > 2013/12/20 Alexandre Courbot <gnurou@gmail.com>: >> On Thu, Dec 19, 2013 at 8:38 PM, Jean-Jacques Hiblot >> <jjhiblot@traphandler.com> wrote: >>> 2013/12/19 Alexandre Courbot <gnurou@gmail.com>: >>>> The problems I can see so far: >>>> >>>> - Using gpiod, GPIOs are not specified as integers, but are typically >>>> mapped to a given (device, function) pair (device can be NULL) using >>>> device tree/platform data/ACPI and obtained by the corresponding >>>> device driver through gpiod_get(). You would need to find a different >>>> way to specify GPIOs, maybe using the gpio_chip's label and the GPIO >>>> hardware number. >>>> >>>> - Even if you do so, there is currently no way to arbitrarily obtain a >>>> GPIO that has not been explicitly mapped to a (device, function), and >>>> IIUC you need to specify the tracing GPIO freely from user-space. This >>>> hints that we will need to add a function that is sensibly the same as >>>> gpio_request_one() to the gpiod API, but I wonder if that does not >>>> defeats the purpose somehow. >>> >>> This is something I was wondering about for another reason. In many >>> cases the GPIOs that are physically available for probing will be >>> limited to the GPIOs already assigned a function (backlight control >>> for example), others are usually not routed except in eval boards or >>> early prototypes. And consequently those GPIOs will be requested by a >>> driver long before a probe is set. >>> It would be nice not to have to remove the driver to be able to use >>> this GPIO as a probe. Maybe a gpiod_steal() interface and a flag >>> indicating that the GPIO can be safely stolen? >> >> Mmm an explicit way to hijack a GPIO does not sound very safe. Do you >> have concrete cases where you need to do so? I guess most boards you >> may want to use this patch with would have at least some spare GPIOs >> with pins somewhere on the board for this kind of purpose. > It's not always true. There are quite a few platforms where GPIOs is a > scarce resource (ppc for example). For example, the board I'm working > on at the moment is built around a APM powerpc which has only 16 > GPIOs. Of those 16 GPIOS, some are not routed and most of the others > are hidden by the shielding so that I can probe only those that go to > external connectors. > IMHO it's probably the case for most of the boards that go into a > final product where EMI and space constraints are tight. > But I agree that's not safe. I thought that maybe a flag indicating > when it is safe would help (on my board that would be : ok to use the > GPIO that turns on or off the backlight, not ok to use the GPIO that > controls the power supply) Rather than a flag per GPIO or board (my definition of "safe" is rather strict ; I'd consider being able to mess with the backlight as unsafe), I think I'd be more comfortable with having this as a kernel config option, defaulting to 'n', and clearly stating that this can potentially allow any GPIO to be hijacked (which is, apart for the last point, what you already did). That way people can make an informed decision about whether to enable it or not (disabled for distro kernels, enabled for the occasional hacker who wants to use this feature). But before doing this, I'd like to make sure we explore every possibility to make this safer by design. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2014-01-03 10:50 ` Alexandre Courbot @ 2014-01-03 16:39 ` Jean-Jacques Hiblot 0 siblings, 0 replies; 15+ messages in thread From: Jean-Jacques Hiblot @ 2014-01-03 16:39 UTC (permalink / raw) To: Alexandre Courbot Cc: Jean-Jacques Hiblot, Linus Walleij, Steven Rostedt, Masami Hiramatsu, linux-gpio@vger.kernel.org, Linux Kernel Mailing List 2014/1/3 Alexandre Courbot <gnurou@gmail.com>: > On Fri, Dec 20, 2013 at 5:40 PM, Jean-Jacques Hiblot > <jjhiblot@traphandler.com> wrote: >> 2013/12/20 Alexandre Courbot <gnurou@gmail.com>: >>> On Thu, Dec 19, 2013 at 8:38 PM, Jean-Jacques Hiblot >>> <jjhiblot@traphandler.com> wrote: >>>> 2013/12/19 Alexandre Courbot <gnurou@gmail.com>: >>>>> The problems I can see so far: >>>>> >>>>> - Using gpiod, GPIOs are not specified as integers, but are typically >>>>> mapped to a given (device, function) pair (device can be NULL) using >>>>> device tree/platform data/ACPI and obtained by the corresponding >>>>> device driver through gpiod_get(). You would need to find a different >>>>> way to specify GPIOs, maybe using the gpio_chip's label and the GPIO >>>>> hardware number. >>>>> >>>>> - Even if you do so, there is currently no way to arbitrarily obtain a >>>>> GPIO that has not been explicitly mapped to a (device, function), and >>>>> IIUC you need to specify the tracing GPIO freely from user-space. This >>>>> hints that we will need to add a function that is sensibly the same as >>>>> gpio_request_one() to the gpiod API, but I wonder if that does not >>>>> defeats the purpose somehow. >>>> >>>> This is something I was wondering about for another reason. In many >>>> cases the GPIOs that are physically available for probing will be >>>> limited to the GPIOs already assigned a function (backlight control >>>> for example), others are usually not routed except in eval boards or >>>> early prototypes. And consequently those GPIOs will be requested by a >>>> driver long before a probe is set. >>>> It would be nice not to have to remove the driver to be able to use >>>> this GPIO as a probe. Maybe a gpiod_steal() interface and a flag >>>> indicating that the GPIO can be safely stolen? >>> >>> Mmm an explicit way to hijack a GPIO does not sound very safe. Do you >>> have concrete cases where you need to do so? I guess most boards you >>> may want to use this patch with would have at least some spare GPIOs >>> with pins somewhere on the board for this kind of purpose. >> It's not always true. There are quite a few platforms where GPIOs is a >> scarce resource (ppc for example). For example, the board I'm working >> on at the moment is built around a APM powerpc which has only 16 >> GPIOs. Of those 16 GPIOS, some are not routed and most of the others >> are hidden by the shielding so that I can probe only those that go to >> external connectors. >> IMHO it's probably the case for most of the boards that go into a >> final product where EMI and space constraints are tight. >> But I agree that's not safe. I thought that maybe a flag indicating >> when it is safe would help (on my board that would be : ok to use the >> GPIO that turns on or off the backlight, not ok to use the GPIO that >> controls the power supply) > > Rather than a flag per GPIO or board (my definition of "safe" is > rather strict ; I'd consider being able to mess with the backlight as > unsafe), I think I'd be more comfortable with having this as a kernel > config option, defaulting to 'n', and clearly stating that this can > potentially allow any GPIO to be hijacked (which is, apart for the > last point, what you already did). That way people can make an > informed decision about whether to enable it or not (disabled for > distro kernels, enabled for the occasional hacker who wants to use > this feature). > > But before doing this, I'd like to make sure we explore every > possibility to make this safer by design. I agree and to be honest I'm not comfortable with the hijacker's way. Maybe I should just stick to the proper way of requesting a GPIO. When this feature is used, it'll not be in the field after production but during the development when building a new kernel is not really an issue. > -- > To unsubscribe from this list: send the line "unsubscribe linux-gpio" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2013-12-19 6:52 ` Alexandre Courbot 2013-12-19 11:38 ` Jean-Jacques Hiblot @ 2014-01-02 12:43 ` Linus Walleij 2014-01-03 16:32 ` Jean-Jacques Hiblot 1 sibling, 1 reply; 15+ messages in thread From: Linus Walleij @ 2014-01-02 12:43 UTC (permalink / raw) To: Alexandre Courbot Cc: Jean-Jacques Hiblot, Steven Rostedt, masami.hiramatsu.pt, linux-gpio@vger.kernel.org, Linux Kernel Mailing List On Thu, Dec 19, 2013 at 7:52 AM, Alexandre Courbot <gnurou@gmail.com> wrote: > On Tue, Dec 17, 2013 at 9:22 AM, Jean-Jacques Hiblot > <jjhiblot@traphandler.com> wrote: >> >> This patch implements a new tracing mechanism based on kprobes and using GPIO. >> Debugging with GPIO is very common in the embedded world. At least for those of us >> fortunate enough to have an oscilloscope or a logic analyzer on their bench... >> This is especially true if the issue results of a hardware/sofware interaction. >> >> Typical use cases are : >> * mixed software/hardware debugging. For example when the software detects a >> situation of interest (typically an error) it toggles a GPIO to trigger the >> oscilloscope acquisition. >> * direct latency/duration measurements. >> >> examples: >> To trig the oscilloscope whenever a mmc command error: >> echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events >> echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable I've never seen the whole patch. Can you please repost this and include linux-gpio@vger.kernel.org and also me on the To: line? Yours, Linus Walleij ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Tracing events with GPIOs 2014-01-02 12:43 ` Linus Walleij @ 2014-01-03 16:32 ` Jean-Jacques Hiblot 0 siblings, 0 replies; 15+ messages in thread From: Jean-Jacques Hiblot @ 2014-01-03 16:32 UTC (permalink / raw) To: Linus Walleij Cc: Alexandre Courbot, Jean-Jacques Hiblot, Steven Rostedt, Masami Hiramatsu, linux-gpio@vger.kernel.org, Linux Kernel Mailing List 2014/1/2 Linus Walleij <linus.walleij@linaro.org>: > On Thu, Dec 19, 2013 at 7:52 AM, Alexandre Courbot <gnurou@gmail.com> wrote: >> On Tue, Dec 17, 2013 at 9:22 AM, Jean-Jacques Hiblot >> <jjhiblot@traphandler.com> wrote: >>> >>> This patch implements a new tracing mechanism based on kprobes and using GPIO. >>> Debugging with GPIO is very common in the embedded world. At least for those of us >>> fortunate enough to have an oscilloscope or a logic analyzer on their bench... >>> This is especially true if the issue results of a hardware/sofware interaction. >>> >>> Typical use cases are : >>> * mixed software/hardware debugging. For example when the software detects a >>> situation of interest (typically an error) it toggles a GPIO to trigger the >>> oscilloscope acquisition. >>> * direct latency/duration measurements. >>> >>> examples: >>> To trig the oscilloscope whenever a mmc command error: >>> echo "p:my_mmc_blk_error mmc_blk_cmd_error gpiopulse@13" > /sys/kernel/debug/tracing/kprobe_events >>> echo 1 > /sys/kernel/debug/tracing/events/kprobes/my_mmc_blk_error/enable > > I've never seen the whole patch. > > Can you please repost this and include linux-gpio@vger.kernel.org and also > me on the To: line? Hello Linus, I'll repost the patch. It has evolved a bit since you've been included in the cc list. It's now based upon the 'event trigger' and more important for you, it doesn't request nor configure the GPIO before using it. The reason is that how to do this is still being discussed with Alexandre. Jean-Jacques > > Yours, > Linus Walleij ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2014-01-03 17:51 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-12-17 0:22 [PATCH] Tracing events with GPIOs Jean-Jacques Hiblot 2013-12-17 1:16 ` Masami Hiramatsu 2013-12-17 17:22 ` Jean-Jacques Hiblot 2013-12-17 18:29 ` Tom Zanussi 2013-12-17 19:05 ` Steven Rostedt 2013-12-17 20:45 ` Tom Zanussi 2013-12-31 10:16 ` Jean-Jacques Hiblot 2013-12-19 6:52 ` Alexandre Courbot 2013-12-19 11:38 ` Jean-Jacques Hiblot 2013-12-20 7:33 ` Alexandre Courbot 2013-12-20 8:40 ` Jean-Jacques Hiblot 2014-01-03 10:50 ` Alexandre Courbot 2014-01-03 16:39 ` Jean-Jacques Hiblot 2014-01-02 12:43 ` Linus Walleij 2014-01-03 16:32 ` Jean-Jacques Hiblot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).