How to add a new device in QEMU source code?

What could be the step wise approach to emulate/add a new device in qemu using QOM approach?

What and where could be the changes with respect to DeviceState/BusState and other properties?


edu in-tree educational PCI device

  • https://github.com/qemu/qemu/blob/v2.7.0/hw/misc/edu.c
  • https://github.com/qemu/qemu/blob/v2.7.0/docs/specs/edu.txt

It is very easy to understand and well documented, so I recommend that you study it.

It exposes a minimal PCI device, with basic IO, interrupt generation, and DMA.

I've written a minimal Linux kernel module + userland tests to play with it at:

  • https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/rootfs_overlay/pci.sh
  • https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/pci.c

Out-of-tree devices

I asked if it is possible to make out-of-tree devices at: How to create out-of-tree QEMU devices? but it does not look like it.


There are some parts of example in "QOM exegesis and apocalypse" 2014 presentation at http://events.linuxfoundation.org/sites/events/files/slides/kvmforum14-qom_0.pdf

Creating an object

Object *o = object_new(TYPE_RNG_BACKEND_RANDOM);
object_property_set_str(o, "filename", "/dev/random", NULL);
object_property_set_bool(o, "opened", "true", NULL);
object_property_add_child(container_get("/somewhere"), "my-rng", o, NULL);
object_unref(o);

Inside properties

static bool rng_get_opened(Object *obj, Error **errp)
{
    RngBackend *s = RNG_BACKEND(obj);
    return s->opened;
}
static void rng_set_opened(Object *obj, bool value, Error **errp)
{
    RngBackend *s = RNG_BACKEND(obj);
    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
    ...
    if (k->opened) {
        k->opened(s, errp)
    }
}
static void rng_backend_init(Object *obj)
{
    object_property_add_bool(obj, "opened",
        rng_get_opened, rng_set_opened, NULL);
}
static const TypeInfo rng_backend_info = {
   .name = TYPE_RNG_BACKEND,
   .parent = TYPE_OBJECT,
   .instance_size = sizeof(RngBackend),
   .instance_init = rng_backend_init,
   .class_size = sizeof(RngBackendClass),
   .abstract = true,
};

(compare with actual code: http://code.metager.de/source/xref/qemu/backends/rng.c and one implementation of RNG_BACKEND http://code.metager.de/source/xref/qemu/backends/rng-random.c)

These two pages may be useful too: * http://wiki.qemu.org/Features/QOM * http://wiki.qemu.org/QOMConventions

The post "Essential QEMU PCI API" by Siro Mugabi: http://nairobi-embedded.org/001_qemu_pci_device_essentials.html (http://web.archive.org/web/20151116022950/http://nairobi-embedded.org/001_qemu_pci_device_essentials.html) has complete example of QOM-enabled PCI driver.

The QEMU Object Model (QOM) provides a framework for registering user creatable Types. QOM models buses, interfaces, devices, etc as types. In QOM, information by a user Type is used to create its ObjectClass instance as well as its Object instance. This information is specified in a TypeInfo structure (include/qom/object.h). For example:

/* hw/misc/pci-testdev.c */

static const TypeInfo pci_testdev_info = {
        .name          = TYPE_PCI_TEST_DEV,
        .parent        = TYPE_PCI_DEVICE,
        .instance_size = sizeof(PCITestDevState),
        .class_init    = pci_testdev_class_init,
};

where:

  • .name a string that indicates the user Type.
  • .parent a string that specifies the Type from which this user Type derives from.
  • .instance_size size of the Type's Object instance. Its allocation will be performed internally by QOM. Objects will be discussed in more detail in Section Object Instantiation.
  • .class_init the constructor hook. This function will be responsible for initializing the Type's ObjectClass instance.