The direction for this work has been set in the discussion thread: "About creating machines on the command line" in January/February 2021: https://lists.gnu.org/archive/html/qemu-devel/2021-01/msg01839.html https://lists.gnu.org/archive/html/qemu-devel/2021-02/msg01070.html
To customize a machine via QMP we need the ability to stop QEMU at a specific machine initialization phase. Currently, machine initialization phases are: 1) no-machine: machine does not exist yet (current_machine == NULL) 2) machine-created: machine exists, but its accelerator does not (current_machine->accelerator == NULL) 3) accel-created: machine's accelerator is configured (current_machine->accelerator != NULL), but machine class's init() has not been called (no properties validated, machine_init_done notifiers not registered, no sysbus, etc.) 4) initialized: machine class's init() has been called, thus machine properties are validated, machine_init_done notifiers registered, sysbus realized, etc. Devices added at this phase are considered to be cold-plugged. 5) ready: machine_init_done notifiers are called, then QEMU is ready to start CPUs. Devices added at this phase are considered to be hot-plugged. QEMU can be stopped today using the -preconfig CLI option at phase 3 (accel-created). This option was introduced to enable the QMP configuration of parameters that affect the machine initialization. We cannot add devices at this point because the machine class's init() has not been called, thus sysbus does not exist yet (a device cannot be added because there is no bus to attach it to). QEMU can be also stopped using the -S CLI option at the machine ready phase. However, it is too late to add devices at this phase because the machine is already configured, and any devices added at this point are considered to be hot-plugged. Since the existing -preconfig CLI option stops QEMU too early, and the -S option stops too late, we need a way to stop QEMU in between (after the machine is initialized and before it becomes ready). We propose to add QMP commands to step through machine phases starting from the initial CLI's '-preconfig' early stop point. With this addition, we may now execute QMP commands at any machine phase. The 'next-machine-phase' command would trigger QEMU to execute initialization steps that are needed to enter the next phase. If it's more convenient to jump to an initialization phase than to single-step through phases, the 'advance-machine-phase' command should be used instead of 'next-machine-phase'. Additionally, we propose to add the command to query the current machine phase, namely 'query-machine-phase'. With this patch it would be possible to add devices via QMP. For example, by running QEMU with: $ qemu-system-riscv32 \ -M sifive_dt \ -qmp unix:./qmp-sock,server \ -preconfig \ ... and scripts/qmp/qmp-shell as the QMP client: $ qemu/scripts/qmp/qmp-shell ./qmp-sock Welcome to the QMP low-level shell! Connected to QEMU 6.0.0 (QEMU) query-machine-phase {"return": {"phase": "accel-created"}} (QEMU) next-machine-phase {"return": {}} (QEMU) query-machine-phase {"return": {"phase": "initialized"}} (QEMU) device_add driver=... {"return": {}} (QEMU) next-machine-phase {"return": {}} (QEMU) query-machine-phase {"return": {"phase": "ready"}} Note that with the introduced changes, devices can still be added via CLI, i.e. we support a mixed configuration approach (CLI, QMP, or CLI/QMP). Any device specified via CLI will be added before QEMU waits for the QMP configuration in the machine 'initialized' phase. Mirela Grujic (9): vl: Allow finer control in advancing machine through phases replace machine phase_check with machine_is_initialized/ready calls rename MachineInitPhase enumeration constants qapi: Implement 'query-machine-phase' command qapi: Implement 'next-machine-phase' command qapi: Implement 'advance-machine-phase' command qdev-monitor: Restructure and fix the check for command availability qapi: Introduce 'allow-init-config' option qapi: Allow some commands to be executed in machine 'initialized' phase docs/sphinx/qapidoc.py | 2 +- qapi/machine.json | 105 ++++++++++++++++++++++++++++++++++++ qapi/qdev.json | 3 +- include/hw/qdev-core.h | 32 ++--------- include/qapi/qmp/dispatch.h | 1 + include/sysemu/sysemu.h | 3 ++ hw/core/machine-qmp-cmds.c | 33 +++++++++++- hw/core/machine.c | 6 +-- hw/core/qdev.c | 17 +++++- hw/pci/pci.c | 2 +- hw/usb/core.c | 2 +- hw/virtio/virtio-iommu.c | 2 +- monitor/hmp.c | 2 +- monitor/misc.c | 2 +- softmmu/qdev-monitor.c | 31 +++++++---- softmmu/vl.c | 94 ++++++++++++++++++++------------ ui/console.c | 2 +- scripts/qapi/commands.py | 10 ++-- scripts/qapi/expr.py | 5 +- scripts/qapi/introspect.py | 3 +- scripts/qapi/schema.py | 10 ++-- 21 files changed, 274 insertions(+), 93 deletions(-) -- 2.25.1