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