2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
15 struct trace_buffer
*trace_buffer_allocate(u64 size
)
17 struct trace_buffer
*tb
;
19 if (size
< sizeof(*tb
)) {
20 fprintf(stderr
, "Error: trace buffer too small\n");
24 tb
= mmap(NULL
, size
, PROT_READ
| PROT_WRITE
,
25 MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
26 if (tb
== MAP_FAILED
) {
38 static bool trace_check_bounds(struct trace_buffer
*tb
, void *p
)
40 return p
< ((void *)tb
+ tb
->size
);
43 static bool trace_check_alloc(struct trace_buffer
*tb
, void *p
)
46 * If we ever overflowed don't allow any more input. This prevents us
47 * from dropping a large item and then later logging a small one. The
48 * buffer should just stop when overflow happened, not be patchy. If
49 * you're overflowing, make your buffer bigger.
54 if (!trace_check_bounds(tb
, p
)) {
62 static void *trace_alloc(struct trace_buffer
*tb
, int bytes
)
67 newtail
= tb
->tail
+ bytes
;
68 if (!trace_check_alloc(tb
, newtail
))
76 static struct trace_entry
*trace_alloc_entry(struct trace_buffer
*tb
, int payload_size
)
78 struct trace_entry
*e
;
80 e
= trace_alloc(tb
, sizeof(*e
) + payload_size
);
82 e
->length
= payload_size
;
87 int trace_log_reg(struct trace_buffer
*tb
, u64 reg
, u64 value
)
89 struct trace_entry
*e
;
92 e
= trace_alloc_entry(tb
, sizeof(reg
) + sizeof(value
));
96 e
->type
= TRACE_TYPE_REG
;
104 int trace_log_counter(struct trace_buffer
*tb
, u64 value
)
106 struct trace_entry
*e
;
109 e
= trace_alloc_entry(tb
, sizeof(value
));
113 e
->type
= TRACE_TYPE_COUNTER
;
120 int trace_log_string(struct trace_buffer
*tb
, char *str
)
122 struct trace_entry
*e
;
128 /* We NULL terminate to make printing easier */
129 e
= trace_alloc_entry(tb
, len
+ 1);
133 e
->type
= TRACE_TYPE_STRING
;
142 int trace_log_indent(struct trace_buffer
*tb
)
144 struct trace_entry
*e
;
146 e
= trace_alloc_entry(tb
, 0);
150 e
->type
= TRACE_TYPE_INDENT
;
155 int trace_log_outdent(struct trace_buffer
*tb
)
157 struct trace_entry
*e
;
159 e
= trace_alloc_entry(tb
, 0);
163 e
->type
= TRACE_TYPE_OUTDENT
;
168 static void trace_print_header(int seq
, int prefix
)
170 printf("%*s[%d]: ", prefix
, "", seq
);
173 static char *trace_decode_reg(int reg
)
176 case 769: return "SPRN_MMCR2"; break;
177 case 770: return "SPRN_MMCRA"; break;
178 case 779: return "SPRN_MMCR0"; break;
179 case 804: return "SPRN_EBBHR"; break;
180 case 805: return "SPRN_EBBRR"; break;
181 case 806: return "SPRN_BESCR"; break;
182 case 800: return "SPRN_BESCRS"; break;
183 case 801: return "SPRN_BESCRSU"; break;
184 case 802: return "SPRN_BESCRR"; break;
185 case 803: return "SPRN_BESCRRU"; break;
186 case 771: return "SPRN_PMC1"; break;
187 case 772: return "SPRN_PMC2"; break;
188 case 773: return "SPRN_PMC3"; break;
189 case 774: return "SPRN_PMC4"; break;
190 case 775: return "SPRN_PMC5"; break;
191 case 776: return "SPRN_PMC6"; break;
192 case 780: return "SPRN_SIAR"; break;
193 case 781: return "SPRN_SDAR"; break;
194 case 768: return "SPRN_SIER"; break;
200 static void trace_print_reg(struct trace_entry
*e
)
202 u64
*p
, *reg
, *value
;
209 name
= trace_decode_reg(*reg
);
211 printf("register %-10s = 0x%016llx\n", name
, *value
);
213 printf("register %lld = 0x%016llx\n", *reg
, *value
);
216 static void trace_print_counter(struct trace_entry
*e
)
220 value
= (u64
*)e
->data
;
221 printf("counter = %lld\n", *value
);
224 static void trace_print_string(struct trace_entry
*e
)
228 str
= (char *)e
->data
;
232 #define BASE_PREFIX 2
233 #define PREFIX_DELTA 8
235 static void trace_print_entry(struct trace_entry
*e
, int seq
, int *prefix
)
239 trace_print_header(seq
, *prefix
);
242 case TRACE_TYPE_COUNTER
:
243 trace_print_header(seq
, *prefix
);
244 trace_print_counter(e
);
246 case TRACE_TYPE_STRING
:
247 trace_print_header(seq
, *prefix
);
248 trace_print_string(e
);
250 case TRACE_TYPE_INDENT
:
251 trace_print_header(seq
, *prefix
);
253 *prefix
+= PREFIX_DELTA
;
255 case TRACE_TYPE_OUTDENT
:
256 *prefix
-= PREFIX_DELTA
;
257 if (*prefix
< BASE_PREFIX
)
258 *prefix
= BASE_PREFIX
;
259 trace_print_header(seq
, *prefix
);
263 trace_print_header(seq
, *prefix
);
264 printf("entry @ %p type %d\n", e
, e
->type
);
269 void trace_buffer_print(struct trace_buffer
*tb
)
271 struct trace_entry
*e
;
275 printf("Trace buffer dump:\n");
276 printf(" address %p \n", tb
);
277 printf(" tail %p\n", tb
->tail
);
278 printf(" size %llu\n", tb
->size
);
279 printf(" overflow %s\n", tb
->overflow
? "TRUE" : "false");
280 printf(" Content:\n");
285 prefix
= BASE_PREFIX
;
287 while (trace_check_bounds(tb
, p
) && p
< tb
->tail
) {
290 trace_print_entry(e
, i
, &prefix
);
293 p
= (void *)e
+ sizeof(*e
) + e
->length
;
297 void trace_print_location(struct trace_buffer
*tb
)
299 printf("Trace buffer 0x%llx bytes @ %p\n", tb
->size
, tb
);