1# Intel Processor Trace driver
2
3See Chapter 36 of the Intel Architecture Software Developer's Manual.
4
5## Trace modes
6
7There are two modes of tracing:
8
9- per cpu
10- specified threads (not implemented yet)
11
12Only one may be active at a time.
13
14### Per CPU tracing
15
16In this mode of operation each cpu is traced, regardless of what is
17running on the cpu, except as can be controlled by PT configuration MSRs
18(e.g., cr3 filtering, kernel/user, address filtering).
19
20### Specified thread tracing
21
22In this mode of operation individual threads are traced, even as they
23migrate from CPU to CPU. This is achieved via the PT state save/restore
24capabilities of the XSAVES and XRSTORS instructions.
25
26Filtering control (e.g., cr3, user/kernel) is not available in this mode.
27Address filtering is possible, but is still TODO.
28
29## IOCTLs
30
31Several ioctls are provided to control tracing.
32
33### *ioctl_ipt_alloc_trace*
34
35```
36ssize_t ioctl_ipt_alloc_trace(int fd, const ioctl_ipt_trace_config_t* config);
37```
38
39Request the kernel allocate the needed internal data structures for
40managing IPT.
41
42Returns zero on success or a negative error code.
43
44### *ioctl_ipt_free_trace*
45
46```
47ssize_t ioctl_ipt_free_trace(int fd);
48```
49
50Request the kernel free all internal data structures for managing IPT.
51
52Returns zero on success or a negative error code.
53
54### *ioctl_ipt_get_trace_config*
55
56```
57ssize_t ioctl_ipt_get_trace_config(int fd,
58                                   const uint32_t* descriptor,
59                                   ioctl_ipt_trace_config_t* out_config);
60```
61
62Return the trace configuration.
63
64Returns *sizeof(\*out_config)* on success or a negative error code.
65
66### *ioctl_ipt_alloc_buffer*
67
68```
69ssize_t ioctl_ipt_alloc_buffer(int fd,
70                               const ioctl_ipt_buffer_config_t* config,
71                               uint32_t* out_descriptor);
72```
73
74Allocate an IPT buffer defined by |config| and return its buffer descriptor
75in *|\*out_descriptor|*.
76
77The descriptor is just an integer to identify the buffer.
78When tracing in cpu mode the descriptor is the number of the cpu
79that the buffer will be assigned to.
80
81Returns *sizeof(\*out_descriptor)* on success or a negative error code.
82
83### *ioctl_ipt_get_buffer_config*
84
85```
86ssize_t ioctl_ipt_get_buffer_config(int fd,
87                                    const uint32_t* descriptor,
88                                    ioctl_ipt_buffer_config_t* out_config);
89```
90
91Return the trace configuration.
92
93Returns *sizeof(\*out_config)* on success or a negative error code.
94
95### *ioctl_ipt_get_buffer_info*
96
97```
98ssize_t ioctl_ipt_get_buffer_info(int fd,
99                                  const uint32_t* descriptor,
100                                  ioctl_ipt_buffer_info_t* out_info);
101```
102
103Return info of the resulting trace of the specified buffer.
104Currently this is the place in the buffer where tracing stopped,
105treating the set of buffers as one large virtual buffer.
106If not using circular buffers then this is the amount of data captured.
107If using circular buffers then this is where tracing stopped.
108
109Returns *sizeof(\*out_data)* on success or a negative error code.
110
111### *ioctl_ipt_get_chunk_handle*
112
113```
114ssize_t ioctl_ipt_get_chunk_handle(int fd,
115                                   const ioctl_ipt_chunk_handle_req_t* req,
116                                   zx_handle_t* out_handle);
117```
118
119Return the handle of the requested VMO with buffer data.
120IPT buffers can be spread out over multiple VMOs as specified when the
121buffer was configured. This call returns the handle of one of them.
122Multiple calls are required to fetch the handle for each VMO.
123
124Returns *sizeof(\*out_handle)* on success or a negative error code.
125
126### *ioctl_ipt_free_buffer*
127
128```
129ssize_t ioctl_ipt_free_buffer(int fd,
130                              const uint32_t* descriptor);
131```
132
133Free the specified buffer and all associated VMOs.
134The caller still needs to free its own handles of the VMOs.
135
136Returns zero on success or a negative error code.
137
138### *ioctl_ipt_start*
139
140```
141ssize_t ioctl_ipt_start(int fd);
142```
143
144Begin tracing.
145One buffer must have already been allocated for each cpu
146with *ioctl_ipt_alloc_buffer*.
147
148Returns zero on success or a negative error code.
149
150### *ioctl_ipt_stop*
151
152```
153ssize_t ioctl_ipt_stop(int fd);
154```
155
156Stop tracing.
157
158Internally, status of the tracing of each cpu is collected for later
159retrieval with *ioctl_ipt_get_buffer_info()*.
160
161Returns zero on success or a negative error code.
162
163## Usage
164
165Here's a sketch of typical usage when tracing in cpu mode.
166
1671) *ioctl_ipt_alloc_trace(IPT_MODE_CPUS, num_cpus)*
1682) allocate buffers for each cpu
1693) *ioctl_ipt_start()*
1704) launch program one wishes to trace
1715) *ioctl_ipt_stop()*
1726) fetch buffer data for each cpu
1737) fetch handles for each vmo in each buffer, and save data
1748) *ioctl_ipt_free_trace()* [this will free each buffer as well]
1759) post-process
176
177## Notes
178
179- We currently only support Table of Physical Addresses mode so that
180we can also support stop-on-full behavior in addition to wrap-around.
181
182- Each cpu/thread has the same size trace buffer.
183
184- While it's possible to allocate and configure buffers outside of the driver,
185this is not done so that we have control over their contents. ToPA buffers
186must have specific contents or Bad Things can happen.
187
188## TODOs (beyond those in the source)
189
190- support tracing individual threads using xsaves
191
192- handle driver crashes
193  - need to turn off tracing
194  - need to keep buffer/table vmos alive until tracing is off
195