|  | .. | 
|  | 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 |