qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC] Plan for moving forward with QOM
@ 2011-09-14 18:04 Anthony Liguori
  2011-09-14 18:49 ` Anthony Liguori
                   ` (5 more replies)
  0 siblings, 6 replies; 88+ messages in thread
From: Anthony Liguori @ 2011-09-14 18:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: Edgar E. Iglesias, Jan Kiszka, Gerd Hoffmann, Markus Armbruster,
	Peter Maydell

Hi,

I spent a couple hours today writing up some comparisons and an initial 
task list for converting qdev to QOM.  The main location of this is the 
wiki[1] but I thought I would inline it here for easier commenting.

I decided to do this because I wanted to avoid a massively long 00 patch 
explaining the rationale for the first batch of changes that I'm going 
to send out.

There is so much complexity in qdev and the device model in general that 
it's hard to come up with a concise document.  I'd really appreciate 
suggestions for topics to write up more rationale as that would help me 
avoid writing a book on the topic :-)

[1] http://wiki.qemu.org/Features/QOM

== Device Relationships ==

=== Device Relationships in QDev ===

The two main concepts in QDev are devices and busses.  A device is 
represented
by a DeviceState and a bus is represented by a BusState.  They do not 
share a
common base class.  Devices can have properties but busses cannot.  A device
has no direct relationship with other devices.  The only relationship is
indirect through busses.

A device may have zero or more busses associated with it via a has-a
relationship.  Each child bus may have multiple devices associated with 
it via
a reference.  All devices have a single parent bus and all busses have a 
single
parent device.  These relationships form a strict tree where every 
alternating
level is a bus level followed by a device level.  The root of the tree 
is the
main system bus often referred to as SysBus.

=== Device Relationships in QOM ===

Everything in QOM is a device.  The concept of busses are implemented as an
interface that a device implements.  Devices can have two types of 
relationships
with other devices: device composition or device backlinks.  Device 
composition
involves one device directly creating another device.  It will own life 
cycle
management for the created device and will generally propagate events to 
that
device (although there are exceptions).

Device backlinks allow one device to refer to another device in a looser
fashion.  While there can be only one device composition relationship that
exists between two specific devices, a device can participate in an 
arbitrary
number of backlinks.

Device composition and backlinks are both strongly typed and can be 
typed as a
specific device type or as an interface.  When typed as an interface, any
device that implements that interface can be used.

There is no explicit notion of parents in QOM.  A typical bus relationship
would the bus having a backlink to the child device, and the child 
device having
a backlink to the bus.

Without device backlinks, device composition forms a multi-rooted strict 
tree.
With backlinks, the result are multiple directed graphs.

== Naming ==

=== Naming in QDev ===

QDev has three namespaces: the device namespace, the bus namespace, and 
property
namespaces.

The device namespace contains the names of qdev devices.  qdev supports the
ability to have anonymous devices.  Anonymous devices are usually created
through composition and are anonymous because the user controls the device
namespace and the user has no way of allocating names for devices created
through composition.

The bus namespace is parallel to the device namespace.  Unlike the device
namespace, busses cannot be anonymous.  For busses that are created as a 
result
of composition, a name is derived either from the device name or via the 
type
name.

In qdev, implicit bus names are not considered stable and may change across
invocations and/or versions of QEMU.

Property namespaces are local to devices.  The 'id' property is reserved to
refer to the name of the device.  Property names do not reference child 
devices.

Paths cannot be meaningfully constructed in QDev.  Devices can only be 
addressed
directly by their name as there is no stable way to refer to busses under a
device, or children under a bus.

=== Naming in QOM ===

In QOM, there are only two namespaces, the device namespace and the property
namespace.

All devices have unique names.  There are no exceptions.  Devices created
through composition are given unique names by deriving the name based on the
parent device name and a special separator, "::", that cannot be used in 
user
supplied names.

Since a bus is-a device in QOM, there is no notion of having multiple busses
under the same device.  A device can implement multiple bus interfaces, 
but can
only be a single bus of any given bus interface.

Device names are completely independent of pathnames.  For devices that 
are no
user created, device names should be treated as opaque blobs with 
absolutely no
semantic meaning.

All device relationships are identified as named properties.  A QOM path 
name
consists of a named device, followed by a series of properties which may 
or may
not refer to other devices.  For instance, all of the following are 
valid paths:

  /i440fx/piix3/i8042/aux
  /i440fx/slot[1.0]/i8042/aux
  /i440fx/slot[1.0]/bus/piix3/i8042/aux

All of these path names are interpreted as follows:

  def resolve_pathname(pathname):
      root, props = pathname[1:].split('/')
      dev = find_device(root)
      for prop in props:
          device_name = get_property(dev, prop)
          dev = find_device(device_name)
      return dev

