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");