|
|
|
@ -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,10 +108,14 @@ 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 |
|
|
|
schema entries are JSON objects. The line above will instruct the QAPI to |
|
|
|
The "command" keyword defines a new QMP command. It instructs QAPI to |
|
|
|
generate any prototypes and the necessary code to marshal and unmarshal |
|
|
|
protocol data. |
|
|
|
|
|
|
|
@ -132,57 +137,70 @@ There are a few things to be noticed: |
|
|
|
3. It takes an "Error \*\*" argument. This is required. Later we will see how to |
|
|
|
return errors and take additional arguments. The Error argument should not |
|
|
|
be touched if the command doesn't return errors |
|
|
|
4. We won't add the function's prototype. That's automatically done by the QAPI |
|
|
|
4. We won't add the function's prototype. That's automatically done by QAPI |
|
|
|
5. Printing to the terminal is discouraged for QMP commands, we do it here |
|
|
|
because it's the easiest way to demonstrate a QMP command |
|
|
|
|
|
|
|
You're done. Now build qemu, run it as suggested in the "Testing" section, |
|
|
|
You're done. Now build QEMU, run it as suggested in the "Testing" section, |
|
|
|
and then type the following QMP command:: |
|
|
|
|
|
|
|
{ "execute": "hello-world" } |
|
|
|
|
|
|
|
Then check the terminal running qemu and look for the "Hello, world" string. If |
|
|
|
Then check the terminal running QEMU and look for the "Hello, world" string. If |
|
|
|
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 |
|
|
|
|
|
|
|
Time to test our new version of the "hello-world" command. Build qemu, run it as |
|
|
|
Time to test our new version of the "hello-world" command. Build QEMU, run it as |
|
|
|
described in the "Testing" section and then send two commands:: |
|
|
|
|
|
|
|
{ "execute": "hello-world" } |
|
|
|
@ -191,13 +209,13 @@ described in the "Testing" section and then send two commands:: |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
{ "execute": "hello-world", "arguments": { "message": "We love qemu" } } |
|
|
|
{ "execute": "hello-world", "arguments": { "message": "We love QEMU" } } |
|
|
|
{ |
|
|
|
"return": { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
You should see "Hello, world" and "We love qemu" in the terminal running qemu, |
|
|
|
You should see "Hello, world" and "We love QEMU" in the terminal running QEMU, |
|
|
|
if you don't see these strings, then something went wrong. |
|
|
|
|
|
|
|
|
|
|
|
@ -227,7 +245,7 @@ The first argument to the error_setg() function is the Error pointer |
|
|
|
to pointer, which is passed to all QMP functions. The next argument is a human |
|
|
|
description of the error, this is a free-form printf-like string. |
|
|
|
|
|
|
|
Let's test the example above. Build qemu, run it as defined in the "Testing" |
|
|
|
Let's test the example above. Build QEMU, run it as defined in the "Testing" |
|
|
|
section, and then issue the following command:: |
|
|
|
|
|
|
|
{ "execute": "hello-world", "arguments": { "message": "all you need is love" } } |
|
|
|
@ -254,44 +272,14 @@ 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 |
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
|
|
|
|
|
|
Now that the QMP command is in place, we can also make it available in the human |
|
|
|
monitor (HMP). |
|
|
|
|
|
|
|
With the introduction of the QAPI, HMP commands make QMP calls. Most of the |
|
|
|
time HMP commands are simple wrappers. All HMP commands implementation exist in |
|
|
|
the monitor/hmp-cmds.c file. |
|
|
|
With the introduction of QAPI, HMP commands make QMP calls. Most of the |
|
|
|
time HMP commands are simple wrappers. |
|
|
|
|
|
|
|
Here's the implementation of the "hello-world" HMP command:: |
|
|
|
|
|
|
|
@ -306,18 +294,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, |
|
|
|
@ -340,17 +330,17 @@ To test this you have to open a user monitor and issue the "hello-world" |
|
|
|
command. It might be instructive to check the command's documentation with |
|
|
|
HMP's "help" command. |
|
|
|
|
|
|
|
Please, check the "-monitor" command-line option to know how to open a user |
|
|
|
Please check the "-monitor" command-line option to know how to open a user |
|
|
|
monitor. |
|
|
|
|
|
|
|
|
|
|
|
Writing more complex commands |
|
|
|
----------------------------- |
|
|
|
|
|
|
|
A QMP command is capable of returning any data the QAPI supports like integers, |
|
|
|
A QMP command is capable of returning any data QAPI supports like integers, |
|
|
|
strings, booleans, enumerations and user defined types. |
|
|
|
|
|
|
|
In this section we will focus on user defined types. Please, check the QAPI |
|
|
|
In this section we will focus on user defined types. Please check the QAPI |
|
|
|
documentation for information about the other types. |
|
|
|
|
|
|
|
|
|
|
|
@ -372,7 +362,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 +376,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" |
|
|
|
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 +593,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 +604,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 +644,5 @@ field NULL:: |
|
|
|
.help = "show roms", |
|
|
|
.cmd_info_hrt = qmp_x_query_roms, |
|
|
|
}, |
|
|
|
|
|
|
|
This is how the actual HMP command is done. |
|
|
|
|