In this specific example, the i440fx object has two properties that both 
refer
to the PIIX3 device.  The 'piix3' device is a property that reflects a 
device
composition relationship.  The 'slot[1.0]' property represents a device 
backlink
relationship.

The PIIX3 device has a 'i8042' property based on device composition of 
the PC
Keyboard Controller device.  It also has a device backlink property, 
'bus', that
points to the bus that it sits on (which is the 'i440fx' object).

Finally, the PC Keyboard Controller device has an 'aux' property which is a
device backlink property that can point to a PS/2 Mouse device.

The full set of devices names and properties used in this example are below:

  Type: I440FX
  Is-a: Device
  Implements: PciBus
  Name: i440fx
  Properties:
   piix3: Composition<PIIX3>
   slot[1.0]: Backlink<PciDevice>

  Type: PIIX3
  Isa-a: PciDevice
  Implements: IsaBus
  Name: i440fx::piix3
  Properties:
   i8042: Composition<I8042>
   bus: Backlink<PciDevice> (inherited from PciDevice)

  Type: I8042
  Isa-a: Device
  Implements: Ps2Controller
  Name: i440fx::piix3::i8042
  Properties:
   aux: Backlink<Ps2Mouse>

== Device Properties ==

=== Properties in QDev ===

Device properties in qdev are bound to classes and map directly to 
elements of
the device structure.  They are strongly typed.  Each type is parsed 
directly
from a string representation.  There is no way to set qdev properties from
anything but a string.

Device properties in qdev are only settable during construction.  After
construction, they are read-only.  Devices cannot hook setting or 
getting of a
property.

=== Properties in QOM ===

Device properties in QOM are bound to devices and are implemented by 
closures
provided by the device.  A Visitor is passed to the closure which 
effectively
allows properties to be set/get through native C types.  Mapping to any 
other
type of representation (string or otherwise) is done by a Visitor with no
knowledge of the device or property.

By convention, most device properties are implemented by writing a C typed
public getter/setter for the device, and then using a property wrapper to
translate those typed functions to an untyped closure that accepts a 
Visitor.

QOM has no notion of construction.  All devices are created without 
properties.
Properties can be set/get after initialization.  Devices support the notion
of "realize" which roughly corresponds to construction.  More accurately, it
corresponds to the moment before a device will be first consumed by a guest.

"unrealize" roughly corresponds to reset.  A device may be realized and
unrealized many times during its lifecycle.

Properties are, by default, locked while the device is realized. 
Exceptions can
be made by the devices themselves in order to implement a way for a user to
interact with a device while it is realized.

Two special types of properties are plug<> and socket<> properties.  A 
plug<>
property is used to represent device composition.  When a plug<> property is
added, the child device has its life cycle automatically tied to the parent
device.  The socket<> property represents a device backlink.

The plug<> property type is always read-only and when read, will return the
name of the child device.

The socket<> property type is by default read/write and locked during 
realize.
Hotplug can be implemented by allowing a socket to be writable after 
realize and
installing a custom setter function that implements hotplug behavior.

== TODO ==

  1. Eliminate anonymous devices.
   a. Will require touching any place in the tree that creates a qdev 
object and
      giving a meaningful unique name.

  2. Refactor any device that creates 2 or more busses to only create a 
single
     bus. This will mean using composition.
   a. An example: IDE controller creates two busses, one for the primary 
and one
      for the secondary.  Instead, IDE device should have two IDE 
controller sub
      devices, each device having a single bus.

  3. Unify the bus/device namespaces
   a. This is a compatibility breaker
   b. Depends on (1) and (2)

  4. Modify qdev properties to allow devices to register setters/getters 
that use
     visitors to access properties.
   a. Implement existing properties in terms of visitors

  5. Modify qdev properties to be stored in the object, not in the class

  6. Expose children as named properties
   a. Read only to start with

  7. Change qdev to use QOM typing
   a. Depends on (3)
   b. Must change all init functions to use QOM init functions
   c. Change all DO_UPCASTS to QOM macro casts
   d. Can be largely done via sed

  8. Change children to be based on plug and socket properties
   a. Eliminate children list in each device
   b. Compatibility breaker

  9. Improve object model
   a. Compatibility breaker

^ permalink raw reply	[flat|nested] 88+ messages in thread

