qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC] QEMU Object Model
@ 2011-07-19 15:14 Anthony Liguori
       [not found] ` <4E2824D2.2050401@redhat.com>
  0 siblings, 1 reply; 13+ messages in thread
From: Anthony Liguori @ 2011-07-19 15:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: Avi Kivity, Markus Armbruster

Hi,

I've started an effort to introduce a consistent object model to QEMU. 
Today, every subsystem implements an ad-hoc object model.  These object 
models all have the same basic properties but do things in arbitrarily 
different ways:

1) Factory interface for object creation
  - Objects usually have names
  - Construction properties for objects

2) Object properties
  - Some have converged around QemuOpts
  - Some support properties on at construction time
  - Most objects don't support introspection of properties

3) Inheritance and Polymorphism
  - Most use a vtable to implement inheritance and polymorphism
  - Only works effectively for one level of inheritance
  - Inconsistency around semantics of overloaded functions
    - Sometimes the base object invokes the overloaded function and 
implements additional behavior

netdev, block, chardev, fsdev, qdev, and displaystate are all examples 
of ad-hoc object models.  They all have their own implementations of the 
above and their own command line/monitor syntaxes.

QOM is a unifying object model inspired by the GObject/GType system.

Here is a short description of the feature it supports or is intended to 
support:

1) All objects derive from a common base object (Plug).  Plug's support 
properties that can be set/get with a Visitor.  This means QMP can be 
natively used to read/write object properties.

2) Properties have a type and flags associated with them.  Properties 
can be read-only, read-write, and locked.

3) Locked properties are read-only after realize.

4) Two special types of properties, plug<> and socket<> allow for a 
type-safe way to create a directed graph of objects at run time.  This 
provides a consistent mechanism to create a tree of devices and to 
associate backends with devices.

5) Single inheritance is supported with full polymorphism.  Interfaces 
are also supported which allows a restricted (Java-style) form of MI.

6) All types are registered through the same interface.  Type modules 
can be used to implement anything from new devices, buses, block/net 
backends, or even entirely new types of backends.  In the future, I 
would like to support demand loading of modules to allow a small core of 
QEMU to be loaded which then loads only the bits of code required to run 
a guest.

It has a few key different from GObject:

1) GObject properties are implemented as GValues.  GValues are variants 
that are assumed to be immutable.  A key requirement of QOM is that we 
can use the Visitor framework for interacting with properties.  This 
allows for a richer expression of properties (specifically, complex 
device state to be serialized as a property).

2) GObject properties are installed in the class.  In order to support 
things like multifunction devices, we really need to install properties 
with the object so that we can have arrays of properties that are sized 
from another property.

3) GTypes/GObjects are always heap allocated as discrete objects. 
GObjects are also reference counted.  In order to support object 
composition, it's necessary to be able to initialize an object from an 
existing piece of memory.

I'll follow up later in the week with some documentation on how the type 
system works in more detail.  A tree is available below that has the 
current implementation:

http://repo.or.cz/w/qemu/aliguori.git/tree/qdev2

I'll be documenting the type system at:

http://wiki.qemu.org/Features/QOM

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
       [not found]     ` <4E282BE3.1050404@redhat.com>
