123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- ..
- Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
- Copyright (c) 2019, Linaro Limited
- Written by Emilio Cota and Alex Bennée
- .. _TCG Plugins:
- QEMU TCG Plugins
- ================
- Writing plugins
- ---------------
- API versioning
- ~~~~~~~~~~~~~~
- This is a new feature for QEMU and it does allow people to develop
- out-of-tree plugins that can be dynamically linked into a running QEMU
- process. However the project reserves the right to change or break the
- API should it need to do so. The best way to avoid this is to submit
- your plugin upstream so they can be updated if/when the API changes.
- All plugins need to declare a symbol which exports the plugin API
- version they were built against. This can be done simply by::
- QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
- The core code will refuse to load a plugin that doesn't export a
- ``qemu_plugin_version`` symbol or if plugin version is outside of QEMU's
- supported range of API versions.
- Additionally the ``qemu_info_t`` structure which is passed to the
- ``qemu_plugin_install`` method of a plugin will detail the minimum and
- current API versions supported by QEMU. The API version will be
- incremented if new APIs are added. The minimum API version will be
- incremented if existing APIs are changed or removed.
- Lifetime of the query handle
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Each callback provides an opaque anonymous information handle which
- can usually be further queried to find out information about a
- translation, instruction or operation. The handles themselves are only
- valid during the lifetime of the callback so it is important that any
- information that is needed is extracted during the callback and saved
- by the plugin.
- Plugin life cycle
- ~~~~~~~~~~~~~~~~~
- First the plugin is loaded and the public qemu_plugin_install function
- is called. The plugin will then register callbacks for various plugin
- events. Generally plugins will register a handler for the *atexit*
- if they want to dump a summary of collected information once the
- program/system has finished running.
- When a registered event occurs the plugin callback is invoked. The
- callbacks may provide additional information. In the case of a
- translation event the plugin has an option to enumerate the
- instructions in a block of instructions and optionally register
- callbacks to some or all instructions when they are executed.
- There is also a facility to add inline instructions doing various operations,
- like adding or storing an immediate value. It is also possible to execute a
- callback conditionally, with condition being evaluated inline. All those inline
- operations are associated to a ``scoreboard``, which is a thread-local storage
- automatically expanded when new cores/threads are created and that can be
- accessed/modified in a thread-safe way without any lock needed. Combining inline
- operations and conditional callbacks offer a more efficient way to instrument
- binaries, compared to classic callbacks.
- Finally when QEMU exits all the registered *atexit* callbacks are
- invoked.
- Exposure of QEMU internals
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
- The plugin architecture actively avoids leaking implementation details
- about how QEMU's translation works to the plugins. While there are
- conceptions such as translation time and translation blocks the
- details are opaque to plugins. The plugin is able to query select
- details of instructions and system configuration only through the
- exported *qemu_plugin* functions.
- However the following assumptions can be made:
- Translation Blocks
- ++++++++++++++++++
- All code will go through a translation phase although not all
- translations will be necessarily be executed. You need to instrument
- actual executions to track what is happening.
- It is quite normal to see the same address translated multiple times.
- If you want to track the code in system emulation you should examine
- the underlying physical address (``qemu_plugin_insn_haddr``) to take
- into account the effects of virtual memory although if the system does
- paging this will change too.
- Not all instructions in a block will always execute so if its
- important to track individual instruction execution you need to
- instrument them directly. However asynchronous interrupts will not
- change control flow mid-block.
- Instructions
- ++++++++++++
- Instruction instrumentation runs before the instruction executes. You
- can be can be sure the instruction will be dispatched, but you can't
- be sure it will complete. Generally this will be because of a
- synchronous exception (e.g. SIGILL) triggered by the instruction
- attempting to execute. If you want to be sure you will need to
- instrument the next instruction as well. See the ``execlog.c`` plugin
- for examples of how to track this and finalise details after execution.
- Memory Accesses
- +++++++++++++++
- Memory callbacks are called after a successful load or store.
- Unsuccessful operations (i.e. faults) will not be visible to memory
- instrumentation although the execution side effects can be observed
- (e.g. entering a exception handler).
- System Idle and Resume States
- +++++++++++++++++++++++++++++
- The ``qemu_plugin_register_vcpu_idle_cb`` and
- ``qemu_plugin_register_vcpu_resume_cb`` functions can be used to track
- when CPUs go into and return from sleep states when waiting for
- external I/O. Be aware though that these may occur less frequently
- than in real HW due to the inefficiencies of emulation giving less
- chance for the CPU to idle.
- Internals
- ---------
- Locking
- ~~~~~~~
- We have to ensure we cannot deadlock, particularly under MTTCG. For
- this we acquire a lock when called from plugin code. We also keep the
- list of callbacks under RCU so that we do not have to hold the lock
- when calling the callbacks. This is also for performance, since some
- callbacks (e.g. memory access callbacks) might be called very
- frequently.
- * A consequence of this is that we keep our own list of CPUs, so that
- we do not have to worry about locking order wrt cpu_list_lock.
- * Use a recursive lock, since we can get registration calls from
- callbacks.
- As a result registering/unregistering callbacks is "slow", since it
- takes a lock. But this is very infrequent; we want performance when
- calling (or not calling) callbacks, not when registering them. Using
- RCU is great for this.
- We support the uninstallation of a plugin at any time (e.g. from
- plugin callbacks). This allows plugins to remove themselves if they no
- longer want to instrument the code. This operation is asynchronous
- which means callbacks may still occur after the uninstall operation is
- requested. The plugin isn't completely uninstalled until the safe work
- has executed while all vCPUs are quiescent.
- Plugin API
- ==========
- The following API is generated from the inline documentation in
- ``include/qemu/qemu-plugin.h``. Please ensure any updates to the API
- include the full kernel-doc annotations.
- .. kernel-doc:: include/qemu/qemu-plugin.h
|