Re: [PATCH v1 1/2] arm: a driver for on-chip ETM and ETB
2009/10/12 Linus Walleij linus.ml.wall...@gmail.com: 2009/10/11 Alexander Shishkin virtu...@slind.org: This driver implements support for on-chip Embedded Tracing Macrocell and Embedded Trace Buffer. It allows to trigger tracing of kernel execution flow and exporting trace output to userspace via character device and a sysrq combo. Cool, can it at all be interfaced to kernel tracing mechanisms like ftrace, LTTng...? Or is this entirely orthogonal? I'll have to check on that. First, these are registered as platform devices, should they not be AMBA devices (i.e. PrimeCells?) I think that's what they are, and they probably have device ID:s to be matched in the last words of their 4K pages do they not? Only ETMv3.2 and are said to comply with AMBA with regards to peripheral id and component id registers and I'm not quite sure how useful those are. Whereas having those as platform devices provides the possibility to have them defined per platform for most of ETM versions. (...) diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c new file mode 100644 index 000..3e7b431 --- /dev/null +++ b/arch/arm/kernel/etm.c @@ -0,0 +1,588 @@ +/* + * linux/arch/arm/kernel/etm.c + * + * Driver for ARM's Embedded Trace Macrocell and Embedded Trace Buffer. + * + * Copyright (C) 2009 Nokia Corporation. + * Alexander Shishkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/kernel.h +#include linux/init.h +#include linux/types.h +#include linux/io.h +#include linux/clk.h +#include linux/sysrq.h +#include linux/platform_device.h +#include linux/fs.h +#include linux/uaccess.h +#include linux/miscdevice.h +#include linux/vmalloc.h +#include linux/mutex.h +#include asm/hardware/coresight.h +#include asm/sections.h + +MODULE_LICENSE(GPL); +MODULE_AUTHOR(Alexander Shishkin); + +static struct tracectx tracer; + +static inline bool trace_isrunning(struct tracectx *t) +{ + return !!(t-flags TRACER_RUNNING); +} + +static int etm_setup_address_range(struct tracectx *t, int n, + unsigned long start, unsigned long end, int exclude, int data) +{ + u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \ + ETMAAT_NOVALCMP; + + if (n 1 || n t-ncmppairs) + return -EINVAL; + + /* comparators and ranges are numbered starting with 1 as opposed + * to bits in a word */ + n--; + + if (data) + flags |= ETMAAT_DLOADSTORE; + else + flags |= ETMAAT_IEXEC; + + /* first comparator for the range */ + etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2)); + etm_writel(t, start, ETMR_COMP_VAL(n * 2)); + + /* second comparator is right next to it */ + etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1)); + etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1)); + + flags = exclude ? ETMTE_INCLEXCL : 0; + etm_writel(t, flags | (1 n), ETMR_TRACEENCTRL); + + return 0; +} + +static int trace_start(struct tracectx *t) +{ + u32 v; + unsigned long timeout = TRACER_TIMEOUT; + + etb_unlock(t); + + etb_writel(t, 0, ETBR_FORMATTERCTRL); + etb_writel(t, 1, ETBR_CTRL); + + etb_lock(t); + + /* configure etm */ + v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t-etm_portsz); + + if (t-flags TRACER_CYCLE_ACC) + v |= ETMCTRL_CYCLEACCURATE; + + etm_unlock(t); + + etm_writel(t, v, ETMR_CTRL); + + while (!(etm_readl(t, ETMR_CTRL) ETMCTRL_PROGRAM) --timeout) + ; + if (!timeout) { + dev_dbg(t-dev, Waiting for progbit to assert timed out\n); + etm_lock(t); + return -EFAULT; + } + + etm_setup_address_range(t, 1, (unsigned long)_stext, + (unsigned long)_etext, 0, 0); + etm_writel(t, 0, ETMR_TRACEENCTRL2); + etm_writel(t, 0, ETMR_TRACESSCTRL); + etm_writel(t, 0x6f, ETMR_TRACEENEVT); + + v = ~ETMCTRL_PROGRAM; + v |= ETMCTRL_PORTSEL; + + etm_writel(t, v, ETMR_CTRL); + + timeout = TRACER_TIMEOUT; + while (etm_readl(t, ETMR_CTRL) ETMCTRL_PROGRAM --timeout) + ; + if (!timeout) { + dev_dbg(t-dev, Waiting for progbit to deassert timed out\n); + etm_lock(t); + return -EFAULT; + } + + etm_lock(t); + + t-flags |= TRACER_RUNNING; + + return 0; +} + +static int trace_stop(struct tracectx *t) +{ + unsigned long timeout = TRACER_TIMEOUT; + + etm_unlock(t); + + etm_writel(t, 0x440, ETMR_CTRL); + while (!(etm_readl(t, ETMR_CTRL) ETMCTRL_PROGRAM)
[PATCH v1 1/2] arm: a driver for on-chip ETM and ETB
This driver implements support for on-chip Embedded Tracing Macrocell and Embedded Trace Buffer. It allows to trigger tracing of kernel execution flow and exporting trace output to userspace via character device and a sysrq combo. Trace output can then be decoded by a fairly simple open source tool [1] which is already sufficient to get the idea of what the kernel is doing. [1]: http://github.com/virtuoso/etm2human Signed-off-by: Alexander Shishkin virtu...@slind.org Signed-off-by: Juha Leppanen juha_motorsport...@luukku.com --- Changes: v1 -- fixed comments from Juha Leppanen v0 -- initial implementation, has been sent to linux-omap only arch/arm/Kconfig.debug|8 + arch/arm/include/asm/hardware/coresight.h | 164 arch/arm/kernel/Makefile |2 + arch/arm/kernel/etm.c | 588 + 4 files changed, 762 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/hardware/coresight.h create mode 100644 arch/arm/kernel/etm.c diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 1a6f70e..ac83c03 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -83,6 +83,14 @@ config DEBUG_ICEDCC It does include a timeout to ensure that the system does not totally freeze when there is nothing connected to read. +config OC_ETM + tristate On-chip ETM and ETB + depends on ARCH_OMAP3 + help + Enables the on-chip embedded trace macrocell and embedded trace + buffer driver that will allow you to collect traces of the + kernel code. + config DEBUG_DC21285_PORT bool Kernel low-level debugging messages via footbridge serial port depends on DEBUG_LL FOOTBRIDGE diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h new file mode 100644 index 000..ba22df9 --- /dev/null +++ b/arch/arm/include/asm/hardware/coresight.h @@ -0,0 +1,164 @@ +/* + * linux/arch/arm/include/asm/hardware/coresight.h + * + * CoreSight components' registers + * + * Copyright (C) 2009 Nokia Corporation. + * Alexander Shishkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_HARDWARE_CORESIGHT_H +#define __ASM_HARDWARE_CORESIGHT_H + +#define TRACER_ACCESSED_BIT0 +#define TRACER_RUNNING_BIT 1 +#define TRACER_CYCLE_ACC_BIT 2 +#define TRACER_ACCESSEDBIT(TRACER_ACCESSED_BIT) +#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT) +#define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT) + +struct tracectx { + unsigned int etb_bufsz; + void __iomem *etb_regs; + void __iomem *etm_regs; + unsigned long flags; + int ncmppairs; + int etm_portsz; + struct device *dev; + struct mutex mutex; +}; + +#define TRACER_TIMEOUT 1 + +#define etm_writel(t, v, x) \ + (__raw_writel((v), (t)-etm_regs + (x))) +#define etm_readl(t, x) (__raw_readl((t)-etm_regs + (x))) + +/* CoreSight Management Registers */ +#define CSMR_LOCKACCESS 0xfb0 +#define CSMR_LOCKSTATUS 0xfb4 +#define CSMR_AUTHSTATUS 0xfb8 +#define CSMR_DEVID 0xfc8 +#define CSMR_DEVTYPE 0xfcc +/* CoreSight Component Registers */ +#define CSCR_CLASS 0xff4 + +#define CSCR_PRSR 0x314 + +#define UNLOCK_MAGIC 0xc5acce55 + +/* ETM control register, ETM Architecture, 3.3.1 */ +#define ETMR_CTRL 0 +#define ETMCTRL_POWERDOWN 1 +#define ETMCTRL_PROGRAM(1 10) +#define ETMCTRL_PORTSEL(1 11) +#define ETMCTRL_DO_CONTEXTID (3 14) +#define ETMCTRL_PORTMASK1 (7 4) +#define ETMCTRL_PORTMASK2 (1 21) +#define ETMCTRL_PORTMASK (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2) +#define ETMCTRL_PORTSIZE(x) x) 7) 4) | (!!((x) 8)) 21) +#define ETMCTRL_DO_CPRT(1 1) +#define ETMCTRL_DATAMASK (3 2) +#define ETMCTRL_DATA_DO_DATA (1 2) +#define ETMCTRL_DATA_DO_ADDR (1 3) +#define ETMCTRL_DATA_DO_BOTH (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR) +#define ETMCTRL_BRANCH_OUTPUT (1 8) +#define ETMCTRL_CYCLEACCURATE (1 12) + +/* ETM configuration code register */ +#define ETMR_CONFCODE (0x04) + +/* ETM trace start/stop resource control register */ +#define ETMR_TRACESSCTRL (0x18) + +/* ETM trigger event register */ +#define ETMR_TRIGEVT (0x08) + +/* address access type register bits, ETM architecture, + * table 3-27 */ +/* - access type */ +#define ETMAAT_IFETCH 0 +#define ETMAAT_IEXEC 1 +#define ETMAAT_IEXECPASS 2 +#define ETMAAT_IEXECFAIL 3 +#define ETMAAT_DLOADSTORE 4 +#define ETMAAT_DLOAD 5 +#define ETMAAT_DSTORE 6 +/* - comparison access size */ +#define ETMAAT_JAVA(0 3) +#define ETMAAT_THUMB (1 3) +#define ETMAAT_ARM
Re: [PATCH v1 1/2] arm: a driver for on-chip ETM and ETB
2009/10/11 Alexander Shishkin virtu...@slind.org: This driver implements support for on-chip Embedded Tracing Macrocell and Embedded Trace Buffer. It allows to trigger tracing of kernel execution flow and exporting trace output to userspace via character device and a sysrq combo. Cool, can it at all be interfaced to kernel tracing mechanisms like ftrace, LTTng...? Or is this entirely orthogonal? First, these are registered as platform devices, should they not be AMBA devices (i.e. PrimeCells?) I think that's what they are, and they probably have device ID:s to be matched in the last words of their 4K pages do they not? (...) diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c new file mode 100644 index 000..3e7b431 --- /dev/null +++ b/arch/arm/kernel/etm.c @@ -0,0 +1,588 @@ +/* + * linux/arch/arm/kernel/etm.c + * + * Driver for ARM's Embedded Trace Macrocell and Embedded Trace Buffer. + * + * Copyright (C) 2009 Nokia Corporation. + * Alexander Shishkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/kernel.h +#include linux/init.h +#include linux/types.h +#include linux/io.h +#include linux/clk.h +#include linux/sysrq.h +#include linux/platform_device.h +#include linux/fs.h +#include linux/uaccess.h +#include linux/miscdevice.h +#include linux/vmalloc.h +#include linux/mutex.h +#include asm/hardware/coresight.h +#include asm/sections.h + +MODULE_LICENSE(GPL); +MODULE_AUTHOR(Alexander Shishkin); + +static struct tracectx tracer; + +static inline bool trace_isrunning(struct tracectx *t) +{ + return !!(t-flags TRACER_RUNNING); +} + +static int etm_setup_address_range(struct tracectx *t, int n, + unsigned long start, unsigned long end, int exclude, int data) +{ + u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \ + ETMAAT_NOVALCMP; + + if (n 1 || n t-ncmppairs) + return -EINVAL; + + /* comparators and ranges are numbered starting with 1 as opposed + * to bits in a word */ + n--; + + if (data) + flags |= ETMAAT_DLOADSTORE; + else + flags |= ETMAAT_IEXEC; + + /* first comparator for the range */ + etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2)); + etm_writel(t, start, ETMR_COMP_VAL(n * 2)); + + /* second comparator is right next to it */ + etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1)); + etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1)); + + flags = exclude ? ETMTE_INCLEXCL : 0; + etm_writel(t, flags | (1 n), ETMR_TRACEENCTRL); + + return 0; +} + +static int trace_start(struct tracectx *t) +{ + u32 v; + unsigned long timeout = TRACER_TIMEOUT; + + etb_unlock(t); + + etb_writel(t, 0, ETBR_FORMATTERCTRL); + etb_writel(t, 1, ETBR_CTRL); + + etb_lock(t); + + /* configure etm */ + v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t-etm_portsz); + + if (t-flags TRACER_CYCLE_ACC) + v |= ETMCTRL_CYCLEACCURATE; + + etm_unlock(t); + + etm_writel(t, v, ETMR_CTRL); + + while (!(etm_readl(t, ETMR_CTRL) ETMCTRL_PROGRAM) --timeout) + ; + if (!timeout) { + dev_dbg(t-dev, Waiting for progbit to assert timed out\n); + etm_lock(t); + return -EFAULT; + } + + etm_setup_address_range(t, 1, (unsigned long)_stext, + (unsigned long)_etext, 0, 0); + etm_writel(t, 0, ETMR_TRACEENCTRL2); + etm_writel(t, 0, ETMR_TRACESSCTRL); + etm_writel(t, 0x6f, ETMR_TRACEENEVT); + + v = ~ETMCTRL_PROGRAM; + v |= ETMCTRL_PORTSEL; + + etm_writel(t, v, ETMR_CTRL); + + timeout = TRACER_TIMEOUT; + while (etm_readl(t, ETMR_CTRL) ETMCTRL_PROGRAM --timeout) + ; + if (!timeout) { + dev_dbg(t-dev, Waiting for progbit to deassert timed out\n); + etm_lock(t); + return -EFAULT; + } + + etm_lock(t); + + t-flags |= TRACER_RUNNING; + + return 0; +} + +static int trace_stop(struct tracectx *t) +{ + unsigned long timeout = TRACER_TIMEOUT; + + etm_unlock(t); + + etm_writel(t, 0x440, ETMR_CTRL); + while (!(etm_readl(t, ETMR_CTRL) ETMCTRL_PROGRAM) --timeout) + ; + if (!timeout) { + dev_dbg(t-dev, Waiting for progbit to assert timed out\n); + etm_lock(t); + return -EFAULT; + } + + etm_lock(t); + + etb_unlock(t); + etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL); + + timeout = TRACER_TIMEOUT; + while
Re: [PATCH v1 1/2] arm: a driver for on-chip ETM and ETB
On Mon, Oct 12, 2009 at 12:07:57AM +0200, Linus Walleij wrote: First, these are registered as platform devices, should they not be AMBA devices (i.e. PrimeCells?) I think that's what they are, and they probably have device ID:s to be matched in the last words of their 4K pages do they not? It does look like it's Primecell-like, so it should be using the primecell support so that others can make use of this. As such, it should not be OMAP specific. + clk = clk_get(pdev-dev, emu_core_alwon_ck); + clk_enable(clk); + + clk = clk_get(pdev-dev, emu_per_alwon_ck); + clk_enable(clk); + + clk = clk_get(pdev-dev, emu_mpu_alwon_ck); + clk_enable(clk); + + clk = clk_get(pdev-dev, emu_src_ck); + clk_enable(clk); Are these clocks really generic? It looks a lot like OMAP-specific stuff. Is it possible to hide these behind a single clock inside the platform? like etbclock or so that increase refcount of the others by 1? First obvious problem is that there's no error checking there. Second problem is that this could very well be a generic driver, and OMAP specifics should not be in here. Looking at the Coresight ETM11 documentation, there's: ATCLK - ATB interface clock CLK - main clock PCLKDBG - Debug APB clock or PCLK - APB clock I'm not sure why OMAP seems to have four clocks when the ETM has only three clocks itself. -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html