@ 2011-07-21 14:49       ` Anthony Liguori
  2011-07-21 15:04         ` Avi Kivity
  2011-07-21 15:19         ` Luca Tettamanti
  0 siblings, 2 replies; 13+ messages in thread
From: Anthony Liguori @ 2011-07-21 14:49 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, Markus Armbruster

On 07/21/2011 08:38 AM, Avi Kivity wrote:
> On 07/21/2011 04:20 PM, Anthony Liguori wrote:

>> static TypeInfo tcp_server_type_info = {
>> .name = TYPE_TCP_SERVER,
>> .parent = TYPE_SOCKET_SERVER,
>> .instance_size = sizeof(TcpServer),
>> .instance_init = tcp_server_init,
>> .class_init = tcp_server_class_init,
>> };
>>
>
> How do the properties become registered? Ah, I see you do have to
> register them. You'd have to do the same in C++, but it would be a lot
> simpler and type-safer (you can use pointers to members, for example,
> and avoid getter/setters where unnecessary).

See git://git.codemonkey.ws/kvm++.git

It's exactly the same object model, but in C++.  Some things are nicer, 
some things are not nicer.  It's not quite a slam dunk.

But what really concerned me about it was that I quickly realized that 
it was going to be mostly write-only code.  The C++ tricks that you need 
to do to make it all work well are extremely obscure.  It requires 
template meta-programming, every obscure detail about partial 
specialization, etc.

And it's really not that much nicer than the C version.  The problem 
with C++ is that even though the type system is much, much nicer, it 
still doesn't have introspection or decorators.  These two things would 
be the killer feature for doing the sort of things we need to do and is 
really where most of the ugliness comes from.

>
> There is quite a lot of boilerplate - around half the code of tcp.[ch].
> It may be simple to create a new type to the author of the framework,
> but I doubt it would be simple to others. There would be a lot of
> cut'n'paste.

Yup.  That's the price you pay for using C over C++.  But the ratio is 
only true for simple types.  Complex types (look at chrdrv.h), the ratio 
is much lower.

>> static void register_backends(void)
>> {
>> type_register_static(&tcp_server_type_info);
>> }
>>
>> device_init(register_backends);
>>
>> C++ doesn't reduce this significantly. The big advantage of an
>> approach like this is that its dirt-simple to integrate incrementally.
>> Converting the entire character device layer will only take a few days.
>
> Wouldn't it be dirt simple in C++ as well?

Not incrementally IMHO.

BTW, take at look at http://repo.or.cz/w/qemu/aliguori.git/blob/qdev2:/qsh

Part of my thinking here is that the few monitor commands we need to 
work with plugs end up being 90% of what we do today.  For instance, all 
of the chardev commands get mapped to generic commands:

chardev_add/-chardev   ->    plug_add
chardev_del            ->    plug_del
query-chardev          ->    plug_list base=chardev

The same is true for blockdev, netdev, and eventually all of the device 
model.

All of the complexity around reading command lines and config files 
should be done in a python front end.   qsh is an ad-hoc attempt at 
doing exactly that.  There is already an import command that handles a 
git-style command line file.

>
> We can change the language first.

My view is roughly this:

1) introduce type system and update build system

2) convert each backend, add compatibility handlers to preserve existing 
monitor commands and command line arguments.  deprecate everything to be 
removed in qemu 2.0.

3) introduce a new front end written in Python that only works with the 
plug interfaces

4) convert the device model.  compatibility will be hard to maintain but 
I think it's doable.

5) declare qemu 2.0, remove all of the compatibility stuff, and 
potentially move it to a new python script for legacy usage.

At this point, qemu would no longer be an executable that was directly 
invoked by a user.  They would use a wrapper script to provide the 
functionality of today's qemu.  Management software could launch the 
daemon on their own.

C++ doesn't eliminate any of these steps.  IMHO, it doesn't tremendously 
simplify any of these steps either.

I think *good* C++ could provide some value by eliminating the 
possibility of buffer overflows, use-after-free, memory-leaks, etc.  But 
that's icing on the cake.

I don't ever see the device model being written in something other than 
C/C++ too.  Having a GC in the VCPU thread would be a major issue IMHO.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 14:49       ` Anthony Liguori
@ 2011-07-21 15:04         ` Avi Kivity
  2011-07-21 15:45           ` Anthony Liguori
  2011-07-21 15:19         ` Luca Tettamanti
  1 sibling, 1 reply; 13+ messages in thread
From: Avi Kivity @ 2011-07-21 15:04 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, Markus Armbruster

On 07/21/2011 05:49 PM, Anthony Liguori wrote:
> On 07/21/2011 08:38 AM, Avi Kivity wrote:
>> On 07/21/2011 04:20 PM, Anthony Liguori wrote:
>
>>> static TypeInfo tcp_server_type_info = {
>>> .name = TYPE_TCP_SERVER,
>>> .parent = TYPE_SOCKET_SERVER,
>>> .instance_size = sizeof(TcpServer),
>>> .instance_init = tcp_server_init,
>>> .class_init = tcp_server_class_init,
>>> };
>>>
>>
>> How do the properties become registered? Ah, I see you do have to
>> register them. You'd have to do the same in C++, but it would be a lot
>> simpler and type-safer (you can use pointers to members, for example,
>> and avoid getter/setters where unnecessary).
>
> See git://git.codemonkey.ws/kvm++.git
>

Connection refused..

> It's exactly the same object model, but in C++.  Some things are 
> nicer, some things are not nicer.  It's not quite a slam dunk.
>
> But what really concerned me about it was that I quickly realized that 
> it was going to be mostly write-only code.  The C++ tricks that you 
> need to do to make it all work well are extremely obscure.  It 
> requires template meta-programming, every obscure detail about partial 
> specialization, etc.

Yes, that's a big worry.  Is all of that exposed to the implementer?  Or 
just in the framework?

>
> And it's really not that much nicer than the C version.  The problem 
> with C++ is that even though the type system is much, much nicer, it 
> still doesn't have introspection or decorators.  These two things 
> would be the killer feature for doing the sort of things we need to do 
> and is really where most of the ugliness comes from.

Agree.  A language with built in support for that would be much nicer 
(for migration as well).

>>
>> There is quite a lot of boilerplate - around half the code of tcp.[ch].
>> It may be simple to create a new type to the author of the framework,
>> but I doubt it would be simple to others. There would be a lot of
>> cut'n'paste.
>
> Yup.  That's the price you pay for using C over C++.  But the ratio is 
> only true for simple types.  Complex types (look at chrdrv.h), the 
> ratio is much lower.

chrdrv.c is almost 100% boilerplate.

>
>>> static void register_backends(void)
>>> {
>>> type_register_static(&tcp_server_type_info);
>>> }
>>>
>>> device_init(register_backends);
>>>
>>> C++ doesn't reduce this significantly. The big advantage of an
>>> approach like this is that its dirt-simple to integrate incrementally.
>>> Converting the entire character device layer will only take a few days.
>>
>> Wouldn't it be dirt simple in C++ as well?
>
> Not incrementally IMHO.
>
> BTW, take at look at 
> http://repo.or.cz/w/qemu/aliguori.git/blob/qdev2:/qsh

Wow, repositories like mushrooms after the rains.

>
> Part of my thinking here is that the few monitor commands we need to 
> work with plugs end up being 90% of what we do today.  For instance, 
> all of the chardev commands get mapped to generic commands:
>
> chardev_add/-chardev   ->    plug_add
> chardev_del            ->    plug_del
> query-chardev          ->    plug_list base=chardev
>
> The same is true for blockdev, netdev, and eventually all of the 
> device model.
>
> All of the complexity around reading command lines and config files 
> should be done in a python front end.   qsh is an ad-hoc attempt at 
> doing exactly that.  There is already an import command that handles a 
> git-style command line file.

IMO, that's much nicer, if we can keep the C<->HLL bridge clean.  Python 
isn't very good about that (and I wouldn't want it as the main 
implementation language for other reasons).

>
>>
>> We can change the language first.
>
> My view is roughly this:
>
> 1) introduce type system and update build system
>
> 2) convert each backend, add compatibility handlers to preserve 
> existing monitor commands and command line arguments.  deprecate 
> everything to be removed in qemu 2.0.
>
> 3) introduce a new front end written in Python that only works with 
> the plug interfaces
>
> 4) convert the device model.  compatibility will be hard to maintain 
> but I think it's doable.
>
> 5) declare qemu 2.0, remove all of the compatibility stuff, and 
> potentially move it to a new python script for legacy usage.
>

The big problem with this plan is that steps 2 and 4 are very difficult 
and yet we see no gains while it's being done.  A much smaller job (the 
memory API conversion) is turning out to be no fun at all.

> At this point, qemu would no longer be an executable that was directly 
> invoked by a user.  They would use a wrapper script to provide the 
> functionality of today's qemu.  Management software could launch the 
> daemon on their own.
>
> C++ doesn't eliminate any of these steps.  IMHO, it doesn't 
> tremendously simplify any of these steps either.

It trades off a lot of boilerplate (translated to copy'n'paste with all 
its issues) into 20-line error messages.  Inheriting from a class and 
implementing all of its pure virtuals is a lot easier than doing the C 
equivalent.

>
> I think *good* C++ could provide some value by eliminating the 
> possibility of buffer overflows, use-after-free, memory-leaks, etc.  
> But that's icing on the cake.

Yes.

> I don't ever see the device model being written in something other 
> than C/C++ too.  Having a GC in the VCPU thread would be a major issue 
> IMHO.

We get the equivalent of GC every time a vcpu thread is scheduled out so 
an iothread or an unrelated process can run.  It will hurt hard realtime 
guests, but these are only interesting to a small subset of users.

I think that if we can get the data path to run in pure C, and have the 
GC HLL involved only when the device model is reconfigured, then we have 
an acceptable tradeoff.  I don't claim that I know how to do this, 
though.  This is a really hard problem, mostly due to the huge size of qemu.

-- 
error compiling committee.c: too many arguments to function

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 14:49       ` Anthony Liguori
  2011-07-21 15:04         ` Avi Kivity
@ 2011-07-21 15:19         ` Luca Tettamanti
  2011-07-21 15:32           ` Avi Kivity
  2011-07-21 15:46           ` Anthony Liguori
  1 sibling, 2 replies; 13+ messages in thread
