diff --git a/panda/include/panda/callbacks/cb-defs.h b/panda/include/panda/callbacks/cb-defs.h index 6170f6d699f..a2af4057a30 100644 --- a/panda/include/panda/callbacks/cb-defs.h +++ b/panda/include/panda/callbacks/cb-defs.h @@ -57,6 +57,7 @@ typedef enum panda_cb_type { PANDA_CB_HD_WRITE, // Each HDD write PANDA_CB_GUEST_HYPERCALL, // Hypercall from the guest (e.g. CPUID) PANDA_CB_MONITOR, // Monitor callback + PANDA_CB_QMP, // QMP callback PANDA_CB_CPU_RESTORE_STATE, // In cpu_restore_state() (fault/exception) PANDA_CB_BEFORE_LOADVM, // at start of replay, before loadvm PANDA_CB_ASID_CHANGED, // When CPU asid (address space identifier) changes @@ -592,6 +593,24 @@ typedef union panda_cb { */ int (*monitor)(Monitor *mon, const char *cmd); + /* Callback ID: PANDA_CB_QMP + + qmp: + Called when someone sends an unhandled QMP command + + Arguments: + QmpCommand *command: a pointer to the QMP command + QDict *dict: a pointer to the QDict containing the command + QObject **ret: a pointer to the return value + Error **errp: a pointer to the error value + + Helper call location: TBA + + Return value: + bool: true IFF the command was handled by the plugin + */ + bool (*qmp)(const char *command, QDict *dict, QObject **ret, Error **errp); + /* Callback ID: PANDA_CB_CPU_RESTORE_STATE @@ -1544,6 +1563,24 @@ typedef union panda_cb_with_context { */ int (*monitor)(void* context, Monitor *mon, const char *cmd); + /* Callback ID: PANDA_CB_QMP + + qmp: + Called when someone sends an unhandled QMP command + + Arguments: + QmpCommand *command: a pointer to the QMP command + QDict *dict: a pointer to the QDict containing the command + QObject **ret: a pointer to the return value + Error **errp: a pointer to the error value + + Helper call location: TBA + + Return value: + bool: true IFF the command was handled by the plugin + */ + bool (*qmp)(void* context, const char *command, QDict *dict, QObject **ret, Error **errp); + /* Callback ID: PANDA_CB_CPU_RESTORE_STATE diff --git a/panda/include/panda/callbacks/cb-support.h b/panda/include/panda/callbacks/cb-support.h index af894b7f4d5..d05e915c24a 100644 --- a/panda/include/panda/callbacks/cb-support.h +++ b/panda/include/panda/callbacks/cb-support.h @@ -75,6 +75,7 @@ bool panda_callbacks_after_find_fast(CPUState *cpu, TranslationBlock *tb, bool b int panda_callbacks_insn_exec(CPUState *env, target_ptr_t pc); int panda_callbacks_after_insn_exec(CPUState *env, target_ptr_t pc); int panda_callbacks_monitor(Monitor *mon, const char *cmd); +bool panda_callbacks_qmp(const char *command, QDict *dict, QObject **ret, Error **errp); int panda_callbacks_before_loadvm(void); void panda_callbacks_replay_hd_transfer(CPUState *env, uint32_t type, target_ptr_t src_addr, target_ptr_t dest_addr, size_t num_bytes); void panda_callbacks_after_machine_init(CPUState *env); diff --git a/panda/include/panda/callbacks/cb-trampolines.h b/panda/include/panda/callbacks/cb-trampolines.h index f13ca5be3a3..5db262aadb3 100644 --- a/panda/include/panda/callbacks/cb-trampolines.h +++ b/panda/include/panda/callbacks/cb-trampolines.h @@ -19,6 +19,7 @@ void panda_cb_trampoline_phys_mem_after_write(void* context, CPUState *env, targ int panda_cb_trampoline_insn_exec(void* context, CPUState *env, target_ptr_t pc); int panda_cb_trampoline_after_insn_exec(void* context, CPUState *env, target_ptr_t pc); int panda_cb_trampoline_monitor(void* context, Monitor *mon, const char *cmd); +bool panda_cb_trampoline_qmp(void* context, const char *command, QDict *dict, QObject **ret, Error **errp); //int panda_cb_trampoline_before_loadvm(void* context); void panda_cb_trampoline_replay_hd_transfer(void* context, CPUState *env, uint32_t type, target_ptr_t src_addr, target_ptr_t dest_addr, size_t num_bytes); void panda_cb_trampoline_after_machine_init(void* context, CPUState *env); diff --git a/panda/src/callbacks.c b/panda/src/callbacks.c index 787e71fe3f7..73ec90c1bb0 100644 --- a/panda/src/callbacks.c +++ b/panda/src/callbacks.c @@ -474,6 +474,7 @@ panda_cb_with_context panda_get_cb_trampoline(panda_cb_type type) { CASE_CB_TRAMPOLINE(HD_WRITE,hd_write) CASE_CB_TRAMPOLINE(GUEST_HYPERCALL,guest_hypercall) CASE_CB_TRAMPOLINE(MONITOR,monitor) + CASE_CB_TRAMPOLINE(QMP,qmp) CASE_CB_TRAMPOLINE(CPU_RESTORE_STATE,cpu_restore_state) //CASE_CB_TRAMPOLINE(BEFORE_LOADVM,before_loadvm) diff --git a/panda/src/cb-support.c b/panda/src/cb-support.c index beb9517ca73..5c4d3afef5b 100644 --- a/panda/src/cb-support.c +++ b/panda/src/cb-support.c @@ -10,6 +10,9 @@ #include "exec/cpu-common.h" #include "exec/ram_addr.h" +// For QDict +#include "qapi/qmp/qdict.h" + // For each callback, use MAKE_CALLBACK or MAKE_REPLAY_ONLY_CALLBACK as defined in #include "panda/callbacks/cb-macros.h" #include "panda/callbacks/cb-trampolines.h" @@ -101,7 +104,9 @@ void panda_cb_trampoline_start_block_exec(void* context, CPUState *cpu, Translat // these aren't used MAKE_CALLBACK(void, HD_READ, hd_read, CPUState*, env); MAKE_CALLBACK(void, HD_WRITE, hd_write, CPUState*, env); + MAKE_CALLBACK(int, MONITOR, monitor, Monitor*, mon, const char*, cmd); +MAKE_CALLBACK(bool, QMP, qmp, const char*, cmd, QDict*, dict, QObject**, ret, Error**, errp); // Helper - get a physical address static inline hwaddr get_paddr(CPUState *cpu, target_ptr_t addr, void *ram_ptr) { diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index dc502129d80..0e38b9d182f 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -19,6 +19,8 @@ #include "qapi/qmp/qjson.h" #include "qapi-types.h" #include "qapi/qmp/qerror.h" +//#include "panda/callbacks/cb-support.h" +extern bool panda_callbacks_qmp(const char *command, QDict *dict, QObject **ret, Error **errp); static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) { @@ -83,24 +85,32 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, command = qdict_get_str(dict, "execute"); cmd = qmp_find_command(cmds, command); + + if (!qdict_haskey(dict, "arguments")) { + args = qdict_new(); + } else { + args = qdict_get_qdict(dict, "arguments"); + QINCREF(args); + } + if (cmd == NULL) { + // Check if this is a PANDA supported command and dispatch if so we're done + if (panda_callbacks_qmp(command, dict, &ret, errp)) { + // XXX callback needs to populate ret, might be hard + return ret; + } + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found", command); return NULL; } + if (!cmd->enabled) { error_setg(errp, "The command %s has been disabled for this instance", command); return NULL; } - if (!qdict_haskey(dict, "arguments")) { - args = qdict_new(); - } else { - args = qdict_get_qdict(dict, "arguments"); - QINCREF(args); - } - cmd->fn(args, &ret, &local_err); if (local_err) { error_propagate(errp, local_err);