From 9c13fb5fd365c6b4023cd7f0d20912402b8dbfa0 Mon Sep 17 00:00:00 2001 From: shinsakukataoka Date: Wed, 10 Jul 2024 13:38:11 +0000 Subject: [PATCH 1/2] Added periodic checkpoint functionality --- libqflex/libqflex-hmp-cmds.c | 69 ++++++++++++++++++++++++++++++++++ libqflex/libqflex.h | 2 + libqflex/plugins/trace/trace.c | 19 ++++++++-- 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/libqflex/libqflex-hmp-cmds.c b/libqflex/libqflex-hmp-cmds.c index 623cfc7..e41f001 100644 --- a/libqflex/libqflex-hmp-cmds.c +++ b/libqflex/libqflex-hmp-cmds.c @@ -12,6 +12,14 @@ #include "libqflex-module.h" #include "libqflex.h" +// add these? + +#include "middleware/libqflex/plugins/trace/trace.h" +#include "libqflex-module.h" +#include "libqflex.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qobject.h" + void hmp_flexus_save_measure(Monitor *mon, const QDict *qdict) { if (! qemu_libqflex_state.is_configured) @@ -74,4 +82,65 @@ hmp_flexus_load_ckpt(Monitor* mon, const QDict* qdict) libqflex_load_ckpt(folder_name); hmp_handle_error(mon, err); +} + +// Functions to call periodic checkpoint + +// Structure for Monitor and QDict +typedef struct { + Monitor *mon; + const QDict *qdict; + int checkpoint_interval; + int sample_size; +} FlexusCkptData; + +static QEMUTimer *flexus_ckpt_timer = NULL; +static void flexus_ckpt_timer_cb(void *opaque); // Timer +static int last_instruction_count = 0; + +static void flexus_ckpt_timer_cb(void *opaque) { + FlexusCkptData *data = (FlexusCkptData *)opaque; + int current_instruction_count = instruction_count; + int instruction_diff = current_instruction_count - last_instruction_count; + + // Cannot trigger the checkpoint generation for every instruction, + // so approximate this by checking the instruction count by every given second. + // Currently it checks the instruction count every 10000 ms but this is adjustable. + if (instruction_diff >= data->checkpoint_interval && current_instruction_count <= data->sample_size * data->checkpoint_interval + 0.5 * data->checkpoint_interval) { + // keep generating checkpoint until it reaches the target sample_size + hmp_flexus_save_ckpt(data->mon, data->qdict); + last_instruction_count = current_instruction_count; + } + + // Reschedule the timer to run again in 10 seconds. + timer_mod(flexus_ckpt_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 10000); +} + +void hmp_flexus_start_periodic_ckpt(Monitor *mon, const QDict *qdict) { + static const int DEFAULT_CHECKPOINT_INTERVAL = 1000000; + static const int DEFAULT_SAMPLE_SIZE = 30; + + if (!qemu_libqflex_state.is_configured) { + monitor_printf(mon, "qflex seems to not be initialized, periodic checkpoint saving makes no sense\n"); + return; + } + + if (flexus_ckpt_timer) { + timer_del(flexus_ckpt_timer); + flexus_ckpt_timer = NULL; // Reset the timer pointer + } + + FlexusCkptData *data = g_malloc(sizeof(FlexusCkptData)); + data->mon = mon; + data->qdict = qdict; + + // Retrieve optional arguments for checkpoint_interval and sample_size + data->checkpoint_interval = qdict_haskey(qdict, "checkpoint_interval") ? qdict_get_int(qdict, "checkpoint_interval") : DEFAULT_CHECKPOINT_INTERVAL; + data->sample_size = qdict_haskey(qdict, "sample_size") ? qdict_get_int(qdict, "sample_size") : DEFAULT_SAMPLE_SIZE; + + // Initialize the last_instruction_count + last_instruction_count = instruction_count; + + flexus_ckpt_timer = timer_new_ms(QEMU_CLOCK_REALTIME, flexus_ckpt_timer_cb, data); + timer_mod(flexus_ckpt_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 10000); // 10 seconds } \ No newline at end of file diff --git a/libqflex/libqflex.h b/libqflex/libqflex.h index 181f37c..ef89742 100644 --- a/libqflex/libqflex.h +++ b/libqflex/libqflex.h @@ -6,6 +6,8 @@ #include "libqflex-legacy-api.h" +extern int instruction_count; + extern struct libqflex_state_t qemu_libqflex_state; /** diff --git a/libqflex/plugins/trace/trace.c b/libqflex/plugins/trace/trace.c index 88efd58..cf06e26 100644 --- a/libqflex/plugins/trace/trace.c +++ b/libqflex/plugins/trace/trace.c @@ -16,6 +16,10 @@ #include "middleware/libqflex/libqflex-legacy-api.h" #include "trace.h" +// Add this + +#include "middleware/libqflex/libqflex.h" + // Ensure that the plugin run only against the version // it was compiled for @@ -46,9 +50,15 @@ trans_free(gpointer data) * @param vaddr OPage virtual address. * @param userdata Generic translation info. */ + +int instruction_count = 0; + static void dispatch_memory_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info, uint64_t vaddr, void* userdata) { + if (vcpu_index == 0) { + instruction_count++; + } trace_insn_t* insn = (trace_insn_t*) userdata; @@ -67,10 +77,8 @@ dispatch_memory_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info, uint // ───────────────────────────────────────────────────────────────────── - struct qemu_plugin_hwaddr* hwaddr = qemu_plugin_get_hwaddr(info, vaddr); - memory_transaction_t tr = {0}; tr.io = (hwaddr && qemu_plugin_hwaddr_is_io(hwaddr)); @@ -85,7 +93,6 @@ dispatch_memory_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info, uint tr.s.atomic = mem_info.is_atomic; tr.s.type = mem_info.is_store ? QEMU_Trans_Store : QEMU_Trans_Load; - flexus_api.trace_mem(vcpu_index, &tr); } @@ -101,9 +108,12 @@ dispatch_memory_access(unsigned int vcpu_index, qemu_plugin_meminfo_t info, uint static void dispatch_instruction(unsigned int vcpu_index, void* userdata) { + if (vcpu_index == 0) { + instruction_count++; + } trace_insn_t* insn = (trace_insn_t*) userdata; - g_assert(insn->target_pc_va); + //g_assert(insn->target_pc_va); MemTxAttrs attrs; branch_type_t br_type; @@ -124,6 +134,7 @@ dispatch_instruction(unsigned int vcpu_index, void* userdata) flexus_api.trace_mem(vcpu_index, &tr); } + /** * Get called on every instruction translation */ From a74a82da3448b6f46f0a7865093bfe4e8c88c8a2 Mon Sep 17 00:00:00 2001 From: shinsakukataoka Date: Mon, 22 Jul 2024 08:04:51 +0000 Subject: [PATCH 2/2] added readme --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d18b6fc --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +Add this line to qflex/qemu/hmp-commands.hx + +``` +ERST + { + .name = "flexus-start-periodic-ckpt", + .args_type = "dirname:F? checkpoint_interval:i? sample_size:i?", + .params = "dirname checkpoint_interval sample_size", + .help = "Start periodic checkpoint generation with optional checkpoint_interval and sample_size", + .cmd = hmp_flexus_start_periodic_ckpt + }, +SRST + ``flexus-start-periodic-ckpt`` *tag* + Qflex specific, save uArch state as checkpoints on the disk. + The tag is a directory the checkpoint will be save to. +```