From: Luca Tettamanti @ 2011-07-21 15:19 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Markus Armbruster, Avi Kivity, qemu-devel

On Thu, Jul 21, 2011 at 4:49 PM, Anthony Liguori <aliguori@us.ibm.com> wrote:
[cut]
> And it's really not that much nicer than the C version.  The problem with
> C++ is that even though the type system is much, much nicer, it still
> doesn't have introspection or decorators.  These two things would be the
> killer feature for doing the sort of things we need to do and is really
> where most of the ugliness comes from.

QT has introspection; what about using the core (i.e. QObject and moc)
to build QEMU object model?

L

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 15:19         ` Luca Tettamanti
@ 2011-07-21 15:32           ` Avi Kivity
  2011-07-21 15:46           ` Anthony Liguori
  1 sibling, 0 replies; 13+ messages in thread
From: Avi Kivity @ 2011-07-21 15:32 UTC (permalink / raw)
  To: Luca Tettamanti; +Cc: Anthony Liguori, qemu-devel, Markus Armbruster

On 07/21/2011 06:19 PM, Luca Tettamanti wrote:
> On Thu, Jul 21, 2011 at 4:49 PM, Anthony Liguori<aliguori@us.ibm.com>  wrote:
> [cut]
> >  And it's really not that much nicer than the C version.  The problem with
> >  C++ is that even though the type system is much, much nicer, it still
> >  doesn't have introspection or decorators.  These two things would be the
> >  killer feature for doing the sort of things we need to do and is really
> >  where most of the ugliness comes from.
>
> QT has introspection; what about using the core (i.e. QObject and moc)
> to build QEMU object model?

Having someone else's code generator is better than building our own, 
but it's still very annoying.

I'm guessing Qt is pretty well done though.  Worth a look.

-- 
error compiling committee.c: too many arguments to function

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 15:04         ` Avi Kivity
@ 2011-07-21 15:45           ` Anthony Liguori
  2011-07-21 15:57             ` Avi Kivity
  0 siblings, 1 reply; 13+ messages in thread
From: Anthony Liguori @ 2011-07-21 15:45 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, Markus Armbruster

