All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [RFC][PATCH 0/21] QEMU Object Model
Date: Tue, 26 Jul 2011 09:02:54 -0500	[thread overview]
Message-ID: <4E2EC90E.8090409@codemonkey.ws> (raw)
In-Reply-To: <4E2EBA1E.90006@redhat.com>

On 07/26/2011 07:59 AM, Paolo Bonzini wrote:
> For host devices (Char/Block/Network) we have a relatively simple
> interface but we need a richer way to create and destroy the objects at
> runtime. We have it already for block and network, we don't for char,
> but it is done ad hoc for each hierarchy. We do not have a deep
> hierarchy, in fact there is no hierarchy at all (only one abstract class
> per subsystem).
>
> Honestly, it is not too bad. It may not be the cleanest code, but is it
> worth the kind of ramifications that your patch has? Of course, the
> answer could be "yes" if the same model can be applied to devices.
> Devices do have the same introspection needs more or less, and I like
> your ideas there. However, the requirements are very different in terms
> of composition.
>
> Also because there is no hierarchy, composition in host devices can be
> done very easily. A decorator for char/block devices, such as a "tee"
> device, can treat the wrapped object(s) the same independent of the
> actual class. A simple vtable works very well. GObject would also do
> well, unifying the introspection at the cost of significantly more
> boilerplate.

The polymorphism model of QOM is identical to GObject so I'm not sure 
what you mean here.

In the case of tee, it's just an object with two sockets.


> (Of course, we could rewrite QEMU in Vala).
>
> For *guest* devices, however, this is not the case. The PCI host needs
> to know that the device on the other end is a PCI device. Even the
> simplest bus, for example I2C, has methods defined on its children.

I have PCI patches, but didn't post them in the series.  Here's how it 
works:

The PCI host controller, the i440fx, has 32 sockets of PCIDevice. 
PCIDevice is a base class.

The PCI host controller implements a PCIBus interface.  The PCIDevices 
have a socket of a PCIBus

Connecting a PCIDevice to the host bus involves setting the socket on 
the PCI host controller with the PCIDevice and then setting the 
PCIDevice's bus socket with the host controller.

A PCIDevice can also be a PCIBus by implementing the PCIBus interface. 
This is what enables a PCI bridge to make sense in this model.

If you're interested, the tree that has this is 
http://repo.or.cz/w/qemu/aliguori.git/tree/qdev2:/devices

> So, the most important point, it seems to me, is to support composition
> effectively. There need not be any hierarchy at all---not even the
> two-level hierarchy we have now, everything can inherit from
> DeviceState---but the combination between devices must be:

I think composition is being overloaded here.  When I say composition, I 
mean that one device is created out of multiple other devices. 
Something like the PIIX3 is composed of an RTC, UART, etc.

That's different that connecting up the links in the device tree graph.

> 1) in a flexible manner, so that it can express complex topologies (as
> long as "plugs" and "sockets" have the same shape of course);

Right, this is what we do today in QOM.  Plugs and Sockets are typed. 
Those types can be interfaces or base classes so there's a lot of 
flexibility.

> 2) in an easily introspectable manner, so that migration and QMP and so
> on work very well in the presence of said topologies;

The 'qsh' tree can view the entire device model as a synthetic file 
system.  Plugs are represented as sub directories and sockets as 
symbolic links.  I plan on writing a quick FUSE file system too.

There is type information with all of the attributes that's not visible 
in this view but it's there nonetheless.

> 3) in a precise manner, so that the two devices being connected can
> interact effectively;
>
>
> The current qdev fails completely at (1). (2) is very limited if you
> consider qdev only; qdev+VMState is at least decent, though nowhere near
> the potential of QOM.
>
> However, qdev gets (3) right by making interaction between the parent
> and the child go through a bus object that knows the details of both. In
> particular, bus objects and their vtable structures are very effective
> in qdev because they provide flexibility and avoid impedence mismatch,
> with a very limited amount of boilerplate.
>
> By contrast, the plug/socket model in QOM achieves (1) and (2), but in
> my opinion it fails at (3). The model for example is not effective in
> specifying the properties of the socket, which are roughly are the bus
> properties and the fields added by DeviceState abstract subclasses in
> the current qdev;

