@@ -227,6 +227,16 @@ int htm_dump(struct pdbg_target *target, uint64_t size, char *filename)
return htm->dump(htm, 0, filename);
}
+int htm_record(struct pdbg_target *target, char *filename)
+{
+ struct htm *htm = check_and_convert(target);
+
+ if (!htm || !filename)
+ return -1;
+
+ return htm->record(htm, filename);
+}
+
static int get_status(struct htm *htm, struct htm_status *status)
{
uint64_t val;
@@ -825,6 +835,26 @@ static uint64_t htm_trace_size(struct htm_status *status)
return size << 20;
}
+static bool htm_complete(struct htm_status *status)
+{
+ return (status->state == COMPLETE);
+}
+
+static int htm_wait_complete(struct htm *htm)
+{
+ struct htm_status status;
+
+ while (1) {
+ if (HTM_ERR(get_status(htm, &status)))
+ return -1;
+ PR_DEBUG("loop curr:0x%016" PRIx64 "\n", status.mem_last);
+ if (htm_complete(&status))
+ break;
+ usleep(100000);
+ }
+ return 0;
+}
+
static int do_htm_status(struct htm *htm)
{
struct htm_status status;
@@ -976,6 +1006,24 @@ static int do_htm_dump(struct htm *htm, uint64_t size, char *filename)
return 1;
}
+static int do_htm_record(struct htm *htm, char *filename)
+{
+ if (do_htm_start(htm) < 0)
+ return -1;
+
+ if (htm_wait_complete(htm))
+ return -1;
+
+ if (do_htm_stop(htm) < 0)
+ return -1;
+
+ if (do_htm_dump(htm, 0, filename) < 0)
+ return -1;
+
+
+ return 1;
+}
+
static bool is_debugfs_memtrace_ok(void)
{
return access(DEBUGFS_MEMTRACE, F_OK) == 0;
@@ -1018,6 +1066,7 @@ static struct htm nhtm = {
},
.start = do_htm_start,
.stop = do_htm_stop,
+ .record = do_htm_record,
.status = do_htm_status,
.dump = do_htm_dump,
};
@@ -1032,6 +1081,7 @@ static struct htm chtm = {
},
.start = do_htm_start,
.stop = do_htm_stop,
+ .record = do_htm_record,
.status = do_htm_status,
.dump = do_htm_dump,
};
@@ -166,6 +166,7 @@ int htm_start(struct pdbg_target *target);
int htm_stop(struct pdbg_target *target);
int htm_status(struct pdbg_target *target);
int htm_dump(struct pdbg_target *target, uint64_t size, char *filename);
+int htm_record(struct pdbg_target *target, char *filename);
int adu_getmem(struct pdbg_target *target, uint64_t addr, uint8_t *ouput, uint64_t size);
int adu_putmem(struct pdbg_target *target, uint64_t addr, uint8_t *input, uint64_t size);
@@ -95,6 +95,7 @@ struct htm {
int (*stop)(struct htm *);
int (*status)(struct htm *);
int (*dump)(struct htm *, uint64_t, char *);
+ int (*record)(struct htm *, char *);
};
#define target_to_htm(x) container_of(x, struct htm, target)
@@ -177,6 +177,37 @@ static int run_dump(enum htm_type type)
return rc;
}
+static int run_record(enum htm_type type)
+{
+ struct pdbg_target *target;
+ char *filename;
+ int rc = 0;
+
+ pdbg_for_each_class_target(HTM_ENUM_TO_STRING(type), target) {
+ if (!target_selected(target))
+ continue;
+ pdbg_target_probe(target);
+ if (target_is_disabled(target))
+ continue;
+
+ filename = get_htm_dump_filename(target);
+ if (!filename)
+ return 0;
+
+ /* size = 0 will dump everything */
+ printf("Recording HTM@");
+ print_htm_address(type, target);
+ if (htm_record(target, filename) != 1) {
+ printf("Couldn't record HTM@");
+ print_htm_address(type, target);
+ }
+ rc++;
+ free(filename);
+ }
+
+ return rc;
+}
+
static struct {
const char *name;
const char *args;
@@ -187,6 +218,7 @@ static struct {
{ "stop", "", "Stop %s HTM", &run_stop },
{ "status", "", "Get %s HTM status", &run_status },
{ "dump", "", "Dump %s HTM buffer to file", &run_dump },
+ { "record", "", "Start, wait & dump %s HTM", &run_record },
};
static void print_usage(enum htm_type type)
This starts the trace, waits for it to complete (ie fill the buffer), then stops the trace and dumps out the file. Signed-off-by: Michael Neuling <mikey@neuling.org> --- libpdbg/htm.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ libpdbg/libpdbg.h | 1 + libpdbg/target.h | 1 + src/htm.c | 32 ++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+)