On 07/21/2011 10:04 AM, Avi Kivity wrote:
> On 07/21/2011 05:49 PM, Anthony Liguori wrote:
>> On 07/21/2011 08:38 AM, Avi Kivity wrote:
>>> On 07/21/2011 04:20 PM, Anthony Liguori wrote:
>>
>>>> static TypeInfo tcp_server_type_info = {
>>>> .name = TYPE_TCP_SERVER,
>>>> .parent = TYPE_SOCKET_SERVER,
>>>> .instance_size = sizeof(TcpServer),
>>>> .instance_init = tcp_server_init,
>>>> .class_init = tcp_server_class_init,
>>>> };
>>>>
>>>
>>> How do the properties become registered? Ah, I see you do have to
>>> register them. You'd have to do the same in C++, but it would be a lot
>>> simpler and type-safer (you can use pointers to members, for example,
>>> and avoid getter/setters where unnecessary).
>>
>> See git://git.codemonkey.ws/kvm++.git
>>
>
> Connection refused..

Sorry, stupid EC2.  Try http://git.codemonkey.ws/git/kvm++.git


>> It's exactly the same object model, but in C++. Some things are nicer,
>> some things are not nicer. It's not quite a slam dunk.
>>
>> But what really concerned me about it was that I quickly realized that
>> it was going to be mostly write-only code. The C++ tricks that you
>> need to do to make it all work well are extremely obscure. It requires
>> template meta-programming, every obscure detail about partial
>> specialization, etc.
>
> Yes, that's a big worry. Is all of that exposed to the implementer? Or
> just in the framework?

I was able to get it mostly hidden but not entirely.  The biggest 
problem is that even with a semi normal looking function, a simple 
mistake like passing in the wrong number of arguments can result in an 
undecipherable error message.  It's not bad to debug if you're used to 
it but very difficult to just slip in to a C project.

>>>
>>> There is quite a lot of boilerplate - around half the code of tcp.[ch].
>>> It may be simple to create a new type to the author of the framework,
>>> but I doubt it would be simple to others. There would be a lot of
>>> cut'n'paste.
>>
>> Yup. That's the price you pay for using C over C++. But the ratio is
>> only true for simple types. Complex types (look at chrdrv.h), the
>> ratio is much lower.
>
> chrdrv.c is almost 100% boilerplate.

Sure, but so is qemu-char.c and block.c.  It's not really different from 
what we have today.

>>
>>>
>>> We can change the language first.
>>
>> My view is roughly this:
>>
>> 1) introduce type system and update build system
>>
>> 2) convert each backend, add compatibility handlers to preserve
>> existing monitor commands and command line arguments. deprecate
>> everything to be removed in qemu 2.0.
>>
>> 3) introduce a new front end written in Python that only works with
>> the plug interfaces
>>
>> 4) convert the device model. compatibility will be hard to maintain
>> but I think it's doable.
>>
>> 5) declare qemu 2.0, remove all of the compatibility stuff, and
>> potentially move it to a new python script for legacy usage.
>>
>
> The big problem with this plan is that steps 2 and 4 are very difficult
> and yet we see no gains while it's being done.

So at least with the chardev conversion, we'll get the ability to 
dynamically add character devices and change the settings of a chardev 
after start up.  Both of these are important features.

I think done properly, it all can have incremental value.  I worry about 
converting the device model.

> A much smaller job (the
> memory API conversion) is turning out to be no fun at all.

Yeah, I don't know how to fix that.  This is why I'm starting with the 
backends.  They're much smaller than the device model.

>> At this point, qemu would no longer be an executable that was directly
>> invoked by a user. They would use a wrapper script to provide the
>> functionality of today's qemu. Management software could launch the
>> daemon on their own.
>>
>> C++ doesn't eliminate any of these steps. IMHO, it doesn't
>> tremendously simplify any of these steps either.
>
> It trades off a lot of boilerplate (translated to copy'n'paste with all
> its issues) into 20-line error messages. Inheriting from a class and
> implementing all of its pure virtuals is a lot easier than doing the C
> equivalent.

Agreed re: the trade offs.

>>
>> I think *good* C++ could provide some value by eliminating the
>> possibility of buffer overflows, use-after-free, memory-leaks, etc.
>> But that's icing on the cake.
>
> Yes.
>
>> I don't ever see the device model being written in something other
>> than C/C++ too. Having a GC in the VCPU thread would be a major issue
>> IMHO.
>
> We get the equivalent of GC every time a vcpu thread is scheduled out so
> an iothread or an unrelated process can run.

But you can control this with pinning, priorities, etc.  You cannot with GC.

And in quite a lot of systems, GC pauses are very, very long.

> It will hurt hard realtime
> guests, but these are only interesting to a small subset of users.
>
> I think that if we can get the data path to run in pure C, and have the
> GC HLL involved only when the device model is reconfigured, then we have
> an acceptable tradeoff. I don't claim that I know how to do this,
> though. This is a really hard problem, mostly due to the huge size of qemu.

This is one very good thing about having a common object model that's 
pluggable (which is what QOM is all about).  It becomes relatively easy 
to build with CONFIG_PCI=n, then build a shared library that implements 
a new PCI layer in your favorite HLL so that you can experiment.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 15:19         ` Luca Tettamanti
  2011-07-21 15:32           ` Avi Kivity
