11 #include <xen/time_travel.h>
16 static void bts_dump(
const char *infile,
char *outfile);
17 static int bts_dump_branch(
struct ttd_rec *rec, FILE *fd);
33 fprintf(stderr,
"Usage: bts-extract [-d] [-S val[:radius]] [-E val[:radius]] [-o outfile] xentt_event_log\n");
34 fprintf(stderr,
" Extracts BTS records from a XenTT replay log,\n");
35 fprintf(stderr,
" dumping them to stdout or a logfile (-o). Optionally\n");
36 fprintf(stderr,
" takes start and end branch counter values to limit\n");
37 fprintf(stderr,
" the range of the dumped records.\n");
38 fprintf(stderr,
" -d Turn on debugging.\n");
39 fprintf(stderr,
" -x Extended format, include brctr.\n");
40 fprintf(stderr,
" -S val[:radius] Starting brctr value and optional radius\n");
41 fprintf(stderr,
" -E val[:radius] Ending brctr value and optional radius\n");
42 fprintf(stderr,
" -o outfile Output file (stdout is default)\n");
47 get_brctr(
char *arg,
struct brctr_val *val)
49 char *bp = index(arg,
':');
53 val->
radius = strtoull(&bp[1], NULL, 0);
55 val->
value = strtoull(arg, NULL, 0);
79 int main(
int argc,
char **argv)
84 while ((ch = getopt(argc, argv,
"dxS:E:o:")) != -1) {
93 if (get_brctr(
optarg, &startat)) {
94 fprintf(stderr,
"invalid brctr value %s\n",
optarg);
99 if (get_brctr(
optarg, &endat)) {
100 fprintf(stderr,
"invalid brctr value %s\n",
optarg);
117 bts_dump(*argv, outfile);
122 static uint64_t curbrctr[
NCPU];
124 static void bts_dump(
const char *fname,
char *outfile)
127 unsigned long nrec, nbtsrec;
128 uint64_t lofound = UINT64_MAX, hifound = 0;
131 fd = fopen(fname,
"r");
133 fprintf(stderr,
"Could not open XenTT log\n");
138 ofd = fopen(outfile,
"w");
140 fprintf(stderr,
"Could not open output file %s\n", outfile);
147 fprintf(stderr,
"Dumping BTS records from %s", fname);
149 fprintf(stderr,
" in range [%llu-",
loval);
150 if (
hival == UINT64_MAX)
151 fprintf(stderr,
"end]");
153 fprintf(stderr,
"%llu]",
hival);
156 fprintf(stderr,
" in extended format");
157 fprintf(stderr,
" ...\n");
166 fwrite(&_rec,
sizeof(_rec), 1, ofd);
170 while ((rec = xentt_readlog(fd)) != 0) {
173 curbrctr[rec->vcpu_id] = rec->cpu_state.brctr_virt;
175 switch (rec->event.event) {
176 case TTD_HW_BRANCHES:
177 case TTD_HW_BRANCHES_64:
178 if (bts_dump_branch(rec, ofd))
181 if (rec->cpu_state.brctr_virt < lofound)
182 lofound = rec->cpu_state.brctr_virt;
183 if (rec->cpu_state.brctr_virt > hifound)
184 hifound = rec->cpu_state.brctr_virt;
187 nbtsrec += rec->data_len /
sizeof(
struct bts_rec);
198 fprintf(stderr,
"Found %lu log records ", nrec);
200 fprintf(stderr,
"with range [%llu-%llu] ", lofound, hifound);
202 fprintf(stderr,
"containing %lu BTS records", nbtsrec);
203 fprintf(stderr,
"\n");
207 static int bts_dump_branch(
struct ttd_rec *rec, FILE *ofd)
211 assert(rec->event.event == TTD_HW_BRANCHES ||
212 rec->event.event == TTD_HW_BRANCHES_64);
215 brctr = rec->cpu_state.brctr_virt;
217 int nrec = rec->data_len /
sizeof(
struct bts_rec);
218 fprintf(stderr,
"0x%08lx/%012llu: found %d records\n",
219 rec->cpu_state.ip, brctr, nrec);
228 struct bts_rec *erec = (
struct bts_rec *)((
void *)rec->data + rec->data_len);
230 while (brec < erec) {
231 brec->
format = curbrctr[rec->vcpu_id];
234 curbrctr[rec->vcpu_id]++;
241 if (fwrite(rec->data, rec->data_len, 1, ofd) == 1)
243 fprintf(stderr,
"error writing record\n");