1 // SPDX-License-Identifier: GPL-2.0-only
3 * intel_pt_log.c: Intel Processor Trace support
4 * Copyright (c) 2013-2014, Intel Corporation.
15 #include <linux/zalloc.h>
16 #include <linux/kernel.h>
18 #include "intel-pt-log.h"
19 #include "intel-pt-insn-decoder.h"
21 #include "intel-pt-pkt-decoder.h"
23 #define MAX_LOG_NAME 256
25 #define DFLT_BUF_SZ (16 * 1024)
36 static char log_name
[MAX_LOG_NAME
];
37 bool intel_pt_enable_logging
;
38 static bool intel_pt_dump_log_on_error
;
39 static unsigned int intel_pt_log_on_error_size
;
40 static struct log_buf log_buf
;
42 void *intel_pt_log_fp(void)
47 void intel_pt_log_enable(bool dump_log_on_error
, unsigned int log_on_error_size
)
49 intel_pt_enable_logging
= true;
50 intel_pt_dump_log_on_error
= dump_log_on_error
;
51 intel_pt_log_on_error_size
= log_on_error_size
;
54 void intel_pt_log_disable(void)
58 intel_pt_enable_logging
= false;
61 void intel_pt_log_set_name(const char *name
)
63 strncpy(log_name
, name
, MAX_LOG_NAME
- 5);
64 strcat(log_name
, ".log");
67 static void intel_pt_print_data(const unsigned char *buf
, int len
, uint64_t pos
,
72 for (i
= 0; i
< indent
; i
++)
75 fprintf(f
, " %08" PRIx64
": ", pos
);
76 for (i
= 0; i
< len
; i
++)
77 fprintf(f
, " %02x", buf
[i
]);
83 static void intel_pt_print_no_data(uint64_t pos
, int indent
)
87 for (i
= 0; i
< indent
; i
++)
90 fprintf(f
, " %08" PRIx64
": ", pos
);
91 for (i
= 0; i
< 16; i
++)
96 static ssize_t
log_buf__write(void *cookie
, const char *buf
, size_t size
)
98 struct log_buf
*b
= cookie
;
105 size_t space
= b
->buf_sz
- b
->head
;
106 size_t n
= min(space
, sz
);
108 memcpy(b
->buf
+ b
->head
, buf
, n
);
112 if (sz
&& b
->head
>= b
->buf_sz
) {
120 static int log_buf__close(void *cookie
)
122 struct log_buf
*b
= cookie
;
128 static FILE *log_buf__open(struct log_buf
*b
, FILE *backend
, unsigned int sz
)
130 cookie_io_functions_t fns
= {
131 .write
= log_buf__write
,
132 .close
= log_buf__close
,
136 memset(b
, 0, sizeof(*b
));
138 b
->buf
= malloc(b
->buf_sz
);
139 b
->backend
= backend
;
140 file
= fopencookie(b
, "a", fns
);
146 static bool remove_first_line(const char **p
, size_t *n
)
148 for (; *n
&& **p
!= '\n'; ++*p
, --*n
)
158 static void write_lines(const char *p
, size_t n
, FILE *fp
, bool *remove_first
)
161 *remove_first
= !remove_first_line(&p
, &n
);
165 static void log_buf__dump(struct log_buf
*b
)
167 bool remove_first
= false;
172 fflush(f
); /* Could update b->head and b->wrapped */
173 fprintf(b
->backend
, "Dumping debug log buffer\n");
176 write_lines(b
->buf
+ b
->head
, b
->buf_sz
- b
->head
, b
->backend
, &remove_first
);
178 write_lines(b
->buf
, b
->head
, b
->backend
, &remove_first
);
179 fprintf(b
->backend
, "End of debug log buffer dump\n");
185 void intel_pt_log_dump_buf(void)
187 log_buf__dump(&log_buf
);
190 static int intel_pt_log_open(void)
192 if (!intel_pt_enable_logging
)
199 f
= fopen(log_name
, "w+");
202 if (f
&& intel_pt_dump_log_on_error
)
203 f
= log_buf__open(&log_buf
, f
, intel_pt_log_on_error_size
);
205 intel_pt_enable_logging
= false;
212 void __intel_pt_log_packet(const struct intel_pt_pkt
*packet
, int pkt_len
,
213 uint64_t pos
, const unsigned char *buf
)
215 char desc
[INTEL_PT_PKT_DESC_MAX
];
217 if (intel_pt_log_open())
220 intel_pt_print_data(buf
, pkt_len
, pos
, 0);
221 intel_pt_pkt_desc(packet
, desc
, INTEL_PT_PKT_DESC_MAX
);
222 fprintf(f
, "%s\n", desc
);
225 void __intel_pt_log_insn(struct intel_pt_insn
*intel_pt_insn
, uint64_t ip
)
227 char desc
[INTEL_PT_INSN_DESC_MAX
];
228 size_t len
= intel_pt_insn
->length
;
230 if (intel_pt_log_open())
233 if (len
> INTEL_PT_INSN_BUF_SZ
)
234 len
= INTEL_PT_INSN_BUF_SZ
;
235 intel_pt_print_data(intel_pt_insn
->buf
, len
, ip
, 8);
236 if (intel_pt_insn_desc(intel_pt_insn
, desc
, INTEL_PT_INSN_DESC_MAX
) > 0)
237 fprintf(f
, "%s\n", desc
);
239 fprintf(f
, "Bad instruction!\n");
242 void __intel_pt_log_insn_no_data(struct intel_pt_insn
*intel_pt_insn
,
245 char desc
[INTEL_PT_INSN_DESC_MAX
];
247 if (intel_pt_log_open())
250 intel_pt_print_no_data(ip
, 8);
251 if (intel_pt_insn_desc(intel_pt_insn
, desc
, INTEL_PT_INSN_DESC_MAX
) > 0)
252 fprintf(f
, "%s\n", desc
);
254 fprintf(f
, "Bad instruction!\n");
257 void __intel_pt_log(const char *fmt
, ...)
261 if (intel_pt_log_open())
265 vfprintf(f
, fmt
, args
);