@ 2011-07-21 15:46           ` Anthony Liguori
  1 sibling, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2011-07-21 15:46 UTC (permalink / raw)
  To: Luca Tettamanti; +Cc: Markus Armbruster, Avi Kivity, qemu-devel

On 07/21/2011 10:19 AM, Luca Tettamanti wrote:
> On Thu, Jul 21, 2011 at 4:49 PM, Anthony Liguori<aliguori@us.ibm.com>  wrote:
> [cut]
>> And it's really not that much nicer than the C version.  The problem with
>> C++ is that even though the type system is much, much nicer, it still
>> doesn't have introspection or decorators.  These two things would be the
>> killer feature for doing the sort of things we need to do and is really
>> where most of the ugliness comes from.
>
> QT has introspection; what about using the core (i.e. QObject and moc)
> to build QEMU object model?

I don't know QT very well except that it's a very odd subset of C++ and 
custom extensions implemented by a preprocessor.

Regards,

Anthony Liguori

>
> L
>

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 15:45           ` Anthony Liguori
@ 2011-07-21 15:57             ` Avi Kivity
  2011-07-21 16:32               ` Anthony Liguori
  0 siblings, 1 reply; 13+ messages in thread
From: Avi Kivity @ 2011-07-21 15:57 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, Markus Armbruster

On 07/21/2011 06:45 PM, Anthony Liguori wrote:
>>> See git://git.codemonkey.ws/kvm++.git
>>>
>>
>> Connection refused..
>
>
> Sorry, stupid EC2.  Try http://git.codemonkey.ws/git/kvm++.git

You don't have permission to access /git/kvm++.git/ on this server.

>
>
>>> It's exactly the same object model, but in C++. Some things are nicer,
>>> some things are not nicer. It's not quite a slam dunk.
>>>
>>> But what really concerned me about it was that I quickly realized that
>>> it was going to be mostly write-only code. The C++ tricks that you
>>> need to do to make it all work well are extremely obscure. It requires
>>> template meta-programming, every obscure detail about partial
>>> specialization, etc.
>>
>> Yes, that's a big worry. Is all of that exposed to the implementer? Or
>> just in the framework?
>
> I was able to get it mostly hidden but not entirely.  The biggest 
> problem is that even with a semi normal looking function, a simple 
> mistake like passing in the wrong number of arguments can result in an 
> undecipherable error message.  It's not bad to debug if you're used to 
> it but very difficult to just slip in to a C project.

I have to agree with this.  You can write neat domain specific languages 
in C++ but the nice abstractions break the minute you misplace a comma.

>
>>>>
>>>> There is quite a lot of boilerplate - around half the code of 
>>>> tcp.[ch].
>>>> It may be simple to create a new type to the author of the framework,
>>>> but I doubt it would be simple to others. There would be a lot of
>>>> cut'n'paste.
>>>
>>> Yup. That's the price you pay for using C over C++. But the ratio is
>>> only true for simple types. Complex types (look at chrdrv.h), the
>>> ratio is much lower.
>>
>> chrdrv.c is almost 100% boilerplate.
>
> Sure, but so is qemu-char.c and block.c.  It's not really different 
> from what we have today.

I'm trying to get us away from boilerplate, actually writing the code 
that matters?

Maybe it's an unsolvable problem.  With a low level language, you get to 
write boilerplate.  With a high level language, the compiler writes it 
for you, and a whole lot more you don't want.

But it's a big problem.  Those conversions suck the life force out of 
whoever's doing them, and then he comes back as zombie to haunt us at 
the next kvm forum.  It's not just type safety at stake here.

>> The big problem with this plan is that steps 2 and 4 are very difficult
>> and yet we see no gains while it's being done.
>
> So at least with the chardev conversion, we'll get the ability to 
> dynamically add character devices and change the settings of a chardev 
> after start up.  Both of these are important features.
>
> I think done properly, it all can have incremental value.  I worry 
> about converting the device model.
>
>> A much smaller job (the
>> memory API conversion) is turning out to be no fun at all.
>
> Yeah, I don't know how to fix that.  This is why I'm starting with the 
> backends.  They're much smaller than the device model.

Ok.  Let's hope you've hit on the least-bad tradeoff.  I'm sceptical, 
but I don't have anything concrete to offer.

>>> I don't ever see the device model being written in something other
>>> than C/C++ too. Having a GC in the VCPU thread would be a major issue
>>> IMHO.
>>
>> We get the equivalent of GC every time a vcpu thread is scheduled out so
>> an iothread or an unrelated process can run.
>
> But you can control this with pinning, priorities, etc.  You cannot 
> with GC.
>
> And in quite a lot of systems, GC pauses are very, very long.

I expect the number of objects we'll have will be very small (O(info qdm 
| wc -l)).  They'll also be very long lived.  Won't that make the GC 
rather fast?

