mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
monitor: minimal conversion of monitors to QOM
This introduces abstract QOM type "monitor", with concrete subtypes "monitor-hmp" and "monitor-qmp". This is the bare minimum conversion of just the type declarations and replacing g_new/g_free with object_new/object_unref. Command line option "-monitor" now creates a "monitor-hmp" object "/objects/compat_monitorNNN" in addition to the character device "/chardevs/compat_monitorNNN". NNN counts up from zero. Exception: "-monitor chardev:ID" creates a "monitor-hmp" object "/objects/ID", and does not create a character device. "-qmp" and "-qmp-pretty" work the same, except they create a "monitor-qmp" object. "-mon" now creates either a "monitor-hmp" or "monitor-qmp" object "/objects/ID" if the option argument provides an ID, else "/objects/compat_monitorNNN". "-gdbstub" and "-serial mon:..." now create a "monitor-hmp" object "/objects/compat_monitorNNN". Note that the object's name in "/objects/" matches the QemuOpts ID when it exists. The only cases where it doesn't exist are "-mon" without ID, "-gdbstub" and "-serial mon:". A future patch will make "monitor-hmp" and "monitor-qmp" work with "-object" and "object-add". Note: there is a slight change in the NNN values assigned. The old code would increment the counter for every monitor added (except for -mon, -serial mon:..., -gdbstub), regardless of whether it needed a "compat_monitorNNN" ID assignment. Now it is only incremented when an automatic ID assigned is needed (but even for -mon, -serial mon:..., -gdbstub). Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Message-ID: <20260706135824.2623960-6-berrange@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [Commit message made slightly more precise] Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
committed by
Markus Armbruster
parent
fc500ce4d3
commit
f96eac8a4f
@@ -805,7 +805,7 @@ static Chardev *qemu_chr_new_from_name(const char *label, const char *filename,
|
||||
|
||||
if (qemu_opt_get_bool(opts, "mux", 0)) {
|
||||
assert(permit_mux_mon);
|
||||
monitor_new_hmp(chr, true, &err);
|
||||
monitor_new_hmp(NULL, chr, true, &err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
object_unparent(OBJECT(chr));
|
||||
|
||||
@@ -390,7 +390,7 @@ bool gdbserver_start(const char *device, Error **errp)
|
||||
/* Initialize a monitor terminal for gdb */
|
||||
mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB,
|
||||
NULL, NULL, &error_abort);
|
||||
monitor_new_hmp(mon_chr, false, &error_abort);
|
||||
monitor_new_hmp(NULL, mon_chr, false, &error_abort);
|
||||
} else {
|
||||
qemu_chr_fe_deinit(&gdbserver_system_state.chr, true);
|
||||
mon_chr = gdbserver_system_state.mon_chr;
|
||||
|
||||
@@ -5,8 +5,17 @@
|
||||
#include "qapi/qapi-types-misc.h"
|
||||
#include "qemu/readline.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_MONITOR "monitor"
|
||||
OBJECT_DECLARE_TYPE(Monitor, MonitorClass, MONITOR);
|
||||
|
||||
#define TYPE_MONITOR_HMP "monitor-hmp"
|
||||
OBJECT_DECLARE_TYPE(MonitorHMP, MonitorHMPClass, MONITOR_HMP);
|
||||
|
||||
#define TYPE_MONITOR_QMP "monitor-qmp"
|
||||
OBJECT_DECLARE_TYPE(MonitorQMP, MonitorQMPClass, MONITOR_QMP);
|
||||
|
||||
typedef struct MonitorHMP MonitorHMP;
|
||||
typedef struct MonitorOptions MonitorOptions;
|
||||
|
||||
#define QMP_REQ_QUEUE_LEN_MAX 8
|
||||
@@ -19,8 +28,11 @@ bool monitor_cur_is_qmp(void);
|
||||
|
||||
void monitor_init_globals(void);
|
||||
void monitor_init_globals_core(void);
|
||||
void monitor_new_qmp(Chardev *chr, bool pretty, Error **errp);
|
||||
void monitor_new_hmp(Chardev *chr, bool use_readline, Error **errp);
|
||||
char *monitor_compat_id(void);
|
||||
void monitor_new_qmp(const char *id, Chardev *chr,
|
||||
bool pretty, Error **errp);
|
||||
void monitor_new_hmp(const char *id, Chardev *chr,
|
||||
bool use_readline, Error **errp);
|
||||
int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp);
|
||||
int monitor_new_opts(QemuOpts *opts, Error **errp);
|
||||
void monitor_cleanup(void);
|
||||
|
||||
@@ -43,6 +43,20 @@
|
||||
#include "system/block-backend.h"
|
||||
#include "trace.h"
|
||||
|
||||
OBJECT_DEFINE_TYPE(MonitorHMP, monitor_hmp, MONITOR_HMP, MONITOR);
|
||||
|
||||
static void monitor_hmp_finalize(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static void monitor_hmp_class_init(ObjectClass *cls, const void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static void monitor_hmp_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static void monitor_command_cb(void *opaque, const char *cmdline,
|
||||
void *readline_opaque)
|
||||
{
|
||||
@@ -1524,12 +1538,23 @@ static void monitor_readline_flush(void *opaque)
|
||||
monitor_flush(&mon->parent_obj);
|
||||
}
|
||||
|
||||
void monitor_new_hmp(Chardev *chr, bool use_readline, Error **errp)
|
||||
void monitor_new_hmp(const char *id, Chardev *chr,
|
||||
bool use_readline, Error **errp)
|
||||
{
|
||||
MonitorHMP *mon = g_new0(MonitorHMP, 1);
|
||||
MonitorHMP *mon;
|
||||
g_autofree char *autoid = id ? NULL : monitor_compat_id();
|
||||
Object *obj = object_new_with_props(TYPE_MONITOR_HMP,
|
||||
object_get_objects_root(),
|
||||
id ? id : autoid,
|
||||
errp,
|
||||
NULL);
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
mon = MONITOR_HMP(obj);
|
||||
|
||||
if (!qemu_chr_fe_init(&mon->parent_obj.chr, chr, errp)) {
|
||||
g_free(mon);
|
||||
object_unparent(OBJECT(mon));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,13 @@ typedef struct HMPCommand {
|
||||
bool coroutine;
|
||||
} HMPCommand;
|
||||
|
||||
|
||||
struct MonitorClass {
|
||||
ObjectClass parent_class;
|
||||
};
|
||||
|
||||
struct Monitor {
|
||||
Object parent;
|
||||
CharFrontend chr;
|
||||
int suspend_cnt; /* Needs to be accessed atomically */
|
||||
bool is_qmp;
|
||||
@@ -127,6 +133,10 @@ struct Monitor {
|
||||
int reset_seen;
|
||||
};
|
||||
|
||||
struct MonitorHMPClass {
|
||||
MonitorClass parent_class;
|
||||
};
|
||||
|
||||
struct MonitorHMP {
|
||||
Monitor parent_obj;
|
||||
bool use_readline;
|
||||
@@ -140,7 +150,11 @@ struct MonitorHMP {
|
||||
ReadLineState *rs;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct MonitorQMPClass {
|
||||
MonitorClass parent_class;
|
||||
};
|
||||
|
||||
struct MonitorQMP {
|
||||
Monitor parent_obj;
|
||||
JSONMessageParser parser;
|
||||
bool pretty;
|
||||
@@ -160,7 +174,7 @@ typedef struct {
|
||||
QemuMutex qmp_queue_lock;
|
||||
/* Input queue that holds all the parsed QMP requests */
|
||||
GQueue *qmp_requests;
|
||||
} MonitorQMP;
|
||||
};
|
||||
|
||||
/**
|
||||
* Is @mon a QMP monitor?
|
||||
|
||||
@@ -73,6 +73,22 @@ static GHashTable *coroutine_mon; /* Maps Coroutine* to Monitor* */
|
||||
MonitorList mon_list;
|
||||
static bool monitor_destroyed;
|
||||
|
||||
int monitor_device_index;
|
||||
|
||||
OBJECT_DEFINE_ABSTRACT_TYPE(Monitor, monitor, MONITOR, OBJECT);
|
||||
|
||||
static void monitor_finalize(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static void monitor_class_init(ObjectClass *cls, const void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static void monitor_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
Monitor *monitor_cur(void)
|
||||
{
|
||||
Monitor *mon;
|
||||
@@ -598,7 +614,7 @@ void monitor_list_append(Monitor *mon)
|
||||
|
||||
if (mon) {
|
||||
monitor_data_destroy(mon);
|
||||
g_free(mon);
|
||||
object_unparent(OBJECT(mon));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,7 +696,7 @@ void monitor_cleanup(void)
|
||||
monitor_flush(mon);
|
||||
monitor_data_destroy(mon);
|
||||
qemu_mutex_lock(&monitor_lock);
|
||||
g_free(mon);
|
||||
object_unparent(OBJECT(mon));
|
||||
}
|
||||
qemu_mutex_unlock(&monitor_lock);
|
||||
|
||||
@@ -715,6 +731,13 @@ void monitor_init_globals(void)
|
||||
aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
|
||||
}
|
||||
|
||||
char *monitor_compat_id(void)
|
||||
{
|
||||
static int monitor_device_index;
|
||||
|
||||
return g_strdup_printf("compat_monitor%d", monitor_device_index++);
|
||||
}
|
||||
|
||||
int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
@@ -732,7 +755,7 @@ int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)
|
||||
|
||||
switch (opts->mode) {
|
||||
case MONITOR_MODE_CONTROL:
|
||||
monitor_new_qmp(chr, opts->pretty, errp);
|
||||
monitor_new_qmp(opts->id, chr, opts->pretty, errp);
|
||||
break;
|
||||
case MONITOR_MODE_READLINE:
|
||||
if (!allow_hmp) {
|
||||
@@ -743,7 +766,7 @@ int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)
|
||||
error_setg(errp, "'pretty' is not compatible with HMP monitors");
|
||||
return -1;
|
||||
}
|
||||
monitor_new_hmp(chr, true, errp);
|
||||
monitor_new_hmp(opts->id, chr, true, errp);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
|
||||
@@ -166,12 +166,12 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
|
||||
int64_t cpu_index, Error **errp)
|
||||
{
|
||||
char *output = NULL;
|
||||
MonitorHMP hmp = {};
|
||||
MonitorHMP *hmp = MONITOR_HMP(object_new(TYPE_MONITOR_HMP));
|
||||
|
||||
monitor_data_init(&hmp.parent_obj, false, true, false);
|
||||
monitor_data_init(&hmp->parent_obj, false, true, false);
|
||||
|
||||
if (has_cpu_index) {
|
||||
int ret = monitor_set_cpu(&hmp.parent_obj, cpu_index);
|
||||
int ret = monitor_set_cpu(&hmp->parent_obj, cpu_index);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
|
||||
"a CPU number");
|
||||
@@ -179,14 +179,15 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
|
||||
}
|
||||
}
|
||||
|
||||
handle_hmp_command(&hmp, command_line);
|
||||
handle_hmp_command(hmp, command_line);
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&hmp.parent_obj.mon_lock) {
|
||||
output = g_strdup(hmp.parent_obj.outbuf->str);
|
||||
WITH_QEMU_LOCK_GUARD(&hmp->parent_obj.mon_lock) {
|
||||
output = g_strdup(hmp->parent_obj.outbuf->str);
|
||||
}
|
||||
|
||||
out:
|
||||
monitor_data_destroy(&hmp.parent_obj);
|
||||
monitor_data_destroy(&hmp->parent_obj);
|
||||
object_unref(hmp);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,20 @@ typedef struct QMPRequest QMPRequest;
|
||||
|
||||
QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
|
||||
|
||||
OBJECT_DEFINE_TYPE(MonitorQMP, monitor_qmp, MONITOR_QMP, MONITOR);
|
||||
|
||||
static void monitor_qmp_finalize(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static void monitor_qmp_class_init(ObjectClass *cls, const void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static void monitor_qmp_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static bool qmp_oob_enabled(MonitorQMP *mon)
|
||||
{
|
||||
return mon->capab[QMP_CAPABILITY_OOB];
|
||||
@@ -513,12 +527,23 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
|
||||
monitor_list_append(&mon->parent_obj);
|
||||
}
|
||||
|
||||
void monitor_new_qmp(Chardev *chr, bool pretty, Error **errp)
|
||||
void monitor_new_qmp(const char *id, Chardev *chr,
|
||||
bool pretty, Error **errp)
|
||||
{
|
||||
MonitorQMP *mon = g_new0(MonitorQMP, 1);
|
||||
MonitorQMP *mon;
|
||||
g_autofree char *autoid = id ? NULL : monitor_compat_id();
|
||||
Object *obj = object_new_with_props(TYPE_MONITOR_QMP,
|
||||
object_get_objects_root(),
|
||||
id ? id : autoid,
|
||||
errp,
|
||||
NULL);
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
mon = MONITOR_QMP(obj);
|
||||
|
||||
if (!qemu_chr_fe_init(&mon->parent_obj.chr, chr, errp)) {
|
||||
g_free(mon);
|
||||
object_unparent(OBJECT(mon));
|
||||
return;
|
||||
}
|
||||
qemu_chr_fe_set_echo(&mon->parent_obj.chr, true);
|
||||
|
||||
@@ -8,6 +8,7 @@ int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void monitor_new_hmp(Chardev *chr, bool use_readline, Error **errp)
|
||||
void monitor_new_hmp(const char *id, Chardev *chr,
|
||||
bool use_readline, Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1252,7 +1252,6 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
|
||||
|
||||
static void monitor_parse(const char *str, const char *mode, bool pretty)
|
||||
{
|
||||
static int monitor_device_index = 0;
|
||||
QemuOpts *opts;
|
||||
const char *p;
|
||||
char label[32];
|
||||
@@ -1260,8 +1259,9 @@ static void monitor_parse(const char *str, const char *mode, bool pretty)
|
||||
if (strstart(str, "chardev:", &p)) {
|
||||
snprintf(label, sizeof(label), "%s", p);
|
||||
} else {
|
||||
snprintf(label, sizeof(label), "compat_monitor%d",
|
||||
monitor_device_index);
|
||||
g_autofree char *id = monitor_compat_id();
|
||||
assert(strlen(id) < sizeof(label));
|
||||
memcpy(label, id, strlen(id) + 1);
|
||||
opts = qemu_chr_parse_compat(label, str, true);
|
||||
if (!opts) {
|
||||
error_report("parse error: %s", str);
|
||||
@@ -1277,7 +1277,6 @@ static void monitor_parse(const char *str, const char *mode, bool pretty)
|
||||
} else {
|
||||
assert(pretty == false);
|
||||
}
|
||||
monitor_device_index++;
|
||||
}
|
||||
|
||||
struct device_config {
|
||||
|
||||
Reference in New Issue
Block a user