end of thread, other threads:[~2011-12-16  5:11 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-14 18:04 [Qemu-devel] [RFC] Plan for moving forward with QOM Anthony Liguori
2011-09-14 18:49 ` Anthony Liguori
2011-09-14 19:30 ` Jan Kiszka
2011-09-14 19:42   ` Anthony Liguori
2011-09-14 21:15     ` Jan Kiszka
2011-09-14 22:11       ` Anthony Liguori
2011-09-15 13:43         ` Jan Kiszka
2011-09-15 14:11           ` Anthony Liguori
2011-09-15 16:38             ` Jan Kiszka
2011-09-15 18:01               ` Anthony Liguori
2011-09-16 10:12             ` Kevin Wolf
2011-09-16 13:00               ` Anthony Liguori
2011-09-14 20:00 ` Edgar E. Iglesias
2011-09-14 20:22   ` Anthony Liguori
2011-09-14 20:27     ` Edgar E. Iglesias
2011-09-14 20:37     ` Blue Swirl
2011-09-14 21:25       ` Anthony Liguori
2011-09-15  6:31 ` Gleb Natapov
2011-09-15 10:49   ` Stefan Hajnoczi
2011-09-15 13:08     ` Anthony Liguori
2011-09-15 13:17   ` Anthony Liguori
2011-09-15 14:23     ` Gleb Natapov
2011-09-16 14:46     ` John Williams
2011-09-16 16:10       ` Anthony Liguori
2011-09-17  1:11         ` Edgar E. Iglesias
2011-09-17  2:12           ` Anthony Liguori
2011-09-17  2:35             ` Edgar E. Iglesias
2011-09-15 13:57   ` Anthony Liguori
2011-09-15 14:14     ` Paolo Bonzini
2011-09-15 14:25       ` Gleb Natapov
2011-09-15 15:28         ` Anthony Liguori
2011-09-15 15:38           ` Gleb Natapov
2011-09-15 16:33             ` Anthony Liguori
2011-09-15 16:59               ` Gleb Natapov
2011-09-15 17:51                 ` Anthony Liguori
2011-09-15 20:29                   ` Gleb Natapov
2011-09-15 20:45                     ` Peter Maydell
2011-09-15 21:15                       ` Anthony Liguori
2011-09-16 16:33                       ` Gleb Natapov
2011-09-16 17:47                         ` Peter Maydell
2011-09-16 18:08                           ` Anthony Liguori
2011-09-16 18:22                             ` Gleb Natapov
2011-09-16 18:42                               ` Anthony Liguori
2011-09-16 19:13                                 ` Gleb Natapov
2011-09-16 19:29                                   ` Anthony Liguori
2011-09-16 20:48                                     ` Gleb Natapov
2011-09-16 21:03                                       ` Anthony Liguori
2011-09-17  0:01                                 ` Edgar E. Iglesias
2011-09-16 18:18                           ` Gleb Natapov
2011-09-15 20:50                     ` Anthony Liguori
2011-09-16 16:47                       ` Gleb Natapov
2011-09-17  0:48                         ` Edgar E. Iglesias
2011-09-17  2:17                           ` Anthony Liguori
2011-09-17  2:29                             ` Anthony Liguori
2011-09-17  2:41                             ` Edgar E. Iglesias
2011-09-15  6:47 ` Paolo Bonzini
2011-09-15 13:26   ` Anthony Liguori
2011-09-15 13:35     ` Paolo Bonzini
2011-09-15 13:54       ` Peter Maydell
2011-09-15 14:18         ` Anthony Liguori
2011-09-15 14:33           ` Paolo Bonzini
2011-09-15 14:48             ` Peter Maydell
2011-09-15 15:31             ` Anthony Liguori
2011-09-15 15:47               ` Paolo Bonzini
2011-09-15 20:23     ` Avi Kivity
2011-09-15 20:52       ` Anthony Liguori
2011-09-18  7:56         ` Avi Kivity
2011-09-18 14:00           ` Avi Kivity
2011-09-16  9:36       ` Gerd Hoffmann
2011-12-13  4:47 ` Paul Brook
2011-12-13 13:22   ` Anthony Liguori
2011-12-13 17:40     ` Paul Brook
2011-12-13 18:00       ` Anthony Liguori
2011-12-13 20:36         ` Paul Brook
2011-12-13 21:53           ` Anthony Liguori
2011-12-14  0:39             ` Paul Brook
2011-12-14 13:53               ` Anthony Liguori
2011-12-14 14:01                 ` Avi Kivity
2011-12-14 14:11                   ` Anthony Liguori
2011-12-14 14:35                     ` Avi Kivity
2011-12-14 14:46                       ` Anthony Liguori
2011-12-14 14:50                         ` Avi Kivity
2011-12-15 18:59                 ` Paul Brook
2011-12-15 19:12                   ` Anthony Liguori
2011-12-15 21:28                     ` Paul Brook
2011-12-16  2:08                       ` Anthony Liguori
2011-12-16  5:11                         ` Paul Brook
2011-12-14  9:11             ` Andreas Färber

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).