>
>> It will hurt hard realtime
>> guests, but these are only interesting to a small subset of users.
>>
>> I think that if we can get the data path to run in pure C, and have the
>> GC HLL involved only when the device model is reconfigured, then we have
>> an acceptable tradeoff. I don't claim that I know how to do this,
>> though. This is a really hard problem, mostly due to the huge size of 
>> qemu.
>
> This is one very good thing about having a common object model that's 
> pluggable (which is what QOM is all about).  It becomes relatively 
> easy to build with CONFIG_PCI=n, then build a shared library that 
> implements a new PCI layer in your favorite HLL so that you can 
> experiment.

If I wanted a new PCI layer I'd write one outside of qemu.  Getting PC 
emulation is probably easier than converting all of qemu - see tools/kvm 
(though they're not doing full emulation, just the subset needed to get 
Linux going).  I want the old layer, it has a lot of knowledge sweated 
into it and it's very compatible with itself and with the guests it has 
booted.

-- 
error compiling committee.c: too many arguments to function

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 15:57             ` Avi Kivity
@ 2011-07-21 16:32               ` Anthony Liguori
  2011-07-22  7:46                 ` Kevin Wolf
  0 siblings, 1 reply; 13+ messages in thread
From: Anthony Liguori @ 2011-07-21 16:32 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Anthony Liguori, qemu-devel, Markus Armbruster

On 07/21/2011 10:57 AM, Avi Kivity wrote:
> On 07/21/2011 06:45 PM, Anthony Liguori wrote:
>>>> See git://git.codemonkey.ws/kvm++.git
>>>>
>>>
>>> Connection refused..
>>
>>
>> Sorry, stupid EC2. Try http://git.codemonkey.ws/git/kvm++.git
>
> You don't have permission to access /git/kvm++.git/ on this server.

git clone http://git.codemonkey.ws/git/kvm++.git

>>> Yes, that's a big worry. Is all of that exposed to the implementer? Or
>>> just in the framework?
>>
>> I was able to get it mostly hidden but not entirely. The biggest
>> problem is that even with a semi normal looking function, a simple
>> mistake like passing in the wrong number of arguments can result in an
>> undecipherable error message. It's not bad to debug if you're used to
>> it but very difficult to just slip in to a C project.
>
> I have to agree with this. You can write neat domain specific languages
> in C++ but the nice abstractions break the minute you misplace a comma.

Yeah, I love C++, but am empathic towards people who don't share my 
affection.

>>>> Yup. That's the price you pay for using C over C++. But the ratio is
>>>> only true for simple types. Complex types (look at chrdrv.h), the
>>>> ratio is much lower.
>>>
>>> chrdrv.c is almost 100% boilerplate.
>>
>> Sure, but so is qemu-char.c and block.c. It's not really different
>> from what we have today.
>
> I'm trying to get us away from boilerplate, actually writing the code
> that matters?

Yeah, I'm with you, but if you figure out how to get all of the 
performance of C/C++, with nice understandable error messages, while 
avoiding writing any unnecessary code than I'm sure you'll be receiving 
the Turing award 20 years from now :-)

> But it's a big problem. Those conversions suck the life force out of
> whoever's doing them, and then he comes back as zombie to haunt us at
> the next kvm forum. It's not just type safety at stake here.

There are many problems to solve and I think we have to attack them 
systematically.

The problem I'm trying to solve here is that we're duplicating the same 
infrastructure over and over again.  Namely, we're inventing object 
models at every opportunity.  qdev, BDS, VLANClientState, 
CharDriverState, FsDev, DisplayState, etc.  The madness has to stop.

Just as we're now realizing that we need to do dramatic things in the 
block layer to make -blockdev work, I'm sure we're going to realize that 
we want to do PCI hotplug of virtio-serial and therefore we need to do 
dynamic creation/destruction of character devices.

We need to come up with a single way to make this work for everything.

Reducing boiler plate code is yet another problem, and I'll argue a much 
less critical one.  I'm all for solving it, but rome wasn't built in a day.


>>> The big problem with this plan is that steps 2 and 4 are very difficult
>>> and yet we see no gains while it's being done.
>>
>> So at least with the chardev conversion, we'll get the ability to
>> dynamically add character devices and change the settings of a chardev
>> after start up. Both of these are important features.
>>
>> I think done properly, it all can have incremental value. I worry
>> about converting the device model.
>>
>>> A much smaller job (the
>>> memory API conversion) is turning out to be no fun at all.
>>
>> Yeah, I don't know how to fix that. This is why I'm starting with the
>> backends. They're much smaller than the device model.
>
> Ok. Let's hope you've hit on the least-bad tradeoff. I'm sceptical, but
> I don't have anything concrete to offer.

I've got lots of ideas, but want to focus on backends first because 
that's the biggest bang for the buck right now.

>>>> I don't ever see the device model being written in something other
>>>> than C/C++ too. Having a GC in the VCPU thread would be a major issue
>>>> IMHO.
>>>
>>> We get the equivalent of GC every time a vcpu thread is scheduled out so
>>> an iothread or an unrelated process can run.
>>
>> But you can control this with pinning, priorities, etc. You cannot
>> with GC.
>>
>> And in quite a lot of systems, GC pauses are very, very long.
>
> I expect the number of objects we'll have will be very small (O(info qdm
> | wc -l)). They'll also be very long lived. Won't that make the GC
> rather fast?

Really depends on the language and the JIT implementation.  Small 
objects that are short lived can lead to the need to do compaction. 
Some JITs do compaction in such a way that there is a periodic very long 
pause (even up to 10ms).

>>> It will hurt hard realtime
>>> guests, but these are only interesting to a small subset of users.
>>>
>>> I think that if we can get the data path to run in pure C, and have the
>>> GC HLL involved only when the device model is reconfigured, then we have
>>> an acceptable tradeoff. I don't claim that I know how to do this,
>>> though. This is a really hard problem, mostly due to the huge size of
>>> qemu.
>>
>> This is one very good thing about having a common object model that's
>> pluggable (which is what QOM is all about). It becomes relatively easy
>> to build with CONFIG_PCI=n, then build a shared library that
>> implements a new PCI layer in your favorite HLL so that you can
>> experiment.
>
> If I wanted a new PCI layer I'd write one outside of qemu. Getting PC
> emulation is probably easier than converting all of qemu - see tools/kvm
> (though they're not doing full emulation, just the subset needed to get
> Linux going). I want the old layer, it has a lot of knowledge sweated
> into it and it's very compatible with itself and with the guests it has
> booted.

What I meant is that if you wanted to port the PCI layer to another 
langauge, you could do it because there are well defined boundaries that 
can be bounded to dynamic languages.  It boils down to the fact that 
there's standard ways to do things like invoke methods on objects, 
introspect properties, etc.  That provides the ability to do incremental 
integration of HLLs.

Regards,

Anthony Liguori

>

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-21 16:32               ` Anthony Liguori
@ 2011-07-22  7:46                 ` Kevin Wolf
  2011-07-22 12:40                   ` Anthony Liguori
  0 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2011-07-22  7:46 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Markus Armbruster, Anthony Liguori, Avi Kivity, qemu-devel

