aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/memory.txt172
-rw-r--r--docs/qapi-code-gen.txt316
2 files changed, 488 insertions, 0 deletions
diff --git a/docs/memory.txt b/docs/memory.txt
new file mode 100644
index 0000000000..4460c0641a
--- /dev/null
+++ b/docs/memory.txt
@@ -0,0 +1,172 @@
+The memory API
+==============
+
+The memory API models the memory and I/O buses and controllers of a QEMU
+machine. It attempts to allow modelling of:
+
+ - ordinary RAM
+ - memory-mapped I/O (MMIO)
+ - memory controllers that can dynamically reroute physical memory regions
+ to different destinations
+
+The memory model provides support for
+
+ - tracking RAM changes by the guest
+ - setting up coalesced memory for kvm
+ - setting up ioeventfd regions for kvm
+
+Memory is modelled as an tree (really acyclic graph) of MemoryRegion objects.
+The root of the tree is memory as seen from the CPU's viewpoint (the system
+bus). Nodes in the tree represent other buses, memory controllers, and
+memory regions that have been rerouted. Leaves are RAM and MMIO regions.
+
+Types of regions
+----------------
+
+There are four types of memory regions (all represented by a single C type
+MemoryRegion):
+
+- RAM: a RAM region is simply a range of host memory that can be made available
+ to the guest.
+
+- MMIO: a range of guest memory that is implemented by host callbacks;
+ each read or write causes a callback to be called on the host.
+
+- container: a container simply includes other memory regions, each at
+ a different offset. Containers are useful for grouping several regions
+ into one unit. For example, a PCI BAR may be composed of a RAM region
+ and an MMIO region.
+
+ A container's subregions are usually non-overlapping. In some cases it is
+ useful to have overlapping regions; for example a memory controller that
+ can overlay a subregion of RAM with MMIO or ROM, or a PCI controller
+ that does not prevent card from claiming overlapping BARs.
+
+- alias: a subsection of another region. Aliases allow a region to be
+ split apart into discontiguous regions. Examples of uses are memory banks
+ used when the guest address space is smaller than the amount of RAM
+ addressed, or a memory controller that splits main memory to expose a "PCI
+ hole". Aliases may point to any type of region, including other aliases,
+ but an alias may not point back to itself, directly or indirectly.
+
+
+Region names
+------------
+
+Regions are assigned names by the constructor. For most regions these are
+only used for debugging purposes, but RAM regions also use the name to identify
+live migration sections. This means that RAM region names need to have ABI
+stability.
+
+Region lifecycle
+----------------
+
+A region is created by one of the constructor functions (memory_region_init*())
+and destroyed by the destructor (memory_region_destroy()). In between,
+a region can be added to an address space by using memory_region_add_subregion()
+and removed using memory_region_del_subregion(). Region attributes may be
+changed at any point; they take effect once the region becomes exposed to the
+guest.
+
+Overlapping regions and priority
+--------------------------------
+Usually, regions may not overlap each other; a memory address decodes into
+exactly one target. In some cases it is useful to allow regions to overlap,
+and sometimes to control which of an overlapping regions is visible to the
+guest. This is done with memory_region_add_subregion_overlap(), which
+allows the region to overlap any other region in the same container, and
+specifies a priority that allows the core to decide which of two regions at
+the same address are visible (highest wins).
+
+Visibility
+----------
+The memory core uses the following rules to select a memory region when the
+guest accesses an address:
+
+- all direct subregions of the root region are matched against the address, in
+ descending priority order
+ - if the address lies outside the region offset/size, the subregion is
+ discarded
+ - if the subregion is a leaf (RAM or MMIO), the seach terminates
+ - if the subregion is a container, the same algorithm is used within the
+ subregion (after the address is adjusted by the subregion offset)
+ - if the subregion is an alias, the search is continues at the alias target
+ (after the address is adjusted by the subregion offset and alias offset)
+
+Example memory map
+------------------
+
+system_memory: container@0-2^48-1
+ |
+ +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff)
+ |
+ +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
+ |
+ +---- vga-window: alias@0xa0000-0xbfffff ---> #pci (0xa0000-0xbffff)
+ | (prio 1)
+ |
+ +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
+
+pci (0-2^32-1)
+ |
+ +--- vga-area: container@0xa0000-0xbffff
+ | |
+ | +--- alias@0x00000-0x7fff ---> #vram (0x010000-0x017fff)
+ | |
+ | +--- alias@0x08000-0xffff ---> #vram (0x020000-0x027fff)
+ |
+ +---- vram: ram@0xe1000000-0xe1ffffff
+ |
+ +---- vga-mmio: mmio@0xe2000000-0xe200ffff
+
+ram: ram@0x00000000-0xffffffff
+
+The is a (simplified) PC memory map. The 4GB RAM block is mapped into the
+system address space via two aliases: "lomem" is a 1:1 mapping of the first
+3.5GB; "himem" maps the last 0.5GB at address 4GB. This leaves 0.5GB for the
+so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with
+4GB of memory.
+
+The memory controller diverts addresses in the range 640K-768K to the PCI
+address space. This is modeled using the "vga-window" alias, mapped at a
+higher priority so it obscures the RAM at the same addresses. The vga window
+can be removed by programming the memory controller; this is modelled by
+removing the alias and exposing the RAM underneath.
+
+The pci address space is not a direct child of the system address space, since
+we only want parts of it to be visible (we accomplish this using aliases).
+It has two subregions: vga-area models the legacy vga window and is occupied
+by two 32K memory banks pointing at two sections of the framebuffer.
+In addition the vram is mapped as a BAR at address e1000000, and an additional
+BAR containing MMIO registers is mapped after it.
+
+Note that if the guest maps a BAR outside the PCI hole, it would not be
+visible as the pci-hole alias clips it to a 0.5GB range.
+
+Attributes
+----------
+
+Various region attributes (read-only, dirty logging, coalesced mmio, ioeventfd)
+can be changed during the region lifecycle. They take effect once the region
+is made visible (which can be immediately, later, or never).
+
+MMIO Operations
+---------------
+
+MMIO regions are provided with ->read() and ->write() callbacks; in addition
+various constraints can be supplied to control how these callbacks are called:
+
+ - .valid.min_access_size, .valid.max_access_size define the access sizes
+ (in bytes) which the device accepts; accesses outside this range will
+ have device and bus specific behaviour (ignored, or machine check)
+ - .valid.aligned specifies that the device only accepts naturally aligned
+ accesses. Unaligned accesses invoke device and bus specific behaviour.
+ - .impl.min_access_size, .impl.max_access_size define the access sizes
+ (in bytes) supported by the *implementation*; other access sizes will be
+ emulated using the ones available. For example a 4-byte write will be
+ emulated using four 1-byte write, is .impl.max_access_size = 1.
+ - .impl.valid specifies that the *implementation* only supports unaligned
+ accesses; unaligned accesses will be emulated by two aligned accesses.
+ - .old_portio and .old_mmio can be used to ease porting from code using
+ cpu_register_io_memory() and register_ioport(). They should not be used
+ in new code.
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
new file mode 100644
index 0000000000..b7befb5e48
--- /dev/null
+++ b/docs/qapi-code-gen.txt
@@ -0,0 +1,316 @@
+= How to use the QAPI code generator =
+
+* Note: as of this writing, QMP does not use QAPI. Eventually QMP
+commands will be converted to use QAPI internally. The following
+information describes QMP/QAPI as it will exist after the
+conversion.
+
+QAPI is a native C API within QEMU which provides management-level
+functionality to internal/external users. For external
+users/processes, this interface is made available by a JSON-based
+QEMU Monitor protocol that is provided by the QMP server.
+
+To map QMP-defined interfaces to the native C QAPI implementations,
+a JSON-based schema is used to define types and function
+signatures, and a set of scripts is used to generate types/signatures,
+and marshaling/dispatch code. The QEMU Guest Agent also uses these
+scripts, paired with a seperate schema, to generate
+marshaling/dispatch code for the guest agent server running in the
+guest.
+
+This document will describe how the schemas, scripts, and resulting
+code is used.
+
+
+== QMP/Guest agent schema ==
+
+This file defines the types, commands, and events used by QMP. It should
+fully describe the interface used by QMP.
+
+This file is designed to be loosely based on JSON although it's technically
+executable Python. While dictionaries are used, they are parsed as
+OrderedDicts so that ordering is preserved.
+
+There are two basic syntaxes used, type definitions and command definitions.
+
+The first syntax defines a type and is represented by a dictionary. There are
+two kinds of types that are supported: complex user-defined types, and enums.
+
+A complex type is a dictionary containing a single key who's value is a
+dictionary. This corresponds to a struct in C or an Object in JSON. An
+example of a complex type is:
+
+ { 'type': 'MyType',
+ 'data' { 'member1': 'str', 'member2': 'int', '*member3': 'str } }
+
+The use of '*' as a prefix to the name means the member is optional. Optional
+members should always be added to the end of the dictionary to preserve
+backwards compatibility.
+
+An enumeration type is a dictionary containing a single key who's value is a
+list of strings. An example enumeration is:
+
+ { 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
+
+Generally speaking, complex types and enums should always use CamelCase for
+the type names.
+
+Commands are defined by using a list containing three members. The first
+member is the command name, the second member is a dictionary containing
+arguments, and the third member is the return type.
+
+An example command is:
+
+ { 'command': 'my-command',
+ 'data': { 'arg1': 'str', '*arg2': 'str' },
+ 'returns': 'str' ]
+
+Command names should be all lower case with words separated by a hyphen.
+
+
+== Code generation ==
+
+Schemas are fed into 3 scripts to generate all the code/files that, paired
+with the core QAPI libraries, comprise everything required to take JSON
+commands read in by a QMP/guest agent server, unmarshal the arguments into
+the underlying C types, call into the corresponding C function, and map the
+response back to a QMP/guest agent response to be returned to the user.
+
+As an example, we'll use the following schema, which describes a single
+complex user-defined type (which will produce a C struct, along with a list
+node structure that can be used to chain together a list of such types in
+case we want to accept/return a list of this type with a command), and a
+command which takes that type as a parameter and returns the same type:
+
+ mdroth@illuin:~/w/qemu2.git$ cat example-schema.json
+ { 'type': 'UserDefOne',
+ 'data': { 'integer': 'int', 'string': 'str' } }
+
+ { 'command': 'my-command',
+ 'data': {'arg1': 'UserDefOne'},
+ 'returns': 'UserDefOne' }
+ mdroth@illuin:~/w/qemu2.git$
+
+=== scripts/qapi-types.py ===
+
+Used to generate the C types defined by a schema. The following files are
+created:
+
+$(prefix)qapi-types.h - C types corresponding to types defined in
+ the schema you pass in
+$(prefix)qapi-types.c - Cleanup functions for the above C types
+
+The $(prefix) is an optional parameter used as a namespace to keep the
+generated code from one schema/code-generation separated from others so code
+can be generated/used from multiple schemas without clobbering previously
+created code.
+
+Example:
+
+ mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
+ --output-dir="qapi-generated" --prefix="example-" < example-schema.json
+ mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
+ /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+ #include "qapi/qapi-dealloc-visitor.h"
+ #include "example-qapi-types.h"
+ #include "example-qapi-visit.h"
+
+ void qapi_free_UserDefOne(UserDefOne * obj)
+ {
+ QapiDeallocVisitor *md;
+ Visitor *v;
+
+ if (!obj) {
+ return;
+ }
+
+ md = qapi_dealloc_visitor_new();
+ v = qapi_dealloc_get_visitor(md);
+ visit_type_UserDefOne(v, &obj, NULL, NULL);
+ qapi_dealloc_visitor_cleanup(md);
+ }
+
+ mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
+ /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+ #ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
+ #define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
+
+ #include "qapi/qapi-types-core.h"
+
+ typedef struct UserDefOne UserDefOne;
+
+ typedef struct UserDefOneList
+ {
+ UserDefOne *value;
+ struct UserDefOneList *next;
+ } UserDefOneList;
+
+ struct UserDefOne
+ {
+ int64_t integer;
+ char * string;
+ };
+
+ void qapi_free_UserDefOne(UserDefOne * obj);
+
+ #endif
+
+
+=== scripts/qapi-visit.py ===
+
+Used to generate the visitor functions used to walk through and convert
+a QObject (as provided by QMP) to a native C data structure and
+vice-versa, as well as the visitor function used to dealloc a complex
+schema-defined C type.
+
+The following files are generated:
+
+$(prefix)qapi-visit.c: visitor function for a particular C type, used
+ to automagically convert QObjects into the
+ corresponding C type and vice-versa, as well
+ as for deallocating memory for an existing C
+ type
+
+$(prefix)qapi-visit.h: declarations for previously mentioned visitor
+ functions
+
+Example:
+
+ mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
+ --output-dir="qapi-generated" --prefix="example-" < example-schema.json
+ mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
+ /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+ #include "example-qapi-visit.h"
+
+ void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
+ {
+ visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
+ visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
+ visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
+ visit_end_struct(m, errp);
+ }
+
+ void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
+ {
+ GenericList *i;
+
+ visit_start_list(m, name, errp);
+
+ for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
+ UserDefOneList *native_i = (UserDefOneList *)i;
+ visit_type_UserDefOne(m, &native_i->value, NULL, errp);
+ }
+
+ visit_end_list(m, errp);
+ }
+ mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
+ /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+ #ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
+ #define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
+
+ #include "qapi/qapi-visit-core.h"
+ #include "example-qapi-types.h"
+
+ void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
+ void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
+
+ #endif
+ mdroth@illuin:~/w/qemu2.git$
+
+
+=== scripts/qapi-commands.py ===
+
+Used to generate the marshaling/dispatch functions for the commands defined
+in the schema. The following files are generated:
+
+$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
+ QMP command defined in the schema. Functions
+ generated by qapi-visit.py are used to
+ convert QObjects recieved from the wire into
+ function parameters, and uses the same
+ visitor functions to convert native C return
+ values to QObjects from transmission back
+ over the wire.
+
+$(prefix)qmp-commands.h: Function prototypes for the QMP commands
+ specified in the schema.
+
+Example:
+
+ mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
+ /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+ #include "qemu-objects.h"
+ #include "qapi/qmp-core.h"
+ #include "qapi/qapi-visit-core.h"
+ #include "qapi/qmp-output-visitor.h"
+ #include "qapi/qmp-input-visitor.h"
+ #include "qapi/qapi-dealloc-visitor.h"
+ #include "example-qapi-types.h"
+ #include "example-qapi-visit.h"
+
+ #include "example-qmp-commands.h"
+ static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
+ {
+ QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
+ QmpOutputVisitor *mo = qmp_output_visitor_new();
+ Visitor *v;
+
+ v = qmp_output_get_visitor(mo);
+ visit_type_UserDefOne(v, &ret_in, "unused", errp);
+ v = qapi_dealloc_get_visitor(md);
+ visit_type_UserDefOne(v, &ret_in, "unused", errp);
+ qapi_dealloc_visitor_cleanup(md);
+
+
+ *ret_out = qmp_output_get_qobject(mo);
+ }
+
+ static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
+ {
+ UserDefOne * retval = NULL;
+ QmpInputVisitor *mi;
+ QapiDeallocVisitor *md;
+ Visitor *v;
+ UserDefOne * arg1 = NULL;
+
+ mi = qmp_input_visitor_new(QOBJECT(args));
+ v = qmp_input_get_visitor(mi);
+ visit_type_UserDefOne(v, &arg1, "arg1", errp);
+
+ if (error_is_set(errp)) {
+ goto out;
+ }
+ retval = qmp_my_command(arg1, errp);
+ qmp_marshal_output_my_command(retval, ret, errp);
+
+ out:
+ md = qapi_dealloc_visitor_new();
+ v = qapi_dealloc_get_visitor(md);
+ visit_type_UserDefOne(v, &arg1, "arg1", errp);
+ qapi_dealloc_visitor_cleanup(md);
+ return;
+ }
+
+ static void qmp_init_marshal(void)
+ {
+ qmp_register_command("my-command", qmp_marshal_input_my_command);
+ }
+
+ qapi_init(qmp_init_marshal);
+ mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
+ /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
+
+ #ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
+ #define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
+
+ #include "example-qapi-types.h"
+ #include "error.h"
+
+ UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
+
+ #endif
+ mdroth@illuin:~/w/qemu2.git$