diff options
Diffstat (limited to 'Documentation/trace/mmiotrace.txt')
-rw-r--r-- | Documentation/trace/mmiotrace.txt | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/Documentation/trace/mmiotrace.txt b/Documentation/trace/mmiotrace.txt new file mode 100644 index 000000000000..5731c67abc55 --- /dev/null +++ b/Documentation/trace/mmiotrace.txt | |||
@@ -0,0 +1,163 @@ | |||
1 | In-kernel memory-mapped I/O tracing | ||
2 | |||
3 | |||
4 | Home page and links to optional user space tools: | ||
5 | |||
6 | http://nouveau.freedesktop.org/wiki/MmioTrace | ||
7 | |||
8 | MMIO tracing was originally developed by Intel around 2003 for their Fault | ||
9 | Injection Test Harness. In Dec 2006 - Jan 2007, using the code from Intel, | ||
10 | Jeff Muizelaar created a tool for tracing MMIO accesses with the Nouveau | ||
11 | project in mind. Since then many people have contributed. | ||
12 | |||
13 | Mmiotrace was built for reverse engineering any memory-mapped IO device with | ||
14 | the Nouveau project as the first real user. Only x86 and x86_64 architectures | ||
15 | are supported. | ||
16 | |||
17 | Out-of-tree mmiotrace was originally modified for mainline inclusion and | ||
18 | ftrace framework by Pekka Paalanen <pq@iki.fi>. | ||
19 | |||
20 | |||
21 | Preparation | ||
22 | ----------- | ||
23 | |||
24 | Mmiotrace feature is compiled in by the CONFIG_MMIOTRACE option. Tracing is | ||
25 | disabled by default, so it is safe to have this set to yes. SMP systems are | ||
26 | supported, but tracing is unreliable and may miss events if more than one CPU | ||
27 | is on-line, therefore mmiotrace takes all but one CPU off-line during run-time | ||
28 | activation. You can re-enable CPUs by hand, but you have been warned, there | ||
29 | is no way to automatically detect if you are losing events due to CPUs racing. | ||
30 | |||
31 | |||
32 | Usage Quick Reference | ||
33 | --------------------- | ||
34 | |||
35 | $ mount -t debugfs debugfs /debug | ||
36 | $ echo mmiotrace > /debug/tracing/current_tracer | ||
37 | $ cat /debug/tracing/trace_pipe > mydump.txt & | ||
38 | Start X or whatever. | ||
39 | $ echo "X is up" > /debug/tracing/trace_marker | ||
40 | $ echo nop > /debug/tracing/current_tracer | ||
41 | Check for lost events. | ||
42 | |||
43 | |||
44 | Usage | ||
45 | ----- | ||
46 | |||
47 | Make sure debugfs is mounted to /debug. If not, (requires root privileges) | ||
48 | $ mount -t debugfs debugfs /debug | ||
49 | |||
50 | Check that the driver you are about to trace is not loaded. | ||
51 | |||
52 | Activate mmiotrace (requires root privileges): | ||
53 | $ echo mmiotrace > /debug/tracing/current_tracer | ||
54 | |||
55 | Start storing the trace: | ||
56 | $ cat /debug/tracing/trace_pipe > mydump.txt & | ||
57 | The 'cat' process should stay running (sleeping) in the background. | ||
58 | |||
59 | Load the driver you want to trace and use it. Mmiotrace will only catch MMIO | ||
60 | accesses to areas that are ioremapped while mmiotrace is active. | ||
61 | |||
62 | During tracing you can place comments (markers) into the trace by | ||
63 | $ echo "X is up" > /debug/tracing/trace_marker | ||
64 | This makes it easier to see which part of the (huge) trace corresponds to | ||
65 | which action. It is recommended to place descriptive markers about what you | ||
66 | do. | ||
67 | |||
68 | Shut down mmiotrace (requires root privileges): | ||
69 | $ echo nop > /debug/tracing/current_tracer | ||
70 | The 'cat' process exits. If it does not, kill it by issuing 'fg' command and | ||
71 | pressing ctrl+c. | ||
72 | |||
73 | Check that mmiotrace did not lose events due to a buffer filling up. Either | ||
74 | $ grep -i lost mydump.txt | ||
75 | which tells you exactly how many events were lost, or use | ||
76 | $ dmesg | ||
77 | to view your kernel log and look for "mmiotrace has lost events" warning. If | ||
78 | events were lost, the trace is incomplete. You should enlarge the buffers and | ||
79 | try again. Buffers are enlarged by first seeing how large the current buffers | ||
80 | are: | ||
81 | $ cat /debug/tracing/buffer_size_kb | ||
82 | gives you a number. Approximately double this number and write it back, for | ||
83 | instance: | ||
84 | $ echo 128000 > /debug/tracing/buffer_size_kb | ||
85 | Then start again from the top. | ||
86 | |||
87 | If you are doing a trace for a driver project, e.g. Nouveau, you should also | ||
88 | do the following before sending your results: | ||
89 | $ lspci -vvv > lspci.txt | ||
90 | $ dmesg > dmesg.txt | ||
91 | $ tar zcf pciid-nick-mmiotrace.tar.gz mydump.txt lspci.txt dmesg.txt | ||
92 | and then send the .tar.gz file. The trace compresses considerably. Replace | ||
93 | "pciid" and "nick" with the PCI ID or model name of your piece of hardware | ||
94 | under investigation and your nick name. | ||
95 | |||
96 | |||
97 | How Mmiotrace Works | ||
98 | ------------------- | ||
99 | |||
100 | Access to hardware IO-memory is gained by mapping addresses from PCI bus by | ||
101 | calling one of the ioremap_*() functions. Mmiotrace is hooked into the | ||
102 | __ioremap() function and gets called whenever a mapping is created. Mapping is | ||
103 | an event that is recorded into the trace log. Note, that ISA range mappings | ||
104 | are not caught, since the mapping always exists and is returned directly. | ||
105 | |||
106 | MMIO accesses are recorded via page faults. Just before __ioremap() returns, | ||
107 | the mapped pages are marked as not present. Any access to the pages causes a | ||
108 | fault. The page fault handler calls mmiotrace to handle the fault. Mmiotrace | ||
109 | marks the page present, sets TF flag to achieve single stepping and exits the | ||
110 | fault handler. The instruction that faulted is executed and debug trap is | ||
111 | entered. Here mmiotrace again marks the page as not present. The instruction | ||
112 | is decoded to get the type of operation (read/write), data width and the value | ||
113 | read or written. These are stored to the trace log. | ||
114 | |||
115 | Setting the page present in the page fault handler has a race condition on SMP | ||
116 | machines. During the single stepping other CPUs may run freely on that page | ||
117 | and events can be missed without a notice. Re-enabling other CPUs during | ||
118 | tracing is discouraged. | ||
119 | |||
120 | |||
121 | Trace Log Format | ||
122 | ---------------- | ||
123 | |||
124 | The raw log is text and easily filtered with e.g. grep and awk. One record is | ||
125 | one line in the log. A record starts with a keyword, followed by keyword | ||
126 | dependant arguments. Arguments are separated by a space, or continue until the | ||
127 | end of line. The format for version 20070824 is as follows: | ||
128 | |||
129 | Explanation Keyword Space separated arguments | ||
130 | --------------------------------------------------------------------------- | ||
131 | |||
132 | read event R width, timestamp, map id, physical, value, PC, PID | ||
133 | write event W width, timestamp, map id, physical, value, PC, PID | ||
134 | ioremap event MAP timestamp, map id, physical, virtual, length, PC, PID | ||
135 | iounmap event UNMAP timestamp, map id, PC, PID | ||
136 | marker MARK timestamp, text | ||
137 | version VERSION the string "20070824" | ||
138 | info for reader LSPCI one line from lspci -v | ||
139 | PCI address map PCIDEV space separated /proc/bus/pci/devices data | ||
140 | unk. opcode UNKNOWN timestamp, map id, physical, data, PC, PID | ||
141 | |||
142 | Timestamp is in seconds with decimals. Physical is a PCI bus address, virtual | ||
143 | is a kernel virtual address. Width is the data width in bytes and value is the | ||
144 | data value. Map id is an arbitrary id number identifying the mapping that was | ||
145 | used in an operation. PC is the program counter and PID is process id. PC is | ||
146 | zero if it is not recorded. PID is always zero as tracing MMIO accesses | ||
147 | originating in user space memory is not yet supported. | ||
148 | |||
149 | For instance, the following awk filter will pass all 32-bit writes that target | ||
150 | physical addresses in the range [0xfb73ce40, 0xfb800000[ | ||
151 | |||
152 | $ awk '/W 4 / { adr=strtonum($5); if (adr >= 0xfb73ce40 && | ||
153 | adr < 0xfb800000) print; }' | ||
154 | |||
155 | |||
156 | Tools for Developers | ||
157 | -------------------- | ||
158 | |||
159 | The user space tools include utilities for: | ||
160 | - replacing numeric addresses and values with hardware register names | ||
161 | - replaying MMIO logs, i.e., re-executing the recorded writes | ||
162 | |||
163 | |||