Am 21.07.2011 18:32, schrieb Anthony Liguori:
> Just as we're now realizing that we need to do dramatic things in the 
> block layer to make -blockdev work, I'm sure we're going to realize that 
> we want to do PCI hotplug of virtio-serial and therefore we need to do 
> dynamic creation/destruction of character devices.

Just to have it said: -blockdev isn't the reason for doing something
like this. The reason is that you want it. (Not saying anything about
whether it is a good or a bad thing to want)

What -blockdev really needs is an additional parameter to bdrv_open that
carries the options. Could be as simple as a QDict, though that might
not align well with your QAPI which wants everything to be C. But in any
case, generalising the qdev properties mechanism to be usable in other
contexts should be enough for anything.

There's really no pressing need to start yet another rewrite of half of
qemu just for -blockdev. And in turn -blockdev doesn't have to wait for
such a rewrite.

Kevin

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-22  7:46                 ` Kevin Wolf
@ 2011-07-22 12:40                   ` Anthony Liguori
  2011-07-22 13:15                     ` Kevin Wolf
  0 siblings, 1 reply; 13+ messages in thread
From: Anthony Liguori @ 2011-07-22 12:40 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, Anthony Liguori, Markus Armbruster, Avi Kivity

On 07/22/2011 02:46 AM, Kevin Wolf wrote:
> Am 21.07.2011 18:32, schrieb Anthony Liguori:
>> Just as we're now realizing that we need to do dramatic things in the
>> block layer to make -blockdev work, I'm sure we're going to realize that
>> we want to do PCI hotplug of virtio-serial and therefore we need to do
>> dynamic creation/destruction of character devices.
>
> Just to have it said: -blockdev isn't the reason for doing something
> like this. The reason is that you want it. (Not saying anything about
> whether it is a good or a bad thing to want)
>
> What -blockdev really needs is an additional parameter to bdrv_open that
> carries the options. Could be as simple as a QDict, though that might
> not align well with your QAPI which wants everything to be C. But in any
> case, generalising the qdev properties mechanism to be usable in other
> contexts should be enough for anything.

That's what QOM is.  qdev generalized.

The problem with "just adding a QDict to bdrv_open" is that you're only 
solving the problem for the block layer.  The fundamental problem that 
we're trying to solve with blockdev is creating backends independently 
of devices and connecting backends to each other.

Chardev has the same need (via mux devices).

Regards,

Anthony Liguori

>
> There's really no pressing need to start yet another rewrite of half of
> qemu just for -blockdev. And in turn -blockdev doesn't have to wait for
> such a rewrite.
>
> Kevin
>

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-22 12:40                   ` Anthony Liguori
@ 2011-07-22 13:15                     ` Kevin Wolf
  2011-07-22 13:52                       ` Anthony Liguori
  0 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2011-07-22 13:15 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: qemu-devel, Anthony Liguori, Markus Armbruster, Avi Kivity

Am 22.07.2011 14:40, schrieb Anthony Liguori:
> On 07/22/2011 02:46 AM, Kevin Wolf wrote:
>> Am 21.07.2011 18:32, schrieb Anthony Liguori:
>>> Just as we're now realizing that we need to do dramatic things in the
>>> block layer to make -blockdev work, I'm sure we're going to realize that
>>> we want to do PCI hotplug of virtio-serial and therefore we need to do
>>> dynamic creation/destruction of character devices.
>>
>> Just to have it said: -blockdev isn't the reason for doing something
>> like this. The reason is that you want it. (Not saying anything about
>> whether it is a good or a bad thing to want)
>>
>> What -blockdev really needs is an additional parameter to bdrv_open that
>> carries the options. Could be as simple as a QDict, though that might
>> not align well with your QAPI which wants everything to be C. But in any
>> case, generalising the qdev properties mechanism to be usable in other
>> contexts should be enough for anything.
> 
> That's what QOM is.  qdev generalized.