There are no properties of the socket.

If you look at something like adding a PCI device in qdev, you add a 
child and set properties of the child to identify how the device sits on 
the PCI bus.

I'd characterize this as awkward, at best.  The slot index is not a 
property of the device, it's a property of how the device is connected 
to the PCI bus.

In my attempt at PCI modelling, I had something like:

struct I440FX
{
    Device parent;

    PciDevice slots[32];
};

Which means that to attach to bus 0, slot 3, fn 0, you do:

i440fx->slots[3] = mydevice

Likewise, if slot 4 contains a PCI-to-PCI bridge that ends up being bus 
1, and you want to assign to bus 1, slot 2, fn 0:

i440fx->slots[4]->slots[2] = myotherdevice;

Now you may observe that this is awkward compared to saying "bus 1". 
But bus numbering is actually a guest concept, not a hardware concept. 
When constructing the device tree, the physical topology is actually 
what make sense in terms of constructing devices, not a guest derived 
numbering concept.

The same applies equally to IDE.  You'd have:

struct IDEBus
{
    IDEDevice *master, *slave;
};

struct IDEChipset
{
    IDEBus primary;
    IDEBus secondary;
};

This would result in:

ide->primary.master = disk1;
ide->secondary.master = cdrom;

> it is not clear where they would live in QOM. Perhaps
> in the parent device or in an intermediate object between the parent and
> the child; if the latter, it looks like a lot of pointer chasing and a
> conversion nightmare.

It's a characteristic of the property itself.  It's definitely very 
different than how we do it today.

>
> Based on my earlier conversations with Peter, I thought a bit on how to
> do more incremental changes to qdev in order to overcome the
> inflexibility. Here is a rough overview of the steps:
>
>
> 1) make properties more flexible. In particular, we *absolutely* need
> array properties, either static or dynamic. The current special casing
> of GPIO pins is required exactly because we do not have arrays of
> properties.
>
> Also, since arrays occur a lot in the device state, array properties
> would also be required to be able to introspect on run-time properties
> (which are now part of VMState only). However, I am not going to
> consider run-time introspection much more. It is "a simple matter of
> programming" if your general introspection design is done right.

Arrays of properties already work in QOM.  Part of the trouble with qdev 
today (and QObject for that matter), is that properties are a 
characteristic of a class, not an object.  This is the primary 
difference between the QOM Plug and is required for proper array support.

> 2) add more kinds of first-class (user specifiable) properties. GPIO
> pins, for example, which are already part of qdev but cannot be
> specified by the user on the command line. Possibly memory regions too.
> Anything that can be used to configure a device (with respect to the
> main bus or to its parent) should be a property.
>
>
> 3) at this point, you can get rid of the specialties of SysBus devices.
> IRQs are an array of GPIO properties, same for memory regions. SysBus
> devices can use a naked DeviceState structure.
>
> At this point, many embedded devices could be entirely described in
> terms of configuration files, except for legacy options (-serial kind)
> and for the few devices that attach directly to the CPU. This without
> the need to define artificial buses that do not exist in real hardware.
>
>
> 4) add support for compound properties. A compound properties is such
> that you define a property named (coincidence...) "bus" and you get
> automatically "bus.parent", "bus.addr", "bus.romfile", "bus.rombar" etc.

Because QOM uses visitors for properties, properties can be arbitrarily 
complicated structures.  How that maps to command line arguments, I 
haven't thought through yet but you can certainly do:

plug_set(obj, "bus", { 'parent': x, 'addr': y, ...})

>
> 5) convert buses to compound properties. Rather than inheriting from
> PCIDevice, a PCI device would inherit straight from DeviceState and
> include a PCIDevice struct that defines the backlink from a device to
> its parent. Note that since we're using C, this is not a big change from
> what we're doing now! (Inheritance by containment is a special case of
> containment.) And it allows to define very flexibly a device that would
> have to sit on two or more buses in the current qdev model. More
> importantly, it keeps the effectiveness of the qbus ops model, while
> removing the constraint of a tree topology.

