blob: c91ead78b583a9930f96b3e643e5c38d517f293f [file] [log] [blame]
MIPI System Trace Module driver
===============================
Copyright (C) ST-Ericsson SA 2011
Authors: Pierre Peiffer <pierre dot peiffer at stericsson dot com>
Philippe Langlais <philippe dot langlais at linaro dot org>
License: The GNU Free Documentation License, Version 1.2
(dual licensed under the GPL v2)
Hardware overview
=================
This hardware collects and provides simple tracepoints,
so a system processor (in our case the main ARM CPU,
or some small CPUs and DSPs) can write some data,
up to 8 bytes, into a register and out comes a log entry
with a time stamp (20ns resolution) on one of 256 channels. Also
hardware tracepoints are supported.
This module external interface is a pad on the chip
which complies to the MIPI System Trace Protocol v1.0
(see http://www.mipi.org/specifications/debug)
and the actual trace output can be read by an
electronic probe, not by software so it cannot be intercepted by
the CPU and reach Linux userspace.
Bandwidth depends on number of lines & bus frequency (for example on ux500
SoC 4 lines at max 100MHz eg max 400Mbit/s shared between 7 cores).
Transmit FIFO size: 256 samples up to 8 bytes.
On ux500 platform there is 2 contiguous STM blocks (eg 512 channels)
Software Overview
=================
Write atomicity and write order on STM trace channels is ensured by the fact
we try to allocate one channel by execution thread (no concurrent access).
There is 2 modes one lossless but intrusive aka Software mode and
another lossy mode less intrusive aka Hardware mode, by default
all sources are configured in Hardware mode and enabled.
The end of data packet is marked by a time stamp on latest byte(s) only.
Kernel API
----------
Configuration functions:
output trace clock frequency, trace mode, output port configuration
and enable/disable STM trace sources
Expose a debugfs interface too for STM trace control
Alloc/free STM trace channel functions
Set of low level atomic trace functions for 1, 2, 4 or 8 bytes
with & w/o time stamp
Higher level lockless trace functions:
stm_trace_buffer:
allocate a channel in 128 highest channels available
output the trace buffer with arbitrary length
(latest byte(s) automatically time stamped) then free the channel
stm_trace_buffer_onchannel:
use given channel to output the trace buffer
with arbitrary length (latest byte(s) automatically time stamped)
File IO output console like interface (open, close, write)
See <trace/stm.h> & drivers/misc/stm.c for more detail
debugfs API
-----------
clockdiv:
This is used to set or display the current clock divisor
that is configured
connection:
This is used to set or display the current output connector
that is configured (common values, 0 not connected, 1 for default
connection, 3 on Ux500 for APE MIPI34 connection)
free_channels:
This is used to display the total number of free channels
masters_enable:
This sets or displays whether the STM trace sources
are activated. Each bits represent the state of corresponding source:
0 for disable or 1 to enable it.
masters_modes:
This sets or displays the STM trace sources modes.
Each bits represent the mode of corresponding source:
0 for Sofware lossless mode or 1 for Hardware lossy mode.
User API
--------
IOCTLs or debugfs for controls
2 levels API for tracing:
- Standard write function, in this case a channel is automatically
allocated at first write, after you can channel number
with IOCTL STM_GET_CHANNEL_NO
- mmap for direct access of all STM trace channels port plus
a set of IOCTLs for alloc/free channels, in this case you can
write your own lib to easiest its usage
Examples of using the STM
=========================
First mount debugfs with:
mount -t debugfs none /sys/kernel/debug
In a shell scipt
----------------
It's as easy as:
echo "My trace point" > /dev/stm0
To avoid trace overflow, increase STM clock by decreasing the clockdiv with:
echo 1 >/sys/kernel/debug/stm/clockdiv # now use DIV2 instead of default DIV8
If not enough you can disable some sources with:
echo YourEnableSources > /sys/kernel/debug/stm/masters_enable
If always not enough the ultime intrusive way is to change the sources mode
and set the corresponding sources in Software mode (set corresponding source
bit to 0) with:
echo YourModeSources > /sys/kernel/debug/stm/masters_modes
(be aware some source doesn't support Software mode => keep it in HW mode)
NB: on Ux500 platform, first you have to configure STM output port to switch
APE tracing on MIPI34 connector with:
echo 3 > /sys/kernel/debug/stm/connection
In C language
-------------
The easy way more intrusive (with STM buffer recopy):
#include <trace/stm.h>
int fd, i;
char buf[1024]; // Try to align this buffer on 64 bits if possible
fd = open("/dev/stm0", O_WRONLY);
snprintf(buf, 1024, "STM0 Hello world\n");
write(fd, buf, strlen(buf));
ioctl(fd, STM_GET_CHANNEL_NO, &i);
snprintf(buf, 1024, "Use channel #%d\n", i);
write(fd, buf, strlen(buf));
close(fd);
NB: You can call open("/dev/stm0", O_WRONLY) as many times as necessary
to allocate a different channel to avoid concurrency in your
multithreaded application.
The more efficient way, use mmap'ed STM channels memory (to put in a lib):
#include <trace/stm.h>
int fd, i, c, l, maxChannels;
char buf[1024]; // Try to align this buffer on 64 bits if possible
volatile struct stm_channel *channels; // mmap'ed channels area
fd = open("/dev/stm0", O_RDWR);
ioctl(fd0, STM_GET_NB_MAX_CHANNELS, &maxChannels);
channels = (struct stm_channel *)mmap(0, maxChannels*sizeof(*channels),
PROT_WRITE, MAP_SHARED, fd, 0);
assert(channels != MAP_FAILED);
if (!ioctl(fd, STM_GET_FREE_CHANNEL, &c)) {
l = snprintf(buf, 1024, "STM0 Hello world on channel #%d\n", c);
// lazy implementation you have to send buffer by 8 Bytes when possible
// and be sure you don't share this channel with others threads
for (i=0; i<l; i++) {
channels[c].stamp8 = buf[i];
}
ioctl(fd, STM_RELEASE_CHANNEL, c);
}
munmap((void *)channels, maxChannels*sizeof(*channels));
close(fd);
Kernel Internal usages
======================
Dynamically channels dedicated for the kernel are allocated
in the 128 highest ones
Via menuconfig you can:
- Duplicate printk output on a STM dedicated channel (255)
- Have realtime ftrace output to a STM dedicated channel (254),
if corresponding TRACER is enabled
- Have realtime sched context switch & sched wakeup output on dedicated channels
(253, 252), if corresponding TRACER is enabled
- Have Stack Trace on dedicated channels (251)
- Duplicate trace_printk output on dedicated channels (250 & 249)
And in the future:
------------------
- Use it in standard kernel tracing infrastucture,
possibilities:
- Insert other STM trace calls before trace ring buffer write
- Substitute time stamping & trace ring buffer by STM