|
|
|
@ -43,6 +43,8 @@ typedef struct { |
|
|
|
|
|
|
|
static GMutex lock; |
|
|
|
static GHashTable *devices; |
|
|
|
static struct qemu_plugin_scoreboard *source_pc_scoreboard; |
|
|
|
static qemu_plugin_u64 source_pc; |
|
|
|
|
|
|
|
/* track the access pattern to a piece of HW */ |
|
|
|
static bool pattern; |
|
|
|
@ -159,7 +161,7 @@ static DeviceCounts *new_count(const char *name, uint64_t base) |
|
|
|
count->name = name; |
|
|
|
count->base = base; |
|
|
|
if (pattern || source) { |
|
|
|
count->detail = g_hash_table_new(NULL, NULL); |
|
|
|
count->detail = g_hash_table_new(g_int64_hash, g_int64_equal); |
|
|
|
} |
|
|
|
g_hash_table_insert(devices, (gpointer) name, count); |
|
|
|
return count; |
|
|
|
@ -169,7 +171,7 @@ static IOLocationCounts *new_location(GHashTable *table, uint64_t off_or_pc) |
|
|
|
{ |
|
|
|
IOLocationCounts *loc = g_new0(IOLocationCounts, 1); |
|
|
|
loc->off_or_pc = off_or_pc; |
|
|
|
g_hash_table_insert(table, (gpointer) off_or_pc, loc); |
|
|
|
g_hash_table_insert(table, &loc->off_or_pc, loc); |
|
|
|
return loc; |
|
|
|
} |
|
|
|
|
|
|
|
@ -224,12 +226,12 @@ static void vcpu_haddr(unsigned int cpu_index, qemu_plugin_meminfo_t meminfo, |
|
|
|
|
|
|
|
/* either track offsets or source of access */ |
|
|
|
if (source) { |
|
|
|
off = (uint64_t) udata; |
|
|
|
off = qemu_plugin_u64_get(source_pc, cpu_index); |
|
|
|
} |
|
|
|
|
|
|
|
if (pattern || source) { |
|
|
|
IOLocationCounts *io_count = g_hash_table_lookup(counts->detail, |
|
|
|
(gpointer) off); |
|
|
|
&off); |
|
|
|
if (!io_count) { |
|
|
|
io_count = new_location(counts->detail, off); |
|
|
|
} |
|
|
|
@ -247,10 +249,14 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) |
|
|
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
|
|
struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i); |
|
|
|
gpointer udata = (gpointer) (source ? qemu_plugin_insn_vaddr(insn) : 0); |
|
|
|
if (source) { |
|
|
|
uint64_t pc = qemu_plugin_insn_vaddr(insn); |
|
|
|
qemu_plugin_register_vcpu_mem_inline_per_vcpu( |
|
|
|
insn, rw, QEMU_PLUGIN_INLINE_STORE_U64, |
|
|
|
source_pc, pc); |
|
|
|
} |
|
|
|
qemu_plugin_register_vcpu_mem_cb(insn, vcpu_haddr, |
|
|
|
QEMU_PLUGIN_CB_NO_REGS, |
|
|
|
rw, udata); |
|
|
|
QEMU_PLUGIN_CB_NO_REGS, rw, NULL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -306,10 +312,9 @@ int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
/* Just warn about overflow */ |
|
|
|
if (info->system.smp_vcpus > 64 || |
|
|
|
info->system.max_vcpus > 64) { |
|
|
|
fprintf(stderr, "hwprofile: can only track up to 64 CPUs\n"); |
|
|
|
if (source) { |
|
|
|
source_pc_scoreboard = qemu_plugin_scoreboard_new(sizeof(uint64_t)); |
|
|
|
source_pc = qemu_plugin_scoreboard_u64(source_pc_scoreboard); |
|
|
|
} |
|
|
|
|
|
|
|
plugin_init(); |
|
|
|
|