|
@@ -66,12 +66,13 @@ Then, in a different terminal::
|
|
|
"version": {
|
|
|
"qemu": {
|
|
|
"micro": 50,
|
|
|
- "minor": 15,
|
|
|
- "major": 0
|
|
|
+ "minor": 2,
|
|
|
+ "major": 8
|
|
|
},
|
|
|
- "package": ""
|
|
|
+ "package": ...
|
|
|
},
|
|
|
"capabilities": [
|
|
|
+ "oob"
|
|
|
]
|
|
|
}
|
|
|
}
|
|
@@ -107,6 +108,11 @@ The first step is defining the command in the appropriate QAPI schema
|
|
|
module. We pick module qapi/misc.json, and add the following line at
|
|
|
the bottom::
|
|
|
|
|
|
+ ##
|
|
|
+ # @hello-world:
|
|
|
+ #
|
|
|
+ # Since: 9.0
|
|
|
+ ##
|
|
|
{ 'command': 'hello-world' }
|
|
|
|
|
|
The "command" keyword defines a new QMP command. It's an JSON object. All
|
|
@@ -148,37 +154,50 @@ you don't see it then something went wrong.
|
|
|
Arguments
|
|
|
~~~~~~~~~
|
|
|
|
|
|
-Let's add an argument called "message" to our "hello-world" command. The new
|
|
|
-argument will contain the string to be printed to stdout. It's an optional
|
|
|
-argument, if it's not present we print our default "Hello, World" string.
|
|
|
+Let's add arguments to our "hello-world" command.
|
|
|
|
|
|
The first change we have to do is to modify the command specification in the
|
|
|
schema file to the following::
|
|
|
|
|
|
- { 'command': 'hello-world', 'data': { '*message': 'str' } }
|
|
|
+ ##
|
|
|
+ # @hello-world:
|
|
|
+ #
|
|
|
+ # @message: message to be printed (default: "Hello, world!")
|
|
|
+ #
|
|
|
+ # @times: how many times to print the message (default: 1)
|
|
|
+ #
|
|
|
+ # Since: 9.0
|
|
|
+ ##
|
|
|
+ { 'command': 'hello-world',
|
|
|
+ 'data': { '*message': 'str', '*times': 'int' } }
|
|
|
|
|
|
-Notice the new 'data' member in the schema. It's an JSON object whose each
|
|
|
-element is an argument to the command in question. Also notice the asterisk,
|
|
|
-it's used to mark the argument optional (that means that you shouldn't use it
|
|
|
-for mandatory arguments). Finally, 'str' is the argument's type, which
|
|
|
-stands for "string". The QAPI also supports integers, booleans, enumerations
|
|
|
-and user defined types.
|
|
|
+Notice the new 'data' member in the schema. It specifies an argument
|
|
|
+'message' of QAPI type 'str', and an argument 'times' of QAPI type
|
|
|
+'int'. Also notice the asterisk, it's used to mark the argument
|
|
|
+optional.
|
|
|
|
|
|
Now, let's update our C implementation in monitor/qmp-cmds.c::
|
|
|
|
|
|
- void qmp_hello_world(const char *message, Error **errp)
|
|
|
+ void qmp_hello_world(const char *message, bool has_times, int64_t times,
|
|
|
+ Error **errp)
|
|
|
{
|
|
|
- if (message) {
|
|
|
+ if (!message) {
|
|
|
+ message = "Hello, world";
|
|
|
+ }
|
|
|
+ if (!has_times) {
|
|
|
+ times = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < times; i++) {
|
|
|
printf("%s\n", message);
|
|
|
- } else {
|
|
|
- printf("Hello, world\n");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
There are two important details to be noticed:
|
|
|
|
|
|
-1. All optional arguments are accompanied by a 'has\_' boolean, which is set
|
|
|
- if the optional argument is present or false otherwise
|
|
|
+1. Optional arguments other than pointers are accompanied by a 'has\_'
|
|
|
+ boolean, which is set if the optional argument is present or false
|
|
|
+ otherwise
|
|
|
2. The C implementation signature must follow the schema's argument ordering,
|
|
|
which is defined by the "data" member
|
|
|
|
|
@@ -254,35 +273,6 @@ If the failure you want to report falls into one of the two cases above,
|
|
|
use error_set() with a second argument of an ErrorClass value.
|
|
|
|
|
|
|
|
|
-Command Documentation
|
|
|
-~~~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-There's only one step missing to make "hello-world"'s implementation complete,
|
|
|
-and that's its documentation in the schema file.
|
|
|
-
|
|
|
-There are many examples of such documentation in the schema file already, but
|
|
|
-here goes "hello-world"'s new entry for qapi/misc.json::
|
|
|
-
|
|
|
- ##
|
|
|
- # @hello-world:
|
|
|
- #
|
|
|
- # Print a client provided string to the standard output stream.
|
|
|
- #
|
|
|
- # @message: string to be printed
|
|
|
- #
|
|
|
- # Returns: Nothing on success.
|
|
|
- #
|
|
|
- # Notes: if @message is not provided, the "Hello, world" string will
|
|
|
- # be printed instead
|
|
|
- #
|
|
|
- # Since: <next qemu stable release, eg. 1.0>
|
|
|
- ##
|
|
|
- { 'command': 'hello-world', 'data': { '*message': 'str' } }
|
|
|
-
|
|
|
-Please, note that the "Returns" clause is optional if a command doesn't return
|
|
|
-any data nor any errors.
|
|
|
-
|
|
|
-
|
|
|
Implementing the HMP command
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
@@ -306,18 +296,20 @@ Here's the implementation of the "hello-world" HMP command::
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-Also, you have to add the function's prototype to the hmp.h file.
|
|
|
+Add it to monitor/hmp-cmds.c. Also, add its prototype to
|
|
|
+include/monitor/hmp.h.
|
|
|
|
|
|
-There are three important points to be noticed:
|
|
|
+There are four important points to be noticed:
|
|
|
|
|
|
1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The
|
|
|
former is the monitor object. The latter is how the monitor passes
|
|
|
arguments entered by the user to the command implementation
|
|
|
-2. hmp_hello_world() performs error checking. In this example we just call
|
|
|
+2. We chose not to support the "times" argument in HMP
|
|
|
+3. hmp_hello_world() performs error checking. In this example we just call
|
|
|
hmp_handle_error() which prints a message to the user, but we could do
|
|
|
more, like taking different actions depending on the error
|
|
|
qmp_hello_world() returns
|
|
|
-3. The "err" variable must be initialized to NULL before performing the
|
|
|
+4. The "err" variable must be initialized to NULL before performing the
|
|
|
QMP call
|
|
|
|
|
|
There's one last step to actually make the command available to monitor users,
|
|
@@ -372,7 +364,7 @@ data, it is not expected that machines will need to parse the result.
|
|
|
The overhead of defining a fine grained QAPI type for the data may not
|
|
|
be justified by the potential benefit. In such cases, it is permitted
|
|
|
to have a command return a simple string that contains formatted data,
|
|
|
-however, it is mandatory for the command to use the 'x-' name prefix.
|
|
|
+however, it is mandatory for the command to be marked unstable.
|
|
|
This indicates that the command is not guaranteed to be long term
|
|
|
stable / liable to change in future and is not following QAPI design
|
|
|
best practices. An example where this approach is taken is the QMP
|
|
@@ -386,302 +378,207 @@ an illustration.
|
|
|
User Defined Types
|
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
-FIXME This example needs to be redone after commit 6d32717
|
|
|
+For this example we will write the query-option-roms command, which
|
|
|
+returns information about ROMs loaded into the option ROM space. For
|
|
|
+more information about it, please check the "-option-rom" command-line
|
|
|
+option.
|
|
|
|
|
|
-For this example we will write the query-alarm-clock command, which returns
|
|
|
-information about QEMU's timer alarm. For more information about it, please
|
|
|
-check the "-clock" command-line option.
|
|
|
-
|
|
|
-We want to return two pieces of information. The first one is the alarm clock's
|
|
|
-name. The second one is when the next alarm will fire. The former information is
|
|
|
-returned as a string, the latter is an integer in nanoseconds (which is not
|
|
|
-very useful in practice, as the timer has probably already fired when the
|
|
|
-information reaches the client).
|
|
|
-
|
|
|
-The best way to return that data is to create a new QAPI type, as shown below::
|
|
|
+For each option ROM, we want to return two pieces of information: the
|
|
|
+ROM image's file name, and its bootindex, if any. We need to create a
|
|
|
+new QAPI type for that, as shown below::
|
|
|
|
|
|
##
|
|
|
- # @QemuAlarmClock
|
|
|
- #
|
|
|
- # QEMU alarm clock information.
|
|
|
+ # @OptionRomInfo:
|
|
|
#
|
|
|
- # @clock-name: The alarm clock method's name.
|
|
|
+ # @filename: option ROM image file name
|
|
|
#
|
|
|
- # @next-deadline: The time (in nanoseconds) the next alarm will fire.
|
|
|
+ # @bootindex: option ROM's bootindex
|
|
|
#
|
|
|
- # Since: 1.0
|
|
|
+ # Since: 9.0
|
|
|
##
|
|
|
- { 'type': 'QemuAlarmClock',
|
|
|
- 'data': { 'clock-name': 'str', '*next-deadline': 'int' } }
|
|
|
+ { 'struct': 'OptionRomInfo',
|
|
|
+ 'data': { 'filename': 'str', '*bootindex': 'int' } }
|
|
|
|
|
|
-The "type" keyword defines a new QAPI type. Its "data" member contains the
|
|
|
-type's members. In this example our members are the "clock-name" and the
|
|
|
-"next-deadline" one, which is optional.
|
|
|
+The "struct" keyword defines a new QAPI type. Its "data" member
|
|
|
+contains the type's members. In this example our members are
|
|
|
+"filename" and "bootindex". The latter is optional.
|
|
|
|
|
|
-Now let's define the query-alarm-clock command::
|
|
|
+Now let's define the query-option-roms command::
|
|
|
|
|
|
##
|
|
|
- # @query-alarm-clock
|
|
|
+ # @query-option-roms:
|
|
|
#
|
|
|
- # Return information about QEMU's alarm clock.
|
|
|
+ # Query information on ROMs loaded into the option ROM space.
|
|
|
#
|
|
|
- # Returns a @QemuAlarmClock instance describing the alarm clock method
|
|
|
- # being currently used by QEMU (this is usually set by the '-clock'
|
|
|
- # command-line option).
|
|
|
+ # Returns: OptionRomInfo
|
|
|
#
|
|
|
- # Since: 1.0
|
|
|
+ # Since: 9.0
|
|
|
##
|
|
|
- { 'command': 'query-alarm-clock', 'returns': 'QemuAlarmClock' }
|
|
|
+ { 'command': 'query-option-roms',
|
|
|
+ 'returns': ['OptionRomInfo'] }
|
|
|
|
|
|
Notice the "returns" keyword. As its name suggests, it's used to define the
|
|
|
data returned by a command.
|
|
|
|
|
|
-It's time to implement the qmp_query_alarm_clock() function, you can put it
|
|
|
-in the qemu-timer.c file::
|
|
|
+Notice the syntax ['OptionRomInfo']". This should be read as "returns
|
|
|
+a list of OptionRomInfo".
|
|
|
|
|
|
- QemuAlarmClock *qmp_query_alarm_clock(Error **errp)
|
|
|
- {
|
|
|
- QemuAlarmClock *clock;
|
|
|
- int64_t deadline;
|
|
|
-
|
|
|
- clock = g_malloc0(sizeof(*clock));
|
|
|
+It's time to implement the qmp_query_option_roms() function. Add to
|
|
|
+monitor/qmp-cmds.c::
|
|
|
|
|
|
- deadline = qemu_next_alarm_deadline();
|
|
|
- if (deadline > 0) {
|
|
|
- clock->has_next_deadline = true;
|
|
|
- clock->next_deadline = deadline;
|
|
|
+ OptionRomInfoList *qmp_query_option_roms(Error **errp)
|
|
|
+ {
|
|
|
+ OptionRomInfoList *info_list = NULL;
|
|
|
+ OptionRomInfoList **tailp = &info_list;
|
|
|
+ OptionRomInfo *info;
|
|
|
+
|
|
|
+ for (int i = 0; i < nb_option_roms; i++) {
|
|
|
+ info = g_malloc0(sizeof(*info));
|
|
|
+ info->filename = g_strdup(option_rom[i].name);
|
|
|
+ info->has_bootindex = option_rom[i].bootindex >= 0;
|
|
|
+ if (info->has_bootindex) {
|
|
|
+ info->bootindex = option_rom[i].bootindex;
|
|
|
+ }
|
|
|
+ QAPI_LIST_APPEND(tailp, info);
|
|
|
}
|
|
|
- clock->clock_name = g_strdup(alarm_timer->name);
|
|
|
|
|
|
- return clock;
|
|
|
+ return info_list;
|
|
|
}
|
|
|
|
|
|
There are a number of things to be noticed:
|
|
|
|
|
|
-1. The QemuAlarmClock type is automatically generated by the QAPI framework,
|
|
|
- its members correspond to the type's specification in the schema file
|
|
|
-2. As specified in the schema file, the function returns a QemuAlarmClock
|
|
|
- instance and takes no arguments (besides the "errp" one, which is mandatory
|
|
|
- for all QMP functions)
|
|
|
-3. The "clock" variable (which will point to our QAPI type instance) is
|
|
|
- allocated by the regular g_malloc0() function. Note that we chose to
|
|
|
- initialize the memory to zero. This is recommended for all QAPI types, as
|
|
|
- it helps avoiding bad surprises (specially with booleans)
|
|
|
-4. Remember that "next_deadline" is optional? Non-pointer optional
|
|
|
- members have a 'has_TYPE_NAME' member that should be properly set
|
|
|
+1. Type OptionRomInfo is automatically generated by the QAPI framework,
|
|
|
+ its members correspond to the type's specification in the schema
|
|
|
+ file
|
|
|
+2. Type OptionRomInfoList is also generated. It's a singly linked
|
|
|
+ list.
|
|
|
+3. As specified in the schema file, the function returns a
|
|
|
+ OptionRomInfoList, and takes no arguments (besides the "errp" one,
|
|
|
+ which is mandatory for all QMP functions)
|
|
|
+4. The returned object is dynamically allocated
|
|
|
+5. All strings are dynamically allocated. This is so because QAPI also
|
|
|
+ generates a function to free its types and it cannot distinguish
|
|
|
+ between dynamically or statically allocated strings
|
|
|
+6. Remember that "bootindex" is optional? As a non-pointer optional
|
|
|
+ member, it comes with a 'has_bootindex' member that needs to be set
|
|
|
by the implementation, as shown above
|
|
|
-5. Even static strings, such as "alarm_timer->name", should be dynamically
|
|
|
- allocated by the implementation. This is so because the QAPI also generates
|
|
|
- a function to free its types and it cannot distinguish between dynamically
|
|
|
- or statically allocated strings
|
|
|
-6. You have to include "qapi/qapi-commands-misc.h" in qemu-timer.c
|
|
|
|
|
|
Time to test the new command. Build qemu, run it as described in the "Testing"
|
|
|
section and try this::
|
|
|
|
|
|
- { "execute": "query-alarm-clock" }
|
|
|
+ { "execute": "query-option-rom" }
|
|
|
{
|
|
|
- "return": {
|
|
|
- "next-deadline": 2368219,
|
|
|
- "clock-name": "dynticks"
|
|
|
- }
|
|
|
+ "return": [
|
|
|
+ {
|
|
|
+ "filename": "kvmvapic.bin"
|
|
|
+ }
|
|
|
+ ]
|
|
|
}
|
|
|
|
|
|
|
|
|
The HMP command
|
|
|
~~~~~~~~~~~~~~~
|
|
|
|
|
|
-Here's the HMP counterpart of the query-alarm-clock command::
|
|
|
+Here's the HMP counterpart of the query-option-roms command::
|
|
|
|
|
|
- void hmp_info_alarm_clock(Monitor *mon)
|
|
|
+ void hmp_info_option_roms(Monitor *mon, const QDict *qdict)
|
|
|
{
|
|
|
- QemuAlarmClock *clock;
|
|
|
Error *err = NULL;
|
|
|
+ OptionRomInfoList *info_list, *tail;
|
|
|
+ OptionRomInfo *info;
|
|
|
|
|
|
- clock = qmp_query_alarm_clock(&err);
|
|
|
+ info_list = qmp_query_option_roms(&err);
|
|
|
if (hmp_handle_error(mon, err)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- monitor_printf(mon, "Alarm clock method in use: '%s'\n", clock->clock_name);
|
|
|
- if (clock->has_next_deadline) {
|
|
|
- monitor_printf(mon, "Next alarm will fire in %" PRId64 " nanoseconds\n",
|
|
|
- clock->next_deadline);
|
|
|
+ for (tail = info_list; tail; tail = tail->next) {
|
|
|
+ info = tail->value;
|
|
|
+ monitor_printf(mon, "%s", info->filename);
|
|
|
+ if (info->has_bootindex) {
|
|
|
+ monitor_printf(mon, " %" PRId64, info->bootindex);
|
|
|
+ }
|
|
|
+ monitor_printf(mon, "\n");
|
|
|
}
|
|
|
|
|
|
- qapi_free_QemuAlarmClock(clock);
|
|
|
+ qapi_free_OptionRomInfoList(info_list);
|
|
|
}
|
|
|
|
|
|
-It's important to notice that hmp_info_alarm_clock() calls
|
|
|
-qapi_free_QemuAlarmClock() to free the data returned by qmp_query_alarm_clock().
|
|
|
-For user defined types, the QAPI will generate a qapi_free_QAPI_TYPE_NAME()
|
|
|
-function and that's what you have to use to free the types you define and
|
|
|
-qapi_free_QAPI_TYPE_NAMEList() for list types (explained in the next section).
|
|
|
-If the QMP call returns a string, then you should g_free() to free it.
|
|
|
-
|
|
|
-Also note that hmp_info_alarm_clock() performs error handling. That's not
|
|
|
-strictly required if you're sure the QMP function doesn't return errors, but
|
|
|
-it's good practice to always check for errors.
|
|
|
-
|
|
|
-Another important detail is that HMP's "info" commands don't go into the
|
|
|
-hmp-commands.hx. Instead, they go into the info_cmds[] table, which is defined
|
|
|
-in the monitor/misc.c file. The entry for the "info alarmclock" follows::
|
|
|
-
|
|
|
- {
|
|
|
- .name = "alarmclock",
|
|
|
- .args_type = "",
|
|
|
- .params = "",
|
|
|
- .help = "show information about the alarm clock",
|
|
|
- .cmd = hmp_info_alarm_clock,
|
|
|
- },
|
|
|
+It's important to notice that hmp_info_option_roms() calls
|
|
|
+qapi_free_OptionRomInfoList() to free the data returned by
|
|
|
+qmp_query_option_roms(). For user defined types, QAPI will generate a
|
|
|
+qapi_free_QAPI_TYPE_NAME() function, and that's what you have to use to
|
|
|
+free the types you define and qapi_free_QAPI_TYPE_NAMEList() for list
|
|
|
+types (explained in the next section). If the QMP function returns a
|
|
|
+string, then you should g_free() to free it.
|
|
|
+
|
|
|
+Also note that hmp_info_option_roms() performs error handling. That's
|
|
|
+not strictly required when you're sure the QMP function doesn't return
|
|
|
+errors; you could instead pass it &error_abort then.
|
|
|
+
|
|
|
+Another important detail is that HMP's "info" commands go into
|
|
|
+hmp-commands-info.hx, not hmp-commands.hx. The entry for the "info
|
|
|
+option-roms" follows::
|
|
|
+
|
|
|
+ {
|
|
|
+ .name = "option-roms",
|
|
|
+ .args_type = "",
|
|
|
+ .params = "",
|
|
|
+ .help = "show roms",
|
|
|
+ .cmd = hmp_info_option_roms,
|
|
|
+ },
|
|
|
+ SRST
|
|
|
+ ``info option-roms``
|
|
|
+ Show the option ROMs.
|
|
|
+ ERST
|
|
|
|
|
|
-To test this, run qemu and type "info alarmclock" in the user monitor.
|
|
|
+To test this, run qemu and type "info option-roms" in the user monitor.
|
|
|
|
|
|
|
|
|
-Returning Lists
|
|
|
-~~~~~~~~~~~~~~~
|
|
|
+Writing a debugging aid returning unstructured text
|
|
|
+---------------------------------------------------
|
|
|
|
|
|
-For this example, we're going to return all available methods for the timer
|
|
|
-alarm, which is pretty much what the command-line option "-clock ?" does,
|
|
|
-except that we're also going to inform which method is in use.
|
|
|
+As discussed in section `Modelling data in QAPI`_, it is required that
|
|
|
+commands expecting machine usage be using fine-grained QAPI data types.
|
|
|
+The exception to this rule applies when the command is solely intended
|
|
|
+as a debugging aid and allows for returning unstructured text, such as
|
|
|
+a query command that report aspects of QEMU's internal state that are
|
|
|
+useful only to human operators.
|
|
|
|
|
|
-This first step is to define a new type::
|
|
|
+In this example we will consider the existing QMP command
|
|
|
+``x-query-roms`` in qapi/machine.json. It has no parameters and
|
|
|
+returns a ``HumanReadableText``::
|
|
|
|
|
|
##
|
|
|
- # @TimerAlarmMethod
|
|
|
- #
|
|
|
- # Timer alarm method information.
|
|
|
+ # @x-query-roms:
|
|
|
#
|
|
|
- # @method-name: The method's name.
|
|
|
+ # Query information on the registered ROMS
|
|
|
#
|
|
|
- # @current: true if this alarm method is currently in use, false otherwise
|
|
|
+ # Features:
|
|
|
#
|
|
|
- # Since: 1.0
|
|
|
- ##
|
|
|
- { 'type': 'TimerAlarmMethod',
|
|
|
- 'data': { 'method-name': 'str', 'current': 'bool' } }
|
|
|
-
|
|
|
-The command will be called "query-alarm-methods", here is its schema
|
|
|
-specification::
|
|
|
-
|
|
|
- ##
|
|
|
- # @query-alarm-methods
|
|
|
+ # @unstable: This command is meant for debugging.
|
|
|
#
|
|
|
- # Returns information about available alarm methods.
|
|
|
+ # Returns: registered ROMs
|
|
|
#
|
|
|
- # Returns: a list of @TimerAlarmMethod for each method
|
|
|
- #
|
|
|
- # Since: 1.0
|
|
|
+ # Since: 6.2
|
|
|
##
|
|
|
- { 'command': 'query-alarm-methods', 'returns': ['TimerAlarmMethod'] }
|
|
|
-
|
|
|
-Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this
|
|
|
-should be read as "returns a list of TimerAlarmMethod instances".
|
|
|
-
|
|
|
-The C implementation follows::
|
|
|
-
|
|
|
- TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
|
|
|
- {
|
|
|
- TimerAlarmMethodList *method_list = NULL;
|
|
|
- const struct qemu_alarm_timer *p;
|
|
|
- bool current = true;
|
|
|
-
|
|
|
- for (p = alarm_timers; p->name; p++) {
|
|
|
- TimerAlarmMethod *value = g_malloc0(*value);
|
|
|
- value->method_name = g_strdup(p->name);
|
|
|
- value->current = current;
|
|
|
- QAPI_LIST_PREPEND(method_list, value);
|
|
|
- current = false;
|
|
|
- }
|
|
|
-
|
|
|
- return method_list;
|
|
|
- }
|
|
|
-
|
|
|
-The most important difference from the previous examples is the
|
|
|
-TimerAlarmMethodList type, which is automatically generated by the QAPI from
|
|
|
-the TimerAlarmMethod type.
|
|
|
-
|
|
|
-Each list node is represented by a TimerAlarmMethodList instance. We have to
|
|
|
-allocate it, and that's done inside the for loop: the "info" pointer points to
|
|
|
-an allocated node. We also have to allocate the node's contents, which is
|
|
|
-stored in its "value" member. In our example, the "value" member is a pointer
|
|
|
-to an TimerAlarmMethod instance.
|
|
|
-
|
|
|
-Notice that the "current" variable is used as "true" only in the first
|
|
|
-iteration of the loop. That's because the alarm timer method in use is the
|
|
|
-first element of the alarm_timers array. Also notice that QAPI lists are handled
|
|
|
-by hand and we return the head of the list.
|
|
|
-
|
|
|
-Now Build qemu, run it as explained in the "Testing" section and try our new
|
|
|
-command::
|
|
|
-
|
|
|
- { "execute": "query-alarm-methods" }
|
|
|
- {
|
|
|
- "return": [
|
|
|
- {
|
|
|
- "current": false,
|
|
|
- "method-name": "unix"
|
|
|
- },
|
|
|
- {
|
|
|
- "current": true,
|
|
|
- "method-name": "dynticks"
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
-
|
|
|
-The HMP counterpart is a bit more complex than previous examples because it
|
|
|
-has to traverse the list, it's shown below for reference::
|
|
|
-
|
|
|
- void hmp_info_alarm_methods(Monitor *mon)
|
|
|
- {
|
|
|
- TimerAlarmMethodList *method_list, *method;
|
|
|
- Error *err = NULL;
|
|
|
-
|
|
|
- method_list = qmp_query_alarm_methods(&err);
|
|
|
- if (hmp_handle_error(mon, err)) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- for (method = method_list; method; method = method->next) {
|
|
|
- monitor_printf(mon, "%c %s\n", method->value->current ? '*' : ' ',
|
|
|
- method->value->method_name);
|
|
|
- }
|
|
|
-
|
|
|
- qapi_free_TimerAlarmMethodList(method_list);
|
|
|
- }
|
|
|
-
|
|
|
-Writing a debugging aid returning unstructured text
|
|
|
----------------------------------------------------
|
|
|
-
|
|
|
-As discussed in section `Modelling data in QAPI`_, it is required that
|
|
|
-commands expecting machine usage be using fine-grained QAPI data types.
|
|
|
-The exception to this rule applies when the command is solely intended
|
|
|
-as a debugging aid and allows for returning unstructured text. This is
|
|
|
-commonly needed for query commands that report aspects of QEMU's
|
|
|
-internal state that are useful to human operators.
|
|
|
-
|
|
|
-In this example we will consider a simplified variant of the HMP
|
|
|
-command ``info roms``. Following the earlier rules, this command will
|
|
|
-need to live under the ``x-`` name prefix, so its QMP implementation
|
|
|
-will be called ``x-query-roms``. It will have no parameters and will
|
|
|
-return a single text string::
|
|
|
-
|
|
|
- { 'struct': 'HumanReadableText',
|
|
|
- 'data': { 'human-readable-text': 'str' } }
|
|
|
-
|
|
|
{ 'command': 'x-query-roms',
|
|
|
- 'returns': 'HumanReadableText' }
|
|
|
+ 'returns': 'HumanReadableText',
|
|
|
+ 'features': [ 'unstable' ] }
|
|
|
|
|
|
-The ``HumanReadableText`` struct is intended to be used for all
|
|
|
-commands, under the ``x-`` name prefix that are returning unstructured
|
|
|
-text targeted at humans. It should never be used for commands outside
|
|
|
-the ``x-`` name prefix, as those should be using structured QAPI types.
|
|
|
+The ``HumanReadableText`` struct is defined in qapi/common.json as a
|
|
|
+struct with a string member. It is intended to be used for all
|
|
|
+commands that are returning unstructured text targeted at
|
|
|
+humans. These should all have feature 'unstable'. Note that the
|
|
|
+feature's documentation states why the command is unstable. We
|
|
|
+commonly use a ``x-`` command name prefix to make lack of stability
|
|
|
+obvious to human users.
|
|
|
|
|
|
Implementing the QMP command
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
The QMP implementation will typically involve creating a ``GString``
|
|
|
-object and printing formatted data into it::
|
|
|
+object and printing formatted data into it, like this::
|
|
|
|
|
|
HumanReadableText *qmp_x_query_roms(Error **errp)
|
|
|
{
|
|
@@ -698,6 +595,9 @@ object and printing formatted data into it::
|
|
|
return human_readable_text_from_str(buf);
|
|
|
}
|
|
|
|
|
|
+The actual implementation emits more information. You can find it in
|
|
|
+hw/core/loader.c.
|
|
|
+
|
|
|
|
|
|
Implementing the HMP command
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -706,7 +606,7 @@ Now that the QMP command is in place, we can also make it available in
|
|
|
the human monitor (HMP) as shown in previous examples. The HMP
|
|
|
implementations will all look fairly similar, as all they need do is
|
|
|
invoke the QMP command and then print the resulting text or error
|
|
|
-message. Here's the implementation of the "info roms" HMP command::
|
|
|
+message. Here's an implementation of the "info roms" HMP command::
|
|
|
|
|
|
void hmp_info_roms(Monitor *mon, const QDict *qdict)
|
|
|
{
|
|
@@ -746,3 +646,5 @@ field NULL::
|
|
|
.help = "show roms",
|
|
|
.cmd_info_hrt = qmp_x_query_roms,
|
|
|
},
|
|
|
+
|
|
|
+This is how the actual HMP command is done.
|