Interfaces are the right way to do this.  Getting MI right is fairly 
hard and since qdev uses a simple container_of, it's not going to work 
very well.  That's another advantage of QOM, casting from interfaces to 
objects Just Works.

>
>
> It is only when this is done, that we should reconsider introspection
> and see if it is useful/sensible to unify the host and guest device
> object models.
>
> Because the host models we have now, with all the defects they may have,
> *work*. The guest models hardly work for anything but PCs, and even then
> only for the subset of devices which are interesting to hot-plug/unplug.
> And so it is from them that we should start designing.
>
> Thoughts?

I think all of the requirements you've outlined are currently handled in 
QOM.  I think it would probably be a good idea to set up a wiki page 
that focused just on qdev-next requirements and that would give us a 
rigorious mechanism to evaluate how well QOM satisfies those requirements.

I haven't thought through how to do OQM incrementally with qdev.  It's 
probably possible but I wanted to focus on the backends first before 
really attacking that.

Regards,

Anthony Liguori

>
> Paolo
>
>

  reply	other threads:[~2011-07-26 14:03 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-07-25  1:44 [Qemu-devel] [RFC][PATCH 0/21] QEMU Object Model Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 01/21] qom: add make infrastructure Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 02/21] qom: convert QAPI to use Qconfig build system Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 03/21] qom: Add core type system Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 04/21] qom: add Plug class Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 05/21] plug: add Plug property type Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 06/21] plug: add socket " Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 07/21] plug: add generated property types Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 08/21] qom: add plug_create QMP command Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 09/21] qom: add plug_list " Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 10/21] qom: add plug_get " Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 11/21] qom: add plug_set " Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 12/21] qom: add plug_list_props " Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 13/21] qom: add plug_destroy command Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 14/21] qom: add example qsh command Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 15/21] qom: add Device class Anthony Liguori
2011-07-27 15:10   ` Peter Maydell
2011-07-27 16:07     ` Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 16/21] qom-devices: add a Pin class Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 17/21] qom: add CharDriver class Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 18/21] qom-chrdrv: add memory character driver Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 19/21] qom-chrdrv: add Socket base class Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 20/21] qom-chrdrv: add TCPServer class Anthony Liguori
2011-07-25  1:44 ` [Qemu-devel] [PATCH 21/21] qom-chrdrv: add UnixServer Anthony Liguori
2011-07-25 11:21 ` [Qemu-devel] [RFC][PATCH 0/21] QEMU Object Model Kevin Wolf
2011-07-25 12:45   ` Anthony Liguori
2011-07-25 13:08     ` Kevin Wolf
2011-07-25 13:10       ` Anthony Liguori
2011-07-26 12:59 ` Paolo Bonzini
2011-07-26 14:02   ` Anthony Liguori [this message]
2011-07-26 14:35     ` Paolo Bonzini
2011-07-26 15:34       ` Anthony Liguori
2011-07-26 18:26         ` Paolo Bonzini
2011-07-26 19:23           ` Anthony Liguori
2011-07-27  8:55             ` Paolo Bonzini
2011-07-27 12:48               ` Anthony Liguori
2011-07-27 15:33                 ` Paolo Bonzini
2011-07-27 16:19                   ` Anthony Liguori
2011-07-27 16:28                   ` Anthony Liguori
2011-07-27 18:51                     ` Paolo Bonzini
2011-07-27 20:01                       ` Anthony Liguori
2011-07-28  7:36                         ` Paolo Bonzini
2011-07-28 12:46                           ` Anthony Liguori
2011-07-28 13:50                             ` Paolo Bonzini
2011-07-28 14:03                               ` Anthony Liguori
2011-07-28 14:41                                 ` Paolo Bonzini
2011-07-28 15:04                                   ` Anthony Liguori
2011-07-28 15:47                                     ` Paolo Bonzini
2011-07-28 17:59                                       ` Anthony Liguori
2011-07-29  7:19                                         ` Paolo Bonzini
2011-07-27 21:33     ` Peter Maydell
2011-07-27 22:31       ` Anthony Liguori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4E2EC90E.8090409@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.