qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Interested in contributing to QEMU


From: John Snow
Subject: Re: Interested in contributing to QEMU
Date: Mon, 15 Feb 2021 19:10:29 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.6.0

On 2/12/21 7:10 AM, Niteesh G. S. wrote:
Hello John,

On Wed, Feb 10, 2021 at 10:33 PM John Snow <jsnow@redhat.com <mailto:jsnow@redhat.com>> wrote:


[...]


    OK: I think I need to be careful about "issuing" work to someone who
    isn't (yet) accepted into the program -- I shouldn't misrepresent this
    arrangement -- but I can give you some more research tips that may help
    you find your footing.

    We can work on getting to know QMP a bit better; it sounds like it'd be
    relevant for both projects.

    Try using '-qmp qmp.sock,server,nowait' when you boot up QEMU and then
    open the qmp.sock file with socat and try messing with it.

    Try going to ./qapi/ in the source tree and "git grep event" to find
    some event definitions. try grepping for that event name in the QEMU
    tree at large and try to work out how QEMU emits these events.

    Try *adding* an event somewhere in ./qapi/ and modifying QEMU to emit
    this event. Try using rlwrap and socat to connect to this QMP socket
    and
    verify that your event is being sent over the wire. Depending on where
    you add the event, it may be helpful to start QEMU in a paused state
    and
    issue a resume command from QMP to make sure you have time to
    connect to
    the socket.

I added an event that is emitted every keypress. It also sends the qcode of the key pressed. https://github.com/gs-niteesh/qemu/pull/1/commits/1684f1f499e67ec4af5f75d0cc09eb1ecf9be709 <https://github.com/gs-niteesh/qemu/pull/1/commits/1684f1f499e67ec4af5f75d0cc09eb1ecf9be709> After doing this, I think I have a basic understanding of how the event stuff works and also
what happens when a command is issued from the shell.

Good!

I have summarized my understanding below, please correct me if I am wrong anywhere.

1) The JSON files under qemu/qapi define the QMP messages. These JSON files are then
compiled into their C representations during the build time.

Yep! They are processed using the scripts/qapi/ python package, the QAPI generator, which builds those definitions into concrete C types, wires up the command handlers for the QMP socket, and so on.

2) These are then registered using qmp_register_command.

Yeah, but in most cases the code generator actually handles this part for you. Every QMP command we have is (to my knowledge) defined as a 'command' in the JSON files.

All one has to do as the implementor is to write a function named "qmp_my_command_name" with the correct arguments and types. (And make sure it gets linked into the final binary!)

3) When a QMP request is initiated, the commands respective C function is found from the registered list of commands and is dispatched. One of the main functions responsible for the finding and dispatching of qmp_* functions is qmp_dispatch in qapi/qmp-dispatch.c. Which is invoked from monitor/qmp.c upon a QMP request. The result is then published to the user
through monitor_qmp_respond -> qmp_send_response.

I believe so. I haven't actually looked too closely at how the API wrangler/dispatcher code works. The high-level abstraction is actually pretty good in most cases.

Similar stuff happens to events too, the difference being, the function definitions are autogenerated depending on their schema, whereas for commands only the function prototypes are generated. TheĀ events can be emitted through qapi_event_send_EVENT_NAME functions. These functions convert C to JSON and call qapi_event_emit which then finally calls the monitor function to display an
event to the user.


Yep, exactly.

Few things I couldn't figure out and understand are
1) Who informs the monitor that the command is been issued? Since there are many ways to connect to the monitor, I think there should be a generic API which informs about input data.
But I can't find the code behind all this.

Yes. monitor/qmp.c handles the implementation of the monitor, but doesn't specify the actual transports for how the data arrives.

We rely on the chardev for that. See the signature for monitor_init_qmp, which receives a "chardev" and then uses it to start listening for data.

Before sending this mail, I decided to give this another try and found
qemu_chr_fe_set_handlers is responsible for registerĀ the handlers for input and output. Is that
right? And also does chr_fe mean character_front_end?


QEMU likes to separate out the idea of a frontend and a backend to a device. A virtual device presented to a guest as some specific model of hardware is the frontend.

The way we achieve the functionality of that device on the user's physical machine is the device backend. For character devices, (chardev), the backend might just be stdio on your terminal.

...QMP is acting kind of like a frontend device in that it's a user of a backend, but it's not really a guest-facing device. FE/BE distinctions get kind of weird at times for that reason.

2) I couldn't understand QEMU co-routines in general. In this case, I couldn't understand the coroutine code in qmp_dispatch in qapi/qmp-dispatch.c. Also please explain OOB in simple terms? How are they different from normal commands? And also their relation with coroutines.


Coroutines are a type of "cooperative" user scheduling. In Linux, this means that the user process itself switching between tasks at its own discretion, independent of the Linux scheduler.

It is "cooperative" because each task needs to indicate when it is ready to yield, they are not pre-empted. When a task needs to wait for an operation to be ready, it can yield to allow another task to run.

In C on Linux, you could implement this with stackswaps (makecontext, swapcontext, setcontext and so on), but there are other ways, and other OSes that need an implementation. Look at `coroutine-ucontext.c` for one possible implementation.

QMP uses them to dispatch certain commands; those marked as such in those qapi JSON files. Look at the definition for 'block_resize'.

OOB commands are complicated, check the docs/devel/qmp-spec.txt file for more info on those. Simply (with lots of caveats and gotchas) is that QMP commands are processed one at a time in FIFO order. OOB commands, however, will "skip the queue" and may be processed immediately. That's roughly why "OOB" exists; it's to send critical commands like "cancel" or "exit" to try and un-jam QEMU when it gets stuck processing a previous command.

Because of this, the handling over what threading context we execute those commands in is handled a little differently / more carefully.

Thanks,
Niteesh.


--js




reply via email to

[Prev in Thread] Current Thread [Next in Thread]