diff options
| author | Pekka Paalanen <pq@iki.fi> | 2008-05-12 15:20:59 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-24 05:26:07 -0400 |
| commit | c6c67c1afcce71335b18ed8769b1165c468bfb03 (patch) | |
| tree | 3e2bbcaeb67e3c28d9b74c22658914c8b1637b5f | |
| parent | 736ca61fa81874b3fee205a593251b1869d0bcf1 (diff) | |
mmiotrace: add user documentation
Signed-off-by: Pekka Paalanen <pq@iki.fi>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
| -rw-r--r-- | Documentation/tracers/mmiotrace.txt | 153 | ||||
| -rw-r--r-- | arch/x86/Kconfig.debug | 8 |
2 files changed, 156 insertions, 5 deletions
diff --git a/Documentation/tracers/mmiotrace.txt b/Documentation/tracers/mmiotrace.txt new file mode 100644 index 000000000000..84246f703875 --- /dev/null +++ b/Documentation/tracers/mmiotrace.txt | |||
| @@ -0,0 +1,153 @@ | |||
| 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 [not implemented]. | ||
| 29 | |||
| 30 | |||
| 31 | Usage Quick Reference | ||
| 32 | --------------------- | ||
| 33 | |||
| 34 | $ mount -t debugfs debugfs /debug | ||
| 35 | $ echo mmiotrace > /debug/tracing/current_tracer | ||
| 36 | $ cat /debug/tracing/trace_pipe > mydump.txt & | ||
| 37 | Start X or whatever. | ||
| 38 | $ echo "X is up" > /debug/tracing/marker | ||
| 39 | $ echo none > /debug/tracing/current_tracer | ||
| 40 | Check kernel log. | ||
| 41 | |||
| 42 | |||
| 43 | Usage | ||
| 44 | ----- | ||
| 45 | |||
| 46 | Make sure debugfs is mounted to /debug. If not, (requires root privileges) | ||
| 47 | $ mount -t debugfs debugfs /debug | ||
| 48 | |||
| 49 | Check that the driver you are about to trace is not loaded. | ||
| 50 | |||
| 51 | Activate mmiotrace (requires root privileges): | ||
| 52 | $ echo mmiotrace > /debug/tracing/current_tracer | ||
| 53 | |||
| 54 | Start storing the trace: | ||
| 55 | $ cat /debug/tracing/trace_pipe > mydump.txt & | ||
| 56 | The 'cat' process should stay running (sleeping) in the background. | ||
| 57 | |||
| 58 | Load the driver you want to trace and use it. Mmiotrace will only catch MMIO | ||
| 59 | accesses to areas that are ioremapped while mmiotrace is active. | ||
| 60 | |||
| 61 | [Unimplemented feature:] | ||
| 62 | During tracing you can place comments (markers) into the trace by | ||
| 63 | $ echo "X is up" > /debug/tracing/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 none > /debug/tracing/current_tracer | ||
| 70 | The 'cat' process exits. If it does not, kill it by 'fg' and pressing ctrl+c. | ||
| 71 | |||
| 72 | [This feature is not implemented yet!] | ||
| 73 | Check your kernel log. If there are messages about mmiotrace losing events, | ||
| 74 | this is due to buffer overrun, and the trace is incomplete. You should enlarge | ||
| 75 | the buffers and try again. [How?] | ||
| 76 | |||
| 77 | If you are doing a trace for a driver project, e.g. Nouveau, you should also | ||
| 78 | do the following before sending your results: | ||
| 79 | $ lspci -vvv > lspci.txt | ||
| 80 | $ dmesg > dmesg.txt | ||
| 81 | $ tar zcf pciid-nick-mmiotrace.tar.gz mydump.txt lspci.txt dmesg.txt | ||
| 82 | and then send the .tar.gz file. The trace compresses considerably. Replace | ||
| 83 | "pciid" and "nick" with the PCI ID or model name of your piece of hardware | ||
| 84 | under investigation and your nick name. | ||
| 85 | |||
| 86 | |||
| 87 | How Mmiotrace Works | ||
| 88 | ------------------- | ||
| 89 | |||
| 90 | Access to hardware IO-memory is gained by mapping addresses from PCI bus by | ||
| 91 | calling one of the ioremap_*() functions. Mmiotrace is hooked into the | ||
| 92 | __ioremap() function and gets called whenever a mapping is created. Mapping is | ||
| 93 | an event that is recorded into the trace log. Note, that ISA range mappings | ||
| 94 | are not caught, since the mapping always exists and is returned directly. | ||
| 95 | |||
| 96 | MMIO accesses are recorded via page faults. Just before __ioremap() returns, | ||
| 97 | the mapped pages are marked as not present. Any access to the pages causes a | ||
| 98 | fault. The page fault handler calls mmiotrace to handle the fault. Mmiotrace | ||
| 99 | marks the page present, sets TF flag to achieve single stepping and exits the | ||
| 100 | fault handler. The instruction that faulted is executed and debug trap is | ||
| 101 | entered. Here mmiotrace again marks the page as not present. The instruction | ||
| 102 | is decoded to get the type of operation (read/write), data width and the value | ||
| 103 | read or written. These are stored to the trace log. | ||
| 104 | |||
| 105 | Setting the page present in the page fault handler has a race condition on SMP | ||
| 106 | machines. During the single stepping other CPUs may run freely on that page | ||
| 107 | and events can be missed without a notice. Re-enabling other CPUs during | ||
| 108 | tracing is discouraged. | ||
| 109 | |||
| 110 | |||
| 111 | Trace Log Format | ||
| 112 | ---------------- | ||
| 113 | |||
| 114 | The raw log is text and easily filtered with e.g. grep and awk. One record is | ||
| 115 | one line in the log. A record starts with a keyword, followed by keyword | ||
| 116 | dependant arguments. Arguments are separated by a space, or continue until the | ||
| 117 | end of line. The format for version 20070824 is as follows: | ||
| 118 | |||
| 119 | Explanation Keyword Space separated arguments | ||
| 120 | --------------------------------------------------------------------------- | ||
| 121 | |||
| 122 | read event R width, timestamp, map id, physical, value, PC, PID | ||
| 123 | write event W width, timestamp, map id, physical, value, PC, PID | ||
| 124 | ioremap event MAP timestamp, map id, physical, virtual, length, PC, PID | ||
| 125 | iounmap event UNMAP timestamp, map id, PC, PID | ||
| 126 | marker MARK timestamp, text | ||
| 127 | version VERSION the string "20070824" | ||
| 128 | info for reader LSPCI one line from lspci -v | ||
| 129 | PCI address map PCIDEV space separated /proc/bus/pci/devices data | ||
| 130 | unk. opcode UNKNOWN timestamp, map id, physical, data, PC, PID | ||
| 131 | |||
| 132 | Timestamp is in seconds with decimals. Physical is a PCI bus address, virtual | ||
| 133 | is a kernel virtual address. Width is the data width in bytes and value is the | ||
| 134 | data value. Map id is an arbitrary id number identifying the mapping that was | ||
| 135 | used in an operation. PC is the program counter and PID is process id. PC is | ||
| 136 | zero if it is not recorded. PID is always zero as tracing MMIO accesses | ||
| 137 | originating in user space memory is not yet supported. | ||
| 138 | |||
| 139 | For instance, the following awk filter will pass all 32-bit writes that target | ||
| 140 | physical addresses in the range [0xfb73ce40, 0xfb800000[ | ||
| 141 | |||
| 142 | $ awk '/W 4 / { adr=strtonum($5); if (adr >= 0xfb73ce40 && | ||
| 143 | adr < 0xfb800000) print; }' | ||
| 144 | |||
| 145 | |||
| 146 | Tools for Developers | ||
| 147 | -------------------- | ||
| 148 | |||
| 149 | The user space tools include utilities for: | ||
| 150 | - replacing numeric addresses and values with hardware register names | ||
| 151 | - replaying MMIO logs, i.e., re-executing the recorded writes | ||
| 152 | |||
| 153 | |||
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 1d6de0d67f99..b28ace2be1a3 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug | |||
| @@ -180,12 +180,10 @@ config MMIOTRACE | |||
| 180 | help | 180 | help |
| 181 | Mmiotrace traces Memory Mapped I/O access and is meant for | 181 | Mmiotrace traces Memory Mapped I/O access and is meant for |
| 182 | debugging and reverse engineering. It is called from the ioremap | 182 | debugging and reverse engineering. It is called from the ioremap |
| 183 | implementation and works via page faults. A user space program is | 183 | implementation and works via page faults. Tracing is disabled by |
| 184 | required to collect the MMIO data from debugfs files. | 184 | default and can be enabled run-time. |
| 185 | Tracing is disabled by default and can be enabled from a debugfs | ||
| 186 | file. | ||
| 187 | 185 | ||
| 188 | See http://nouveau.freedesktop.org/wiki/MmioTrace | 186 | See Documentation/tracers/mmiotrace.txt. |
| 189 | If you are not helping to develop drivers, say N. | 187 | If you are not helping to develop drivers, say N. |
| 190 | 188 | ||
| 191 | config MMIOTRACE_TEST | 189 | config MMIOTRACE_TEST |