Hm, yes, quite possible.

Then maybe it's just its usage that I'm not happy with. You're turning
the block layer upside down to change BlockDriverStates and BDRV*State
to fit this API, which at the first sight looks pretty invasive. I was
thinking of an object not for the whole BDS, but just for the same
purpose as the QDict would have been used, that is something that can be
passed to bdrv_open.

On the other hand, it's really hard to quickly see in your git tree what
changes QOM really means. Real patches to the existing code would be
much more useful than an additional modified copy of the file.

Kevin

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

* Re: [Qemu-devel] [RFC] QEMU Object Model
  2011-07-22 13:15                     ` Kevin Wolf
@ 2011-07-22 13:52                       ` Anthony Liguori
  0 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2011-07-22 13:52 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Avi Kivity, qemu-devel, Markus Armbruster

On 07/22/2011 08:15 AM, Kevin Wolf wrote:
> Am 22.07.2011 14:40, schrieb Anthony Liguori:
>> On 07/22/2011 02:46 AM, Kevin Wolf wrote:
>>> Am 21.07.2011 18:32, schrieb Anthony Liguori:
>>>> Just as we're now realizing that we need to do dramatic things in the
>>>> block layer to make -blockdev work, I'm sure we're going to realize that
>>>> we want to do PCI hotplug of virtio-serial and therefore we need to do
>>>> dynamic creation/destruction of character devices.
>>>
>>> Just to have it said: -blockdev isn't the reason for doing something
>>> like this. The reason is that you want it. (Not saying anything about
>>> whether it is a good or a bad thing to want)
>>>
>>> What -blockdev really needs is an additional parameter to bdrv_open that
>>> carries the options. Could be as simple as a QDict, though that might
>>> not align well with your QAPI which wants everything to be C. But in any
>>> case, generalising the qdev properties mechanism to be usable in other
>>> contexts should be enough for anything.
>>
>> That's what QOM is.  qdev generalized.
>
> Hm, yes, quite possible.
>
> Then maybe it's just its usage that I'm not happy with. You're turning
> the block layer upside down to change BlockDriverStates and BDRV*State
> to fit this API, which at the first sight looks pretty invasive.

The changes are pretty systematic and boil down to:

1) Instead of BlockDriverState having an opaque pointer that points to 
BDRVQcowState, BDRVQcowState contains a BlockDriverState and you use the 
equivalent of container_of() to access it.

2) Instead of creating an empty BDS and then creating the substate and 
setting opaque, you create the substate through a factory.

3) Instead of passing a single const char * to bdrv_open(), each driver 
registers the options it supports.  There is still an open() but the 
open takes no parameters because the parameters are set before open() is 
called.

4) Instead of having a fixed backing_file and file BDS * in BDS, each 
driver can register as many named BDS * as they want.

It shouldn't change much code at all in the image formats.  The only 
place that it will really change is block.c but not any of the code that 
actually matters.

> I was
> thinking of an object not for the whole BDS, but just for the same
> purpose as the QDict would have been used, that is something that can be
> passed to bdrv_open.

Passing a QDict to bdrv_open() would allow you to set more properties, 
but there are other things that need to be address:

a) how do you describe which properties are valid for a given image format?

b) how do you specify how a backing_file gets initialized?

c) how do support composing a BDS from multiple BDS's (to support VMDK's 
fully)?

I think once you come up with a mechanism to do all of this, you get 90% 
of what QOM.  By doing the extra 10%, we don't have to reinvent this for 
every other subsystem.

netdev and qdev have already done this, but in different ways.  Doing 
this in a third way would be pretty bad IMHO.

>
> On the other hand, it's really hard to quickly see in your git tree what
> changes QOM really means. Real patches to the existing code would be
> much more useful than an additional modified copy of the file.

I'll have the first RFC out next week.  Just trying to get some input as 
early as possible.

Regards,

Anthony Liguori

>
> Kevin
>

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

end of thread, other threads:[~2011-07-22 13:52 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-19 15:14 [Qemu-devel] [RFC] QEMU Object Model Anthony Liguori
     [not found] ` <4E2824D2.2050401@redhat.com>
     [not found]   ` <4E2827A2.6010603@us.ibm.com>
     [not found]     ` <4E282BE3.1050404@redhat.com>
2011-07-21 14:49       ` Anthony Liguori
2011-07-21 15:04         ` Avi Kivity
2011-07-21 15:45           ` Anthony Liguori
2011-07-21 15:57             ` Avi Kivity
2011-07-21 16:32               ` Anthony Liguori
2011-07-22  7:46                 ` Kevin Wolf
2011-07-22 12:40                   ` Anthony Liguori
2011-07-22 13:15                     ` Kevin Wolf
2011-07-22 13:52                       ` Anthony Liguori
2011-07-21 15:19         ` Luca Tettamanti
2011-07-21 15:32           ` Avi Kivity
2011-07-21 15:46           ` Anthony Liguori

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