diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index ddfcd5adcc..6db3457a78 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -19,6 +19,7 @@ ETEXI .params = "", .help = "show the version of QEMU", .cmd = hmp_info_version, + .flags = "p", }, STEXI @@ -47,6 +48,7 @@ ETEXI .params = "", .help = "show the character devices", .cmd = hmp_info_chardev, + .flags = "p", }, STEXI @@ -165,6 +167,7 @@ ETEXI .params = "", .help = "show the command line history", .cmd = hmp_info_history, + .flags = "p", }, STEXI @@ -399,6 +402,7 @@ ETEXI .params = "", .help = "show the current VM status (running|paused)", .cmd = hmp_info_status, + .flags = "p", }, STEXI @@ -457,6 +461,7 @@ ETEXI .params = "", .help = "show the current VM name", .cmd = hmp_info_name, + .flags = "p", }, STEXI @@ -471,6 +476,7 @@ ETEXI .params = "", .help = "show the current VM UUID", .cmd = hmp_info_uuid, + .flags = "p", }, STEXI @@ -613,6 +619,7 @@ ETEXI .params = "[path]", .help = "show QOM composition tree", .cmd = hmp_info_qom_tree, + .flags = "p", }, STEXI @@ -671,6 +678,7 @@ ETEXI .params = "", .help = "show memory backends", .cmd = hmp_info_memdev, + .flags = "p", }, STEXI @@ -699,6 +707,7 @@ ETEXI .params = "", .help = "show iothreads", .cmd = hmp_info_iothreads, + .flags = "p", }, STEXI @@ -829,6 +838,7 @@ ETEXI .params = "", .help = "Show information about hotpluggable CPUs", .cmd = hmp_hotpluggable_cpus, + .flags = "p", }, STEXI diff --git a/hmp-commands.hx b/hmp-commands.hx index 0de7c4c29e..ba9cdb8800 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -15,6 +15,7 @@ ETEXI .params = "[cmd]", .help = "show the help", .cmd = do_help_cmd, + .flags = "p", }, STEXI @@ -54,6 +55,25 @@ STEXI @item q or quit @findex quit Quit the emulator. +ETEXI + + { + .name = "exit_preconfig", + .args_type = "", + .params = "", + .help = "exit the preconfig state", + .cmd = hmp_exit_preconfig, + .flags = "p", + }, + +STEXI +@item exit_preconfig +@findex exit_preconfig +This command makes QEMU exit the preconfig state and proceed with +VM initialization using configuration data provided on the command line +and via the QMP monitor during the preconfig state. The command is only +available during the preconfig state (i.e. when the --preconfig command +line option was in use). ETEXI { @@ -1116,7 +1136,7 @@ ETEXI { .name = "dump-guest-memory", - .args_type = "paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:i?,length:i?", + .args_type = "paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?", .params = "[-p] [-d] [-z|-l|-s] filename [begin length]", .help = "dump guest memory into file 'filename'.\n\t\t\t" "-p: do paging to get guest's memory mapping.\n\t\t\t" @@ -1827,6 +1847,7 @@ ETEXI .params = "path", .help = "list QOM properties", .cmd = hmp_qom_list, + .flags = "p", }, STEXI @@ -1840,6 +1861,7 @@ ETEXI .params = "path property value", .help = "set QOM property", .cmd = hmp_qom_set, + .flags = "p", }, STEXI @@ -1854,6 +1876,7 @@ ETEXI .help = "show various information about the system state", .cmd = hmp_info_help, .sub_table = info_cmds, + .flags = "p", }, STEXI diff --git a/hmp.c b/hmp.c index f40d8279cf..f601099f90 100644 --- a/hmp.c +++ b/hmp.c @@ -1068,6 +1068,14 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict) qmp_system_powerdown(NULL); } +void hmp_exit_preconfig(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + + qmp_exit_preconfig(&err); + hmp_handle_error(mon, &err); +} + void hmp_cpu(Monitor *mon, const QDict *qdict) { int64_t cpu_index; diff --git a/hmp.h b/hmp.h index 20f27439d3..33354f1bdd 100644 --- a/hmp.h +++ b/hmp.h @@ -44,6 +44,7 @@ void hmp_quit(Monitor *mon, const QDict *qdict); void hmp_stop(Monitor *mon, const QDict *qdict); void hmp_system_reset(Monitor *mon, const QDict *qdict); void hmp_system_powerdown(Monitor *mon, const QDict *qdict); +void hmp_exit_preconfig(Monitor *mon, const QDict *qdict); void hmp_cpu(Monitor *mon, const QDict *qdict); void hmp_memsave(Monitor *mon, const QDict *qdict); void hmp_pmemsave(Monitor *mon, const QDict *qdict); diff --git a/monitor.c b/monitor.c index 885e000f9b..0730a27172 100644 --- a/monitor.c +++ b/monitor.c @@ -128,6 +128,7 @@ typedef struct mon_cmd_t { const char *args_type; const char *params; const char *help; + const char *flags; /* p=preconfig */ void (*cmd)(Monitor *mon, const QDict *qdict); /* @sub_table is a list of 2nd level of commands. If it does not exist, * cmd should be used. If it exists, sub_table[?].cmd should be @@ -958,6 +959,19 @@ static int parse_cmdline(const char *cmdline, return -1; } +/* + * Returns true if the command can be executed in preconfig mode + * i.e. it has the 'p' flag. + */ +static bool cmd_can_preconfig(const mon_cmd_t *cmd) +{ + if (!cmd->flags) { + return false; + } + + return strchr(cmd->flags, 'p'); +} + static void help_cmd_dump_one(Monitor *mon, const mon_cmd_t *cmd, char **prefix_args, @@ -965,6 +979,10 @@ static void help_cmd_dump_one(Monitor *mon, { int i; + if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { + return; + } + for (i = 0; i < prefix_args_nb; i++) { monitor_printf(mon, "%s ", prefix_args[i]); } @@ -987,7 +1005,9 @@ static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds, /* Find one entry to dump */ for (cmd = cmds; cmd->name != NULL; cmd++) { - if (compare_cmd(args[arg_index], cmd->name)) { + if (compare_cmd(args[arg_index], cmd->name) && + ((!runstate_check(RUN_STATE_PRECONFIG) || + cmd_can_preconfig(cmd)))) { if (cmd->sub_table) { /* continue with next arg */ help_cmd_dump(mon, cmd->sub_table, @@ -3041,6 +3061,12 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon, (int)(p - cmdp_start), cmdp_start); return NULL; } + if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { + monitor_printf(mon, "Command '%.*s' not available with -preconfig " + "until after exit_preconfig.\n", + (int)(p - cmdp_start), cmdp_start); + return NULL; + } /* filter out following useless space */ while (qemu_isspace(*p)) { @@ -3431,15 +3457,10 @@ static void handle_hmp_command(Monitor *mon, const char *cmdline) { QDict *qdict; const mon_cmd_t *cmd; + const char *cmd_start = cmdline; trace_handle_hmp_command(mon, cmdline); - if (runstate_check(RUN_STATE_PRECONFIG)) { - monitor_printf(mon, "HMP not available in preconfig state, " - "use QMP instead\n"); - return; - } - cmd = monitor_parse_command(mon, cmdline, &cmdline, mon->cmd_table); if (!cmd) { return; @@ -3447,8 +3468,11 @@ static void handle_hmp_command(Monitor *mon, const char *cmdline) qdict = monitor_parse_arguments(mon, &cmdline, cmd); if (!qdict) { - monitor_printf(mon, "Try \"help %s\" for more information\n", - cmd->name); + while (cmdline > cmd_start && qemu_isspace(cmdline[-1])) { + cmdline--; + } + monitor_printf(mon, "Try \"help %.*s\" for more information\n", + (int)(cmdline - cmd_start), cmd_start); return; } @@ -3990,12 +4014,17 @@ static void monitor_find_completion_by_table(Monitor *mon, cmdname = args[0]; readline_set_completion_index(mon->rs, strlen(cmdname)); for (cmd = cmd_table; cmd->name != NULL; cmd++) { - cmd_completion(mon, cmdname, cmd->name); + if (!runstate_check(RUN_STATE_PRECONFIG) || + cmd_can_preconfig(cmd)) { + cmd_completion(mon, cmdname, cmd->name); + } } } else { /* find the command */ for (cmd = cmd_table; cmd->name != NULL; cmd++) { - if (compare_cmd(args[0], cmd->name)) { + if (compare_cmd(args[0], cmd->name) && + (!runstate_check(RUN_STATE_PRECONFIG) || + cmd_can_preconfig(cmd))) { break; } } diff --git a/qapi/char.json b/qapi/char.json index ae19dcd1ed..60f31d83fc 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -62,7 +62,8 @@ # } # ## -{ 'command': 'query-chardev', 'returns': ['ChardevInfo'] } +{ 'command': 'query-chardev', 'returns': ['ChardevInfo'], + 'allow-preconfig': true } ## # @ChardevBackendInfo: diff --git a/qapi/misc.json b/qapi/misc.json index f83a63a0ab..fa86831ec3 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -117,7 +117,8 @@ # } # ## -{ 'command': 'query-version', 'returns': 'VersionInfo' } +{ 'command': 'query-version', 'returns': 'VersionInfo', + 'allow-preconfig': true } ## # @CommandInfo: @@ -241,7 +242,7 @@ # <- { "return": { "name": "qemu-name" } } # ## -{ 'command': 'query-name', 'returns': 'NameInfo' } +{ 'command': 'query-name', 'returns': 'NameInfo', 'allow-preconfig': true } ## # @KvmInfo: @@ -301,7 +302,7 @@ # <- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } } # ## -{ 'command': 'query-uuid', 'returns': 'UuidInfo' } +{ 'command': 'query-uuid', 'returns': 'UuidInfo', 'allow-preconfig': true } ## # @EventInfo: @@ -710,7 +711,8 @@ # } # ## -{ 'command': 'query-iothreads', 'returns': ['IOThreadInfo'] } +{ 'command': 'query-iothreads', 'returns': ['IOThreadInfo'], + 'allow-preconfig': true } ## # @BalloonInfo: @@ -1408,7 +1410,8 @@ ## { 'command': 'qom-list', 'data': { 'path': 'str' }, - 'returns': [ 'ObjectPropertyInfo' ] } + 'returns': [ 'ObjectPropertyInfo' ], + 'allow-preconfig': true } ## # @qom-get: @@ -1444,7 +1447,8 @@ ## { 'command': 'qom-get', 'data': { 'path': 'str', 'property': 'str' }, - 'returns': 'any' } + 'returns': 'any', + 'allow-preconfig': true } ## # @qom-set: @@ -1461,7 +1465,8 @@ # Since: 1.2 ## { 'command': 'qom-set', - 'data': { 'path': 'str', 'property': 'str', 'value': 'any' } } + 'data': { 'path': 'str', 'property': 'str', 'value': 'any' }, + 'allow-preconfig': true } ## # @change: @@ -1543,7 +1548,8 @@ ## { 'command': 'qom-list-types', 'data': { '*implements': 'str', '*abstract': 'bool' }, - 'returns': [ 'ObjectTypeInfo' ] } + 'returns': [ 'ObjectTypeInfo' ], + 'allow-preconfig': true } ## # @device-list-properties: @@ -1581,7 +1587,8 @@ ## { 'command': 'qom-list-properties', 'data': { 'typename': 'str'}, - 'returns': [ 'ObjectPropertyInfo' ] } + 'returns': [ 'ObjectPropertyInfo' ], + 'allow-preconfig': true } ## # @xen-set-global-dirty-log: @@ -2902,7 +2909,7 @@ # } # ## -{ 'command': 'query-memdev', 'returns': ['Memdev'] } +{ 'command': 'query-memdev', 'returns': ['Memdev'], 'allow-preconfig': true } ## # @PCDIMMDeviceInfo: