Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 05:13:41PM -0600, Anthony Liguori wrote:
 On 11/28/2010 04:28 PM, Michael S. Tsirkin wrote:
 
 But rather need to use ugly factory functions with all sorts of
 DO_UPCAST.  This is really unfriendly especially for writing test
 cases.
 Yes, I agree. Just moving memory allocation out of there
 will fix most of the ugliness.
 
 So here's a short list of things I've been working on that I don't
 believe have nice implementations in C.
 
 1) Factories with string based parameters with natural constructor
 arguments.

This was the only item, right?  So in fact, this is needed as part of
configuration file/command line/monitor parser.

IMHO, this really should be separate from the device model.
The fact that qdev currently mixes the device model
with argument parsing is bad IMO. So we ended up with
saying
.driver   = PCI
in hw/pc_piix.c instead of an instance of the structure.
There's no compile-time check that the correct string
is used and that is pretty bad IMO.
Yes, this makes it easier to add new properties, but making it easy is
exactly the wrong thing to do because we really have to support such
properties forever.

So how about a compromise: libqemu written in C, with APIs that should
not deal with string parsing at all, and should above all else make
sense:
i8254_init_drift_mode
i8254_init_catchup

net_set_link_up
net_set_link_down

(and it really needs to be C for portability: so that management
 written in C can use it).
This API should be properly versioned, with a backwards compatibility
story, and we should be careful about adding interfaces there.

On top of this you can have a management interface written in
any other language, and have that deal with string parsing.

-- 
MST
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Avi Kivity

On 11/28/2010 06:57 PM, Michael S. Tsirkin wrote:

  
  sparce lets you solve C problems that C++ inherited as is.
  E.g. if you have a pointer you can always dereference it.

  It's the other way round.

  For example __user cannot be done in C.  It has to be done as an add-on.

  In C++ it's simply:

templateclass T
class user_ptrT
{
public:
explicit user_ptr(unsigned long addr);
void copy_from(T  to); // throws EFAULT
void copy_to(const T  from); // throws EFAULT
private:
unsigned long addr;
};

This does not allow simple uses such as arithmetic,


Add a raw_addr() method that returns addr.


void,


Fixable.


  builtin
types,


should work


  sizeof,


sizeof(T)?


arrays,


should work


  NULL comparizon,


Do we ever compare __user pointers against NULL?  It's  a valid address.


inheritance, cast,


What do these mean in the context of user pointers?


memory management.


And this?


Examples to ponder: what is the appropriate value of T for void *?


Probably a specialization user_ptr or a separate class user_void_ptr.  
After all you can't do anthing with such a pointer.



What if you want a shared/auto ptr to manage this memory?


What does it mean for user pointers?


Some of these might be fixable, with a lot of code.
Boost might haver some solutions, I haven't looked.

Meanwhile sparse is already there.


With sparse you have to implement every rule in a separate compiler.  
With C++ you introduce the rules into the code.



  No need for an additional toolchain.

It's a feature :) This way  you are not forced to rewrite all code each
time you realize you need an extra check, and checks can be added
gradually without breaking build.


You can see that user_ptr is not just for the checks, it adds 
functionality (sizeof-less copy_from and copy_to).  That's usually the 
case.  If there's something you must not do because of some rule, 
there's also something you want to do, and those become member functions.


In C++ you could also introduce user_ptr gradually, it won't break 
anything.



  
 Things like __user are easily done in C++.
  
  Some of what sparce does can be done if you create a separate type for
  all address spaces.  This can be done in C too, and the result won't
  be like __user at all.

  That's quite a lot of work.

   Sparse:  T __user *foo;
   C++: user_ptrT  foo;

Sparse has some advantages: it makes the contract obvious so you clearly
see it's a pointer and know -, [], + will work, * and  will not.


I don't really see how you can tell this from __user.  You have to look 
up the definition.  For user_ptr, the definition is actually available.



   C : struct T_user_ptr { unsigned long addr } foo; + lots of accessors.

Some kind of macro can be closer to user_ptr above.


Those macros are called templates, and the compiler can check that they 
are used correctly.





 C++ support in gdb has some limitations
 if you use overloading, exceptions, templates. The example posted here
 uses two of these, so it would be harder to debug.
  
 I haven't seen issues with overloading or exceptions.
  
  Build your test with -g, fire up gdb from command line,
  try to put a breakpoint in the constructor of
  the fd object, maybe you will see what I mean :)
  
  (gdb) break 'kvm::fd::fd'
  Breakpoint 3 at 0x8049650: file api/kvmxx.cc, line 25.
  Breakpoint 4 at 0x8049628: file api/kvmxx.cc, line 31.
  Breakpoint 5 at 0x8049080: file api/kvmxx.cc, line 21

But it's hard to figure out that you need the kvm namespace.  Your code
only has one namespace, but with multiple namespaces, you don't even
know in which namespace to look up the fd.  With templates you might not
even know the fd class.


If you like, you can avoid namespaces and prefix everything with kvm_.  
I never found it necessary.



  An example of an issue with overloading is that gdb seems unable to resolve
  them properly depending on the current scope.  So you see a call to
  foo() and want to put a breakpoint there, first problem is just to find
  one which namespace it is in. Once you did the best
  it can do it prompt you to select one of the overloaded options.
  How do you know which one do you want? You don't, so you guess. Sometimes
  gdb will guess, because of a complex set of name resolution rules, and
  sometimes it will this wrongly.
  Which is not what I want to spend mental cycles on when I am debugging a 
problem.
  
  Functions using exceptions can not be called from the gdb prompt
  (gdb is not smart enough to catch them).
  
  There are more issues.

  That's not restricted to gdb.  C has just three scopes: block (may
  be nested), file static, and global.  C++ has more.  Stating
  everything leads to verbose code and potential conflicts.  Having
  more scopes allows tighter code usually

  but more head-scratching if
  something goes wrong.

  In my experience conflicts are very rare.  But it's true that when
  they happen 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Avi Kivity

On 11/28/2010 04:40 PM, Michael S. Tsirkin wrote:

On Sun, Nov 28, 2010 at 03:14:17PM +0200, Avi Kivity wrote:
  On 11/28/2010 01:44 PM, Michael S. Tsirkin wrote:
  On Sun, Nov 28, 2010 at 11:54:26AM +0200, Avi Kivity wrote:
 On 11/28/2010 11:50 AM, Michael S. Tsirkin wrote:
 
 Another problem is that there seem to be two memory allocations 
and a
 copy here, apparently just to simplify error handling.  It might 
be fine
 for this test but won't scale for when performance matters.
 
 When it matters, we can fix it.  I don't see msr read/write 
becoming
 a hot path.
 
 It will be very painful to fix it.
  
 Why?
  
  Because the API returns a vector.

  Returning an object does not involve a copy (return value optimization).

Yes, but assigning the value in the code that uses it will, unless again
you do this in an initializer.


So do that.



  This code is not reusable.  Everywhere you use an fd, you have to
  repeat this code.

But that's not a lot of code. And you can abstract it away at a higher
level. For example kvm_init and kvm_cleanup would setup/cleanup
state in a consistent way.


That's not what we see in C code.  The error handling gets everywhere, 
obscuring what's actually going on, and usually getting it wrong by leaking.



My experience tells me C++ code has much more boilerplate code that you
are forced to repeat over and over.  This is especially true for unix
system programming:  by the time you are done wrapping all of unix you
have created more LOC than you are ever likely to save.


You don't need to wrap everything.  Sometimes you can get away with if 
(ret == -1) throw.  But things like file descriptors are essential.




  class kvm::fd is reusable, if you embed it in another object you
  don't have to worry about errors any more (as long as the object's
  methods are exception safe).

To get exception safe code, you have to constantly worry about errors.
And it's easier to spot an unhandled return code than exception-unsafe
code:  gcc actually has  __attribute__((warn_unused_result)) which
might help catch common errors. No such tool to catch
exception-unsafe code AFAIK.


We see exactly how easy it is by the constant stream of patches that fix 
error paths into Linux.  Most user space programs don't even care about 
errors because they're so difficult and annoying to get right.



  Yes, all the correctness is more or less pointless here.  Like I
  said, this is an experiment to see what things look like.  I guess
  each side will it as proving its claims.

This is exactly what seems to be happening.
I did my best to try and be objective and point out real issues,
but you probably guessed which side I am on already :).


The lack of the C++ compiler eats babies and line noise comments is 
appreciated.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Avi Kivity

On 11/28/2010 04:49 PM, Michael S. Tsirkin wrote:

On Sun, Nov 28, 2010 at 03:15:52PM +0200, Avi Kivity wrote:
  On 11/28/2010 01:49 PM, Michael S. Tsirkin wrote:
 +++ b/api/kvmxx.cc
 @@ -0,0 +1,168 @@
 +#include kvmxx.h
 +#includefcntl.h
 +#includesys/ioctl.h
 +#includesys/mman.h
  
  I just realized this is wrong: I think you should wrap
  the headers in extern C. Same for other headers.

  I think system headers already do this
  (otherwise it won't link -
  int foo() is different than extern C { int foo(void); })

okay, but they aren't there for linux/kvm.h, are they?


I don't think they are needed - they only declare structures and 
constants, not functions.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Michael S. Tsirkin
On Mon, Nov 29, 2010 at 11:22:44AM +0200, Avi Kivity wrote:
   No need for an additional toolchain.
 
 It's a feature :) This way  you are not forced to rewrite all code each
 time you realize you need an extra check, and checks can be added
 gradually without breaking build.
 
 You can see that user_ptr is not just for the checks, it adds
 functionality (sizeof-less copy_from and copy_to).  That's usually
 the case.  If there's something you must not do because of some
 rule, there's also something you want to do, and those become member
 functions.
 
 In C++ you could also introduce user_ptr gradually, it won't break
 anything.

Yes but in
void foo(void *p) {
bar(p);
}
both foo and bar must be converted.

   
  Things like __user are easily done in C++.
   
   Some of what sparce does can be done if you create a separate type for
   all address spaces.  This can be done in C too, and the result won't
   be like __user at all.
 
   That's quite a lot of work.
 
Sparse:  T __user *foo;
C++: user_ptrT  foo;
 
 Sparse has some advantages: it makes the contract obvious so you clearly
 see it's a pointer and know -, [], + will work, * and  will not.
 
 I don't really see how you can tell this from __user.

I can tell this is a pointer from T *foo :), and I can tell
it has some attribute.

  You have to
 look up the definition.  For user_ptr, the definition is actually
 available.

The definition for __user is also available:
#ifdef __CHECKER__
# define __user__attribute__((noderef, address_space(1)))
#else
# define __user
#endif

Which is a very transparent way to say: this is just a checker
attribute, it does not affect actual code.

With a template we go 'I have overridden + but compiler should
optimize it back to original'. Note the should :)

   Templates are
  indeed harder to debug, simply because names can become very long.
   
   That's not the only problem. A bigger one is when you type tab to
   complete function name and get a list of options to select from for each
   of the times a template was instantiated.  Only one of them is relevant
   in a given scope. No hint is given which.  Further when you step into
   the template, the source does not give you any hint about the types
   used.
   
   Some of this is true for macros as well of course. Except people know
   macros are bad and so make them thin wrappers around proper functions.
 
   Or they simply avoid it and duplicate the code.  You can't always
   wrap functions with macros.
 
 Always is a strong word.  What are the examples of such duplicated code
 in qemu?  Let's see if they are easy to fix.
 
 qemu in fact uses macros extensively (glue()), they are hardly readable.

Well, we don't have so many instances left anymore.

We used to have this in pci and I got rid of it pretty easily,
just passing in length at runtime. And it turned out the only reason
for it was because we didn't pass in the transaction length.
That technique (clean up APIs so we don't have to work around
them with macros) leads IMO to better code than just sticking
a tamplate around it.

 Do a 'git grep hash' for examples of duplication.

I see. Don't know enough about tcg to fix unfortunately, but
the logic is different: e.g. sparc opcode table is completely
static, translation cache is dynamic, jump cache has
static size but dynamic content, qdict could do
with linear lookups just as well. So it could
just be different optimization strategies.

 -- 
 error compiling committee.c: too many arguments to function
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Avi Kivity

On 11/29/2010 12:47 PM, Michael S. Tsirkin wrote:

On Mon, Nov 29, 2010 at 11:22:44AM +0200, Avi Kivity wrote:
 No need for an additional toolchain.
  
  It's a feature :) This way  you are not forced to rewrite all code each
  time you realize you need an extra check, and checks can be added
  gradually without breaking build.

  You can see that user_ptr  is not just for the checks, it adds
  functionality (sizeof-less copy_from and copy_to).  That's usually
  the case.  If there's something you must not do because of some
  rule, there's also something you want to do, and those become member
  functions.

  In C++ you could also introduce user_ptr  gradually, it won't break
  anything.

Yes but in
void foo(void *p) {
bar(p);
}
both foo and bar must be converted.


No.  You can convert from user_ptr to __user * and back.


  Sparse has some advantages: it makes the contract obvious so you clearly
  see it's a pointer and know -, [], + will work, * and   will not.

  I don't really see how you can tell this from __user.

I can tell this is a pointer from T *foo :), and I can tell
it has some attribute.

   You have to
  look up the definition.  For user_ptr, the definition is actually
  available.

The definition for __user is also available:
#ifdef __CHECKER__
# define __user__attribute__((noderef, address_space(1)))
#else
# define __user
#endif

Which is a very transparent way to say: this is just a checker
attribute, it does not affect actual code.


Can you tell you must not dereference it?


With a template we go 'I have overridden + but compiler should
optimize it back to original'. Note the should :)


We do this in C all the time with pte_t and lots of inlines.


  Do a 'git grep hash' for examples of duplication.

I see. Don't know enough about tcg to fix unfortunately, but
the logic is different: e.g. sparc opcode table is completely
static, translation cache is dynamic, jump cache has
static size but dynamic content, qdict could do
with linear lookups just as well. So it could
just be different optimization strategies.


The default is duplication.  With C++ your default is 
tr1::unordered_map and you can optimize it later if you like.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Michael S. Tsirkin
On Mon, Nov 29, 2010 at 12:52:29PM +0200, Avi Kivity wrote:
 The default is duplication.  With C++ your default is
 tr1::unordered_map and you can optimize it later if you like.

BTW not relevant to kvm, but for qemu, some people seem to care about
building with an old migw compiler in Debian stable which is unlikely to
have tr1.  If we drop this we'll also have a working %llx in printf :)

 -- 
 error compiling committee.c: too many arguments to function
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Anthony Liguori

On 11/29/2010 05:26 AM, Michael S. Tsirkin wrote:

On Mon, Nov 29, 2010 at 12:52:29PM +0200, Avi Kivity wrote:
   

The default is duplication.  With C++ your default is
tr1::unordered_map  and you can optimize it later if you like.
 

BTW not relevant to kvm, but for qemu, some people seem to care about
building with an old migw compiler in Debian stable which is unlikely to
have tr1.  If we drop this we'll also have a working %llx in printf :)
   


Boost has a very compatible tr1 library.

Regards,

Anthony Liguori


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Anthony Liguori

On 11/29/2010 02:04 AM, Michael S. Tsirkin wrote:

On Sun, Nov 28, 2010 at 05:13:41PM -0600, Anthony Liguori wrote:
   

On 11/28/2010 04:28 PM, Michael S. Tsirkin wrote:
 
   

But rather need to use ugly factory functions with all sorts of
DO_UPCAST.  This is really unfriendly especially for writing test
cases.
 

Yes, I agree. Just moving memory allocation out of there
will fix most of the ugliness.
   

So here's a short list of things I've been working on that I don't
believe have nice implementations in C.

1) Factories with string based parameters with natural constructor
arguments.
 

This was the only item, right?  So in fact, this is needed as part of
configuration file/command line/monitor parser.
   


I really see it more as an API interface.  I think the best long term 
architecture for QEMU is where qemu is launched as essentially a daemon 
and is manipulated via an RPC interface to create an initial device 
model, etc.



IMHO, this really should be separate from the device model.
The fact that qdev currently mixes the device model
with argument parsing is bad IMO. So we ended up with
saying
.driver   = PCI
in hw/pc_piix.c instead of an instance of the structure.
There's no compile-time check that the correct string
is used and that is pretty bad IMO.
   


Indeed.


Yes, this makes it easier to add new properties, but making it easy is
exactly the wrong thing to do because we really have to support such
properties forever.
   


One advantage of having a factory and the objects in a single place is 
that the factory is the long term supported interface and the objects 
can evolve in a more natural fashion.



So how about a compromise: libqemu written in C, with APIs that should
not deal with string parsing at all, and should above all else make
sense:
i8254_init_drift_mode
i8254_init_catchup

net_set_link_up
net_set_link_down

(and it really needs to be C for portability: so that management
  written in C can use it).
This API should be properly versioned, with a backwards compatibility
story, and we should be careful about adding interfaces there.

On top of this you can have a management interface written in
any other language, and have that deal with string parsing.
   


I still dislike the idea of implementing an object system in C.  Besides 
reinventing vtables, we'll have to also reinvent RTTI to allow for safe 
upcasting (which is unavoidable).


But really, let's defer this discussion for when patches are available.  
I understand your objections but I'm pretty convinced that the code will 
speak for itself when it's ready.


Regards,

Anthony Liguori


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-29 Thread Avi Kivity

On 11/29/2010 03:44 PM, Anthony Liguori wrote:


But really, let's defer this discussion for when patches are 
available.  I understand your objections but I'm pretty convinced that 
the code will speak for itself when it's ready.




It will, but everyone will hear something different.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sat, Nov 27, 2010 at 11:12:58AM +0200, Avi Kivity wrote:
 On 11/26/2010 12:16 PM, Michael S. Tsirkin wrote:
 On Wed, Nov 24, 2010 at 12:52:11PM +0200, Avi Kivity wrote:
   Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
 
   Signed-off-by: Avi Kivitya...@redhat.com
 
 ioctlp calls below ignore possible errors.
 Somre more comments below.
 
 
 Can you elaborate?  The simply propagate the exception.

I was confused by this:

+long ioctlp(unsigned nr, void *arg) {
+   return ioctl(nr, reinterpret_castlong(arg));
+}


ioctl here is not the C ioctl function.  It's the local method that
throws exceptions on errors. This will likely confuse others
as well.


   +
   +vcpu::~vcpu()
   +{
   +unsigned mmap_size = _vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 
  0);
 
 This might throw an exception on destructor path, if this happens
 because an exception was thrown terminate is called.
 
 Fixed.
 
   +
   +std::vectorkvm_msr_entry  vcpu::msrs(std::vectoruint32_t  indices)
   +{
   +std::auto_ptrkvm_msrs  msrs(alloc_msr_list(indices.size()));
 
 This looks wrong. auto_ptr frees memory with delete,
 alloc_msr_list allocates it with malloc.
 
 Anthony pointed this out as well.

Another problem is that there seem to be two memory allocations and a
copy here, apparently just to simplify error handling.  It might be fine
for this test but won't scale for when performance matters.

  Fixed by replacing
 alloc_msr_list() by an object.

It seems that any action which has side effects which needs to be
undone on error, we will have to have a new class with constructor doing
the work. This will likely create much more lines of code
than a simple goto end strategy.

One also wonders how well will the compiler be able to optimize
such complex code, and by how much will compile times go up.

Any input on that?

 
 -- 
 
 I have a truly marvellous patch that fixes the bug which this
 signature is too narrow to contain.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Avi Kivity

On 11/28/2010 10:58 AM, Michael S. Tsirkin wrote:

On Sat, Nov 27, 2010 at 11:12:58AM +0200, Avi Kivity wrote:
  On 11/26/2010 12:16 PM, Michael S. Tsirkin wrote:
  On Wed, Nov 24, 2010 at 12:52:11PM +0200, Avi Kivity wrote:
 Introduce exception-safe objects for calling system, vm, and vcpu 
ioctls.
  
 Signed-off-by: Avi Kivitya...@redhat.com
  
  ioctlp calls below ignore possible errors.
  Somre more comments below.
  

  Can you elaborate?  The simply propagate the exception.

I was confused by this:

+long ioctlp(unsigned nr, void *arg) {
+   return ioctl(nr, reinterpret_castlong(arg));
+}


ioctl here is not the C ioctl function.  It's the local method that
throws exceptions on errors. This will likely confuse others
as well.


Could do this-ioctl(), though I don't much like it.


 +
 +std::vectorkvm_msr_entry   vcpu::msrs(std::vectoruint32_t   
indices)
 +{
 +std::auto_ptrkvm_msrs   msrs(alloc_msr_list(indices.size()));
  
  This looks wrong. auto_ptr frees memory with delete,
  alloc_msr_list allocates it with malloc.

  Anthony pointed this out as well.

Another problem is that there seem to be two memory allocations and a
copy here, apparently just to simplify error handling.  It might be fine
for this test but won't scale for when performance matters.


When it matters, we can fix it.  I don't see msr read/write becoming a 
hot path.



   Fixed by replacing
  alloc_msr_list() by an object.

It seems that any action which has side effects which needs to be
undone on error, we will have to have a new class with constructor doing
the work. This will likely create much more lines of code
than a simple goto end strategy.


It creates correctness.  The equivalent in qemu is to create a constant 
size array on the stack, because people can't be bothered with error 
checking.


The lines of code pay back as soon as there is some reuse (2x in this case).


One also wonders how well will the compiler be able to optimize
such complex code, and by how much will compile times go up.

Any input on that?


The compiler should optimize it away completely.  There's been a lot of 
work in gcc on that.


About compile times, I don't care much.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 11:31:09AM +0200, Avi Kivity wrote:
 On 11/28/2010 10:58 AM, Michael S. Tsirkin wrote:
 On Sat, Nov 27, 2010 at 11:12:58AM +0200, Avi Kivity wrote:
   On 11/26/2010 12:16 PM, Michael S. Tsirkin wrote:
   On Wed, Nov 24, 2010 at 12:52:11PM +0200, Avi Kivity wrote:
  Introduce exception-safe objects for calling system, vm, and vcpu 
  ioctls.
   
  Signed-off-by: Avi Kivitya...@redhat.com
   
   ioctlp calls below ignore possible errors.
   Somre more comments below.
   
 
   Can you elaborate?  The simply propagate the exception.
 
 I was confused by this:
 
 +long ioctlp(unsigned nr, void *arg) {
 +   return ioctl(nr, reinterpret_castlong(arg));
 +}
 
 
 ioctl here is not the C ioctl function.  It's the local method that
 throws exceptions on errors. This will likely confuse others
 as well.
 
 Could do this-ioctl(), though I don't much like it.
  +
  +std::vectorkvm_msr_entry   vcpu::msrs(std::vectoruint32_t   
  indices)
  +{
  +std::auto_ptrkvm_msrs   msrs(alloc_msr_list(indices.size()));
   
   This looks wrong. auto_ptr frees memory with delete,
   alloc_msr_list allocates it with malloc.
 
   Anthony pointed this out as well.
 
 Another problem is that there seem to be two memory allocations and a
 copy here, apparently just to simplify error handling.  It might be fine
 for this test but won't scale for when performance matters.
 
 When it matters, we can fix it.  I don't see msr read/write becoming
 a hot path.

It will be very painful to fix it.


Fixed by replacing
   alloc_msr_list() by an object.
 
 It seems that any action which has side effects which needs to be
 undone on error, we will have to have a new class with constructor doing
 the work. This will likely create much more lines of code
 than a simple goto end strategy.
 
 It creates correctness.  The equivalent in qemu is to create a
 constant size array on the stack, because people can't be bothered
 with error checking.
 
 The lines of code pay back as soon as there is some reuse (2x in this case).
 
 One also wonders how well will the compiler be able to optimize
 such complex code, and by how much will compile times go up.
 
 Any input on that?
 
 The compiler should optimize it away completely.

Should as opposed to does.  Want me to try a simple test?

  There's been a lot
 of work in gcc on that.
 
 About compile times, I don't care much.

I do. You will too when we have codebase that can be built as fast as
we commit things, so buildbot breaks.
This is common in C++ based projects.

 -- 
 error compiling committee.c: too many arguments to function
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Avi Kivity

On 11/28/2010 11:50 AM, Michael S. Tsirkin wrote:

  
  Another problem is that there seem to be two memory allocations and a
  copy here, apparently just to simplify error handling.  It might be fine
  for this test but won't scale for when performance matters.

  When it matters, we can fix it.  I don't see msr read/write becoming
  a hot path.

It will be very painful to fix it.


Why?  One copy is necessary (it's due to the bad kvm API), but we can 
avoid the others.


In any case the data will be copied by the kernel.




  The compiler should optimize it away completely.

Should as opposed to does.  Want me to try a simple test?


Please.


   There's been a lot
  of work in gcc on that.

  About compile times, I don't care much.

I do. You will too when we have codebase that can be built as fast as
we commit things, so buildbot breaks.
This is common in C++ based projects.


If kvm-unit-tests.git takes to long to compile, I'll be very happy.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 11:54:26AM +0200, Avi Kivity wrote:
 On 11/28/2010 11:50 AM, Michael S. Tsirkin wrote:
   
   Another problem is that there seem to be two memory allocations and a
   copy here, apparently just to simplify error handling.  It might be fine
   for this test but won't scale for when performance matters.
 
   When it matters, we can fix it.  I don't see msr read/write becoming
   a hot path.
 
 It will be very painful to fix it.
 
 Why?

Because the API returns a vector.

  One copy is necessary (it's due to the bad kvm API), but we
 can avoid the others.
 
 In any case the data will be copied by the kernel.
 
 
 
   The compiler should optimize it away completely.
 
 Should as opposed to does.  Want me to try a simple test?
 
 Please.

Just for fun: optimize for size, and compare code sizes.
The C++ code is yours but I have removed all use of STL to make
it more of an even fight.  I checked by object and executable size.
Note that this is shared library build: a C++ executable
will pull in a large C++ library, a C executable won't.
If you are interested in an STL based example let me know.
You can take it from here and make it more real if you like,
or look at the assembler output.

--
[...@tuck ~]$ cat test.c
#include sys/ioctl.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include errno.h

int main(int argc, char **argv)
{
int fd = open(/dev/kvm, O_RDWR);
int r;
if (fd  0)
goto open_err;
r = ioctl(fd, 0, 0);
if (r  0)
goto ioctl_err;
return 0;
ioctl_err:
close(fd);
open_err:
return -1;
}
[...@tuck ~]$ gcc -c -Os test.c 
[...@tuck ~]$ size test.o 
   textdata bss dec hex filename
 97   0   0  97  61 test.o
[...@tuck ~]$ gcc -Os test.c
[...@tuck ~]$ size a.out 
   textdata bss dec hex filename
   1192 260   81460 5b4 a.out
[...@tuck ~]$ wc -l test.c
22 test.c
--
[...@tuck ~]$ cat kvmxx.cpp 
extern C {
#include sys/ioctl.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include errno.h
}

namespace kvm {

class fd {
public:
explicit fd(const char *path, int flags);
~fd() { ::close(_fd); }
long ioctl(unsigned nr, long arg);
private:
int _fd;
};

};

namespace kvm {

static long check_error(long r)
{
if (r == -1) {
throw errno;
}
return r;
}

fd::fd(const char *device_node, int flags)
: _fd(::open(device_node, flags))
{
check_error(_fd);
}


long fd::ioctl(unsigned nr, long arg)
{
return check_error(::ioctl(_fd, nr, arg));
}

}

int main(int ac, char **av)
{
try {
kvm::fd fd(/dev/kvm, O_RDWR);
fd.ioctl(0, 0);
} catch (...) {
return -1;
}
return 0;
}
[...@tuck ~]$ g++ -c -Os kvmxx.cpp 
[...@tuck ~]$ size kvmxx.o 
   textdata bss dec hex filename
529   0   0 529 211 kvmxx.o
[...@tuck ~]$ g++ -Os kvmxx.cpp 
[...@tuck ~]$ size a.out 
   textdata bss dec hex filename
   2254 308  162578 a12 a.out
[...@tuck ~]$ wc kvmxx.cpp 
56 kvmxx.cpp
--


One interesting thing is that the object size grew
faster than linked executable size.
This might mean that the compiler generated some
dead code that the linker then threw out.
It's also interesting that C++ managed to use up
more data/bss storage.


There's been a lot
   of work in gcc on that.
 
   About compile times, I don't care much.
 
 I do. You will too when we have codebase that can be built as fast as
 we commit things, so buildbot breaks.
 This is common in C++ based projects.
 
 If kvm-unit-tests.git takes to long to compile, I'll be very happy.

If the claim is it's so small it does not matter what it's written in
then I guess don't mind. But then - why do we care about
error handling so much? For the test, it's probably ok to just assert
after each ioctl/malloc and be done with it.

 -- 
 error compiling committee.c: too many arguments to function
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Wed, Nov 24, 2010 at 12:52:11PM +0200, Avi Kivity wrote:
 Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
 
 Signed-off-by: Avi Kivity a...@redhat.com
 ---
  api/kvmxx.cc |  168 
 ++
  api/kvmxx.h  |   80 +++
  2 files changed, 248 insertions(+), 0 deletions(-)
  create mode 100644 api/kvmxx.cc
  create mode 100644 api/kvmxx.h
 
 diff --git a/api/kvmxx.cc b/api/kvmxx.cc
 new file mode 100644
 index 000..2f8fc27
 --- /dev/null
 +++ b/api/kvmxx.cc
 @@ -0,0 +1,168 @@
 +#include kvmxx.h
 +#include fcntl.h
 +#include sys/ioctl.h
 +#include sys/mman.h

I just realized this is wrong: I think you should wrap
the headers in extern C. Same for other headers.

 +#include memory
 +#include algorithm
 +
 +namespace kvm {
 +
 +static long check_error(long r)
 +{
 +if (r == -1) {
 + throw errno;
 +}
 +return r;
 +}
 +
 +fd::fd(int fd)
 +: _fd(fd)
 +{
 +}
 +
 +fd::fd(const fd other)
 +: _fd(::dup(other._fd))
 +{
 +check_error(_fd);
 +}
 +
 +fd::fd(std::string device_node, int flags)
 +: _fd(::open(device_node.c_str(), flags))
 +{
 +check_error(_fd);
 +}
 +
 +long fd::ioctl(unsigned nr, long arg)
 +{
 +return check_error(::ioctl(_fd, nr, arg));
 +}
 +
 +vcpu::vcpu(vm vm, int id)
 +: _vm(vm), _fd(vm._fd.ioctl(KVM_CREATE_VCPU, id)), _shared(NULL)
 +{
 +unsigned mmap_size = _vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0);
 +kvm_run *shared = static_castkvm_run*(::mmap(NULL, mmap_size,
 +PROT_READ | PROT_WRITE,
 +MAP_SHARED,
 +_fd.get(), 0));
 +if (shared == MAP_FAILED) {
 + throw errno;
 +}
 +_shared = shared;
 +}
 +
 +vcpu::~vcpu()
 +{
 +unsigned mmap_size = _vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0);
 +munmap(_shared, mmap_size);
 +}
 +
 +void vcpu::run()
 +{
 +_fd.ioctl(KVM_RUN, 0);
 +}
 +
 +kvm_regs vcpu::regs()
 +{
 +kvm_regs regs;
 +_fd.ioctlp(KVM_GET_REGS, regs);
 +return regs;
 +}
 +
 +void vcpu::set_regs(const kvm_regs regs)
 +{
 +_fd.ioctlp(KVM_SET_REGS, const_castkvm_regs*(regs));
 +}
 +
 +kvm_sregs vcpu::sregs()
 +{
 +kvm_sregs sregs;
 +_fd.ioctlp(KVM_GET_SREGS, sregs);
 +return sregs;
 +}
 +
 +void vcpu::set_sregs(const kvm_sregs sregs)
 +{
 +_fd.ioctlp(KVM_SET_SREGS, const_castkvm_sregs*(sregs));
 +}
 +
 +kvm_msrs* vcpu::alloc_msr_list(size_t nmsrs)
 +{
 +size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
 +kvm_msrs* ret = static_castkvm_msrs*(malloc(size));
 +if (!ret) {
 + throw ENOMEM;
 +}
 +return ret;
 +}
 +
 +std::vectorkvm_msr_entry vcpu::msrs(std::vectoruint32_t indices)
 +{
 +std::auto_ptrkvm_msrs msrs(alloc_msr_list(indices.size()));
 +msrs-nmsrs = indices.size();
 +for (unsigned i = 0; i  msrs-nmsrs; ++i) {
 + msrs-entries[i].index = indices[i];
 +}
 +_fd.ioctlp(KVM_GET_MSRS, msrs.get());
 +return std::vectorkvm_msr_entry(msrs-entries,
 +   msrs-entries + msrs-nmsrs);
 +}
 +
 +void vcpu::set_msrs(const std::vectorkvm_msr_entry msrs)
 +{
 +std::auto_ptrkvm_msrs _msrs(alloc_msr_list(msrs.size()));
 +_msrs-nmsrs = msrs.size();
 +std::copy(msrs.begin(), msrs.end(), _msrs-entries);
 +_fd.ioctlp(KVM_SET_MSRS, _msrs.get());
 +}
 +
 +void vcpu::set_debug(uint64_t dr[8], bool enabled, bool singlestep)
 +{
 +kvm_guest_debug gd;
 +
 +gd.control = 0;
 +if (enabled) {
 + gd.control |= KVM_GUESTDBG_ENABLE;
 +}
 +if (singlestep) {
 + gd.control |= KVM_GUESTDBG_SINGLESTEP;
 +}
 +for (int i = 0; i  8; ++i) {
 + gd.arch.debugreg[i] = dr[i];
 +}
 +_fd.ioctlp(KVM_SET_GUEST_DEBUG, gd);
 +}
 +
 +vm::vm(system system)
 +: _system(system), _fd(system._fd.ioctl(KVM_CREATE_VM, 0))
 +{
 +}
 +
 +void vm::set_memory_region(int slot, void *addr, uint64_t gpa, size_t len)
 +{
 +struct kvm_userspace_memory_region umr;
 +
 +umr.slot = slot;
 +umr.flags = 0;
 +umr.guest_phys_addr = gpa;
 +umr.memory_size = len;
 +umr.userspace_addr = reinterpret_castuint64_t(addr);
 +_fd.ioctlp(KVM_SET_USER_MEMORY_REGION, umr);
 +}
 +
 +void vm::set_tss_addr(uint32_t addr)
 +{
 +_fd.ioctl(KVM_SET_TSS_ADDR, addr);
 +}
 +
 +system::system(std::string device_node)
 +: _fd(device_node, O_RDWR)
 +{
 +}
 +
 +bool system::check_extension(int extension)
 +{
 +return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
 +}
 +
 +};
 diff --git a/api/kvmxx.h b/api/kvmxx.h
 new file mode 100644
 index 000..716e400
 --- /dev/null
 +++ b/api/kvmxx.h
 @@ -0,0 +1,80 @@
 +#ifndef KVMXX_H
 +#define KVMXX_H
 +
 +#include string
 +#include signal.h
 +#include unistd.h
 +#include vector
 +#include errno.h
 +#include linux/kvm.h
 +#include stdint.h
 +
 +namespace kvm {
 +
 +class system;
 +class vm;
 +class 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Wed, Nov 24, 2010 at 01:59:14PM +0100, Alexander Graf wrote:
 
 On 24.11.2010, at 11:52, Avi Kivity wrote:
 
  Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
  
  Signed-off-by: Avi Kivity a...@redhat.com
 
 
 FWIW, I still disagree with C++ and believe this code to be hardly readable.

A major issue is existing tools.

Using C++ would prevent us from using sparce for static code checking.
We should be adding more annotations instead of throwing existing ones
out. ctags is also broken with C++ which will make it much harder
for me to browse the codebase. C++ support in gdb has some limitations
if you use overloading, exceptions, templates. The example posted here
uses two of these, so it would be harder to debug.
I also hoped we'll be able to adopt checkpatch at some point for coding
style enforcement, C++ syntax is just too complex for a perl script to
be of any use.

-- 
MST
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Wed, Nov 24, 2010 at 08:41:26AM -0600, Anthony Liguori wrote:
 On 11/24/2010 06:59 AM, Alexander Graf wrote:
 On 24.11.2010, at 11:52, Avi Kivity wrote:
 
 Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
 
 Signed-off-by: Avi Kivitya...@redhat.com
 
 FWIW, I still disagree with C++ and believe this code to be hardly readable.
 
 There's a general prettiness that well written C++ code will have
 over C when there's heavy object modelling.  This can be subjective
 but for me, it's fairly significant.

My guess is this comes from the fact that you are rewriting large pieces
of code from scratch so it suits your personal style perfectly :)

If history teaches us anything, as with most projects in qemu, what we will
end up with is a half done conversion of maybe 30% of the codebase.
The result might be anything: safer, more correct - but it won't be prettier.


 The fact that objects are easily created on the stack and on the
 heap is also pretty significant.

Significant how?

To create an object on the stack, you must have the class definition in
a public header and a public constructor/destructor.
This is exactly the same in C.

  When considering device models, we
 struggle today with device composition.

IMO this has nothing to do with the language and everything to do with
how trying to do the changes in small incremental steps and keep a lot
of configurations working.

 In real hardware, the i8042 (keyboard controller) is actually
 implemented in the PIIX3 which is a chip that is part of the i440fx.
 The i440fx acts as both the memory controller and as the PCI Host
 controller.  So you get something that looks like:
 
 class PIIX3 : public PCIDevice
 {
 private:
 I8042 i8042;
 RTC rtc;
 // ...
 };
 
 class I440FX : public PCIHostController
 {
I440FX(void) {
 this-slots[1].plug(this-piix3); // piix3 is always in slot 1
}
 
 private:
PlugPCIDevice * slots[32]; // slot 0 is the PMC
PIIX3 piix3;
 };


We can have the same thing today.  In fact, getting rid of the UP_CAST
and opaque pointers should be a priority.

 So whereas we have this very complicate machine create function that
 attempts to create and composite all of these devices after the
 fact, when written in C++, partially due to good design, but
 partially due to the fact that the languages forces you to think a
 certain way, you get a tremendous simplification.
 
 A proper C++ device model turns a vast majority of our device
 creation complexity into a single new I440FX.  Then it's just a
 matter of instantiating and plugging the appropriate set of PCI
 devices.
 
 Of course, this can be wrapped in a factory to make it drivable via
 an API or config file.

 Another area that C++ shines is safety.  C++ enables you to inject
 safe versions of things that you really can't do in C.  For
 instance, the PIT has three channels but the mask to select a
 channel is two bits.  There was a kernel exploit that found a way to
 trick selection of a forth channel because of a missing check.
 
 In C++, you can convert:
 
 PITChannel channnels[3];
 
 Into:
 
 ArrayPITChannel, 3 channels;
 
 It behaves in every other way just like a normal array.  The memory
 is stack allocated, the type has a fixed size.   The only difference
 is that you can overload the [] operators and implement bounds
 checking for array accesses.  This means that as long as you use
 Array, array overflows disappear from the code base.  That's a big
 deal.

Except that you get used to the fact that [] is safe,
and then forget to check the value in a dynamically
sized array access. Boom.

Much better to be able to differentiate between
safe and unsafe calls IMO.

 Another area C++ shines is generating metacode.  Consider the
 ugliness around VMState.  The crux of the problem is that it's not
 possible to write type-neutral code in C.  This all gets simplified
 with C++.  Instead of having a bunch of macros like:
 
 VMSTATE_INT8(val0, ...)
 VMSTATE_INT16(val1, ...)
 
 You can just have:
 
 vmstate(val0)
 vmstate(val1)
 
 And use type overloading to implement different behaviors.  Combined
 with template specialization and an Array wrapper, the same thing
 works for arrays too.
 
 Regards,
 
 Anthony Liguori
 
 Regards,
 
 Anthony Liguori

At least with VMSTATE_INT16 I can grep and find the definition.


 Alex
 
 
 --
 To unsubscribe from this list: send the line unsubscribe kvm in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
 
 --
 To unsubscribe from this list: send the line unsubscribe kvm in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Avi Kivity

On 11/28/2010 01:59 PM, Michael S. Tsirkin wrote:



  FWIW, I still disagree with C++ and believe this code to be hardly readable.

A major issue is existing tools.

Using C++ would prevent us from using sparce for static code checking.


C++ static checking is way better than anything sparse offers.

Things like __user are easily done in C++.


We should be adding more annotations instead of throwing existing ones
out. ctags is also broken with C++ which will make it much harder
for me to browse the codebase.


C++ does want a good IDE.


C++ support in gdb has some limitations
if you use overloading, exceptions, templates. The example posted here
uses two of these, so it would be harder to debug.


I haven't seen issues with overloading or exceptions.  Templates are 
indeed harder to debug, simply because names can become very long.



I also hoped we'll be able to adopt checkpatch at some point for coding
style enforcement, C++ syntax is just too complex for a perl script to
be of any use.


Not much of a loss IMO.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Avi Kivity

On 11/28/2010 01:44 PM, Michael S. Tsirkin wrote:

On Sun, Nov 28, 2010 at 11:54:26AM +0200, Avi Kivity wrote:
  On 11/28/2010 11:50 AM, Michael S. Tsirkin wrote:
 
 Another problem is that there seem to be two memory allocations and a
 copy here, apparently just to simplify error handling.  It might be 
fine
 for this test but won't scale for when performance matters.
  
 When it matters, we can fix it.  I don't see msr read/write becoming
 a hot path.
  
  It will be very painful to fix it.

  Why?

Because the API returns a vector.


Returning an object does not involve a copy (return value optimization).


  
 The compiler should optimize it away completely.
  
  Should as opposed to does.  Want me to try a simple test?

  Please.

Just for fun: optimize for size, and compare code sizes.
The C++ code is yours but I have removed all use of STL to make
it more of an even fight.  I checked by object and executable size.
Note that this is shared library build: a C++ executable
will pull in a large C++ library, a C executable won't.
If you are interested in an STL based example let me know.
You can take it from here and make it more real if you like,
or look at the assembler output.

--
[...@tuck ~]$ cat test.c
#includesys/ioctl.h
#includesys/types.h
#includesys/stat.h
#includefcntl.h
#includeunistd.h
#includeerrno.h

int main(int argc, char **argv)
{
 int fd = open(/dev/kvm, O_RDWR);
 int r;
 if (fd  0)
 goto open_err;
 r = ioctl(fd, 0, 0);
 if (r  0)
 goto ioctl_err;
 return 0;
ioctl_err:
 close(fd);
open_err:
 return -1;
}



This code is not reusable.  Everywhere you use an fd, you have to repeat 
this code.



[...@tuck ~]$ gcc -c -Os test.c
[...@tuck ~]$ size test.o
textdata bss dec hex filename
  97   0   0  97  61 test.o
[...@tuck ~]$ gcc -Os test.c
[...@tuck ~]$ size a.out
textdata bss dec hex filename
1192 260   81460 5b4 a.out
[...@tuck ~]$ wc -l test.c
22 test.c
--
[...@tuck ~]$ cat kvmxx.cpp
extern C {
#includesys/ioctl.h
#includesys/types.h
#includesys/stat.h
#includefcntl.h
#includeunistd.h
#includeerrno.h
}

namespace kvm {

 class fd {
 public:
 explicit fd(const char *path, int flags);
 ~fd() { ::close(_fd); }
 long ioctl(unsigned nr, long arg);
 private:
 int _fd;
 };

};

namespace kvm {

static long check_error(long r)
{
 if (r == -1) {
 throw errno;
 }
 return r;
}

fd::fd(const char *device_node, int flags)
 : _fd(::open(device_node, flags))
{
 check_error(_fd);
}


long fd::ioctl(unsigned nr, long arg)
{
 return check_error(::ioctl(_fd, nr, arg));
}

}

int main(int ac, char **av)
{
 try {
 kvm::fd fd(/dev/kvm, O_RDWR);
 fd.ioctl(0, 0);
 } catch (...) {
 return -1;
 }
 return 0;
}


class kvm::fd is reusable, if you embed it in another object you don't 
have to worry about errors any more (as long as the object's methods are 
exception safe).



[...@tuck ~]$ g++ -c -Os kvmxx.cpp
[...@tuck ~]$ size kvmxx.o
textdata bss dec hex filename
 529   0   0 529 211 kvmxx.o
[...@tuck ~]$ g++ -Os kvmxx.cpp
[...@tuck ~]$ size a.out
textdata bss dec hex filename
2254 308  162578 a12 a.out
[...@tuck ~]$ wc kvmxx.cpp
56 kvmxx.cpp
--


One interesting thing is that the object size grew
faster than linked executable size.
This might mean that the compiler generated some
dead code that the linker then threw out.
It's also interesting that C++ managed to use up
more data/bss storage.


C++ will have much larger data and code sizes because it uses DWARF 
tables for unwinding and generates stack unwinding code.  These are all 
out of the hot path.



  There's been a lot
 of work in gcc on that.
  
 About compile times, I don't care much.
  
  I do. You will too when we have codebase that can be built as fast as
  we commit things, so buildbot breaks.
  This is common in C++ based projects.

  If kvm-unit-tests.git takes to long to compile, I'll be very happy.

If the claim is it's so small it does not matter what it's written in
then I guess don't mind. But then - why do we care about
error handling so much? For the test, it's probably ok to just assert
after each ioctl/malloc and be done with it.


Yes, all the correctness is more or less pointless here.  Like I said, 
this is an experiment to see what things look like.  I guess each side 
will it as proving its claims.


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

--
To 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Avi Kivity

On 11/28/2010 01:49 PM, Michael S. Tsirkin wrote:

  +++ b/api/kvmxx.cc
  @@ -0,0 +1,168 @@
  +#include kvmxx.h
  +#includefcntl.h
  +#includesys/ioctl.h
  +#includesys/mman.h

I just realized this is wrong: I think you should wrap
the headers in extern C. Same for other headers.


I think system headers already do this (otherwise it won't link - int 
foo() is different than extern C { int foo(void); })


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 03:02:18PM +0200, Avi Kivity wrote:
 On 11/28/2010 01:59 PM, Michael S. Tsirkin wrote:
 
 
   FWIW, I still disagree with C++ and believe this code to be hardly 
  readable.
 
 A major issue is existing tools.
 
 Using C++ would prevent us from using sparce for static code checking.
 
 C++ static checking is way better than anything sparse offers.

This seems a second system effect at work.

sparce lets you solve C problems that C++ inherited as is.
E.g. if you have a pointer you can always dereference it.

 
 Things like __user are easily done in C++.

Some of what sparce does can be done if you create a separate type for
all address spaces.  This can be done in C too, and the result won't
be like __user at all.

 We should be adding more annotations instead of throwing existing ones
 out. ctags is also broken with C++ which will make it much harder
 for me to browse the codebase.
 
 C++ does want a good IDE.

For some definitions of good :).
Let's start a vi versus emacs flamewar?

 C++ support in gdb has some limitations
 if you use overloading, exceptions, templates. The example posted here
 uses two of these, so it would be harder to debug.
 
 I haven't seen issues with overloading or exceptions.

Build your test with -g, fire up gdb from command line,
try to put a breakpoint in the constructor of
the fd object, maybe you will see what I mean :)

An example of an issue with overloading is that gdb seems unable to resolve
them properly depending on the current scope.  So you see a call to
foo() and want to put a breakpoint there, first problem is just to find
one which namespace it is in. Once you did the best
it can do it prompt you to select one of the overloaded options.
How do you know which one do you want? You don't, so you guess. Sometimes
gdb will guess, because of a complex set of name resolution rules, and
sometimes it will this wrongly.
Which is not what I want to spend mental cycles on when I am debugging a 
problem.

Functions using exceptions can not be called from the gdb prompt
(gdb is not smart enough to catch them).

There are more issues.

  Templates are
 indeed harder to debug, simply because names can become very long.

That's not the only problem. A bigger one is when you type tab to
complete function name and get a list of options to select from for each
of the times a template was instantiated.  Only one of them is relevant
in a given scope. No hint is given which.  Further when you step into
the template, the source does not give you any hint about the types
used.

Some of this is true for macros as well of course. Except people know
macros are bad and so make them thin wrappers around proper functions.

 I also hoped we'll be able to adopt checkpatch at some point for coding
 style enforcement, C++ syntax is just too complex for a perl script to
 be of any use.
 
 Not much of a loss IMO.

This is just an example of how coding style is harder to
specify and enforce. There are just much more ways to do
any given thing. Uniform style is much harder to achieve.

 -- 
 error compiling committee.c: too many arguments to function
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Avi Kivity

On 11/28/2010 03:57 PM, Michael S. Tsirkin wrote:

On Sun, Nov 28, 2010 at 03:02:18PM +0200, Avi Kivity wrote:
  On 11/28/2010 01:59 PM, Michael S. Tsirkin wrote:
  
  
 FWIW, I still disagree with C++ and believe this code to be hardly 
readable.
  
  A major issue is existing tools.
  
  Using C++ would prevent us from using sparce for static code checking.

  C++ static checking is way better than anything sparse offers.

This seems a second system effect at work.

sparce lets you solve C problems that C++ inherited as is.
E.g. if you have a pointer you can always dereference it.


It's the other way round.

For example __user cannot be done in C.  It has to be done as an add-on.

In C++ it's simply:

  template class T
  class user_ptrT
  {
  public:
  explicit user_ptr(unsigned long addr);
  void copy_from(T to); // throws EFAULT
  void copy_to(const T from); // throws EFAULT
  private:
  unsigned long addr;
  };

No need for an additional toolchain.



  Things like __user are easily done in C++.

Some of what sparce does can be done if you create a separate type for
all address spaces.  This can be done in C too, and the result won't
be like __user at all.


That's quite a lot of work.

 Sparse:  T __user *foo;
 C++: user_ptrT foo;
 C : struct T_user_ptr { unsigned long addr } foo; + lots of accessors.


  We should be adding more annotations instead of throwing existing ones
  out. ctags is also broken with C++ which will make it much harder
  for me to browse the codebase.

  C++ does want a good IDE.

For some definitions of good :).
Let's start a vi versus emacs flamewar?


Like we haven't enough...


  C++ support in gdb has some limitations
  if you use overloading, exceptions, templates. The example posted here
  uses two of these, so it would be harder to debug.

  I haven't seen issues with overloading or exceptions.

Build your test with -g, fire up gdb from command line,
try to put a breakpoint in the constructor of
the fd object, maybe you will see what I mean :)


(gdb) break 'kvm::fd::fd'
Breakpoint 3 at 0x8049650: file api/kvmxx.cc, line 25.
Breakpoint 4 at 0x8049628: file api/kvmxx.cc, line 31.
Breakpoint 5 at 0x8049080: file api/kvmxx.cc, line 21


An example of an issue with overloading is that gdb seems unable to resolve
them properly depending on the current scope.  So you see a call to
foo() and want to put a breakpoint there, first problem is just to find
one which namespace it is in. Once you did the best
it can do it prompt you to select one of the overloaded options.
How do you know which one do you want? You don't, so you guess. Sometimes
gdb will guess, because of a complex set of name resolution rules, and
sometimes it will this wrongly.
Which is not what I want to spend mental cycles on when I am debugging a 
problem.

Functions using exceptions can not be called from the gdb prompt
(gdb is not smart enough to catch them).

There are more issues.


That's not restricted to gdb.  C has just three scopes: block (may be 
nested), file static, and global.  C++ has more.  Stating everything 
leads to verbose code and potential conflicts.  Having more scopes 
allows tighter code usually but more head-scratching if something goes 
wrong.


In my experience conflicts are very rare.  But it's true that when they 
happen they can be surprising.



   Templates are
  indeed harder to debug, simply because names can become very long.

That's not the only problem. A bigger one is when you type tab to
complete function name and get a list of options to select from for each
of the times a template was instantiated.  Only one of them is relevant
in a given scope. No hint is given which.  Further when you step into
the template, the source does not give you any hint about the types
used.

Some of this is true for macros as well of course. Except people know
macros are bad and so make them thin wrappers around proper functions.


Or they simply avoid it and duplicate the code.  You can't always wrap 
functions with macros.



  I also hoped we'll be able to adopt checkpatch at some point for coding
  style enforcement, C++ syntax is just too complex for a perl script to
  be of any use.

  Not much of a loss IMO.

This is just an example of how coding style is harder to
specify and enforce. There are just much more ways to do
any given thing. Uniform style is much harder to achieve.


The language does more, so it's more complicated.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 03:14:17PM +0200, Avi Kivity wrote:
 On 11/28/2010 01:44 PM, Michael S. Tsirkin wrote:
 On Sun, Nov 28, 2010 at 11:54:26AM +0200, Avi Kivity wrote:
   On 11/28/2010 11:50 AM, Michael S. Tsirkin wrote:
  
  Another problem is that there seem to be two memory allocations and 
  a
  copy here, apparently just to simplify error handling.  It might be 
  fine
  for this test but won't scale for when performance matters.
   
  When it matters, we can fix it.  I don't see msr read/write becoming
  a hot path.
   
   It will be very painful to fix it.
 
   Why?
 
 Because the API returns a vector.
 
 Returning an object does not involve a copy (return value optimization).

Yes, but assigning the value in the code that uses it will, unless again
you do this in an initializer.

   
  The compiler should optimize it away completely.
   
   Should as opposed to does.  Want me to try a simple test?
 
   Please.
 
 Just for fun: optimize for size, and compare code sizes.
 The C++ code is yours but I have removed all use of STL to make
 it more of an even fight.  I checked by object and executable size.
 Note that this is shared library build: a C++ executable
 will pull in a large C++ library, a C executable won't.
 If you are interested in an STL based example let me know.
 You can take it from here and make it more real if you like,
 or look at the assembler output.
 
 --
 [...@tuck ~]$ cat test.c
 #includesys/ioctl.h
 #includesys/types.h
 #includesys/stat.h
 #includefcntl.h
 #includeunistd.h
 #includeerrno.h
 
 int main(int argc, char **argv)
 {
  int fd = open(/dev/kvm, O_RDWR);
  int r;
  if (fd  0)
  goto open_err;
  r = ioctl(fd, 0, 0);
  if (r  0)
  goto ioctl_err;
  return 0;
 ioctl_err:
  close(fd);
 open_err:
  return -1;
 }
 
 
 This code is not reusable.  Everywhere you use an fd, you have to
 repeat this code.

But that's not a lot of code. And you can abstract it away at a higher
level. For example kvm_init and kvm_cleanup would setup/cleanup
state in a consistent way.

My experience tells me C++ code has much more boilerplate code that you
are forced to repeat over and over.  This is especially true for unix
system programming:  by the time you are done wrapping all of unix you
have created more LOC than you are ever likely to save.


 [...@tuck ~]$ gcc -c -Os test.c
 [...@tuck ~]$ size test.o
 textdata bss dec hex filename
   97   0   0  97  61 test.o
 [...@tuck ~]$ gcc -Os test.c
 [...@tuck ~]$ size a.out
 textdata bss dec hex filename
 1192 260   81460 5b4 a.out
 [...@tuck ~]$ wc -l test.c
 22 test.c
 --
 [...@tuck ~]$ cat kvmxx.cpp
 extern C {
 #includesys/ioctl.h
 #includesys/types.h
 #includesys/stat.h
 #includefcntl.h
 #includeunistd.h
 #includeerrno.h
 }
 
 namespace kvm {
 
  class fd {
  public:
  explicit fd(const char *path, int flags);
  ~fd() { ::close(_fd); }
  long ioctl(unsigned nr, long arg);
  private:
  int _fd;
  };
 
 };
 
 namespace kvm {
 
 static long check_error(long r)
 {
  if (r == -1) {
  throw errno;
  }
  return r;
 }
 
 fd::fd(const char *device_node, int flags)
  : _fd(::open(device_node, flags))
 {
  check_error(_fd);
 }
 
 
 long fd::ioctl(unsigned nr, long arg)
 {
  return check_error(::ioctl(_fd, nr, arg));
 }
 
 }
 
 int main(int ac, char **av)
 {
  try {
  kvm::fd fd(/dev/kvm, O_RDWR);
  fd.ioctl(0, 0);
  } catch (...) {
  return -1;
  }
  return 0;
 }
 
 class kvm::fd is reusable, if you embed it in another object you
 don't have to worry about errors any more (as long as the object's
 methods are exception safe).

To get exception safe code, you have to constantly worry about errors.
And it's easier to spot an unhandled return code than exception-unsafe
code:  gcc actually has  __attribute__((warn_unused_result)) which
might help catch common errors. No such tool to catch
exception-unsafe code AFAIK.


 [...@tuck ~]$ g++ -c -Os kvmxx.cpp
 [...@tuck ~]$ size kvmxx.o
 textdata bss dec hex filename
  529   0   0 529 211 kvmxx.o
 [...@tuck ~]$ g++ -Os kvmxx.cpp
 [...@tuck ~]$ size a.out
 textdata bss dec hex filename
 2254 308  162578 a12 a.out
 [...@tuck ~]$ wc kvmxx.cpp
 56 kvmxx.cpp
 --
 
 
 One interesting thing is that the object size grew
 faster than linked executable size.
 This might mean that the compiler generated some
 dead code that the linker then threw out.
 It's also interesting that C++ 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 03:15:52PM +0200, Avi Kivity wrote:
 On 11/28/2010 01:49 PM, Michael S. Tsirkin wrote:
   +++ b/api/kvmxx.cc
   @@ -0,0 +1,168 @@
   +#include kvmxx.h
   +#includefcntl.h
   +#includesys/ioctl.h
   +#includesys/mman.h
 
 I just realized this is wrong: I think you should wrap
 the headers in extern C. Same for other headers.
 
 I think system headers already do this
 (otherwise it won't link -
 int foo() is different than extern C { int foo(void); })

okay, but they aren't there for linux/kvm.h, are they?

 -- 
 error compiling committee.c: too many arguments to function
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 04:34:39PM +0200, Avi Kivity wrote:
 On 11/28/2010 03:57 PM, Michael S. Tsirkin wrote:
 On Sun, Nov 28, 2010 at 03:02:18PM +0200, Avi Kivity wrote:
   On 11/28/2010 01:59 PM, Michael S. Tsirkin wrote:
   
   
  FWIW, I still disagree with C++ and believe this code to be hardly 
  readable.
   
   A major issue is existing tools.
   
   Using C++ would prevent us from using sparce for static code checking.
 
   C++ static checking is way better than anything sparse offers.
 
 This seems a second system effect at work.
 
 sparce lets you solve C problems that C++ inherited as is.
 E.g. if you have a pointer you can always dereference it.
 
 It's the other way round.
 
 For example __user cannot be done in C.  It has to be done as an add-on.
 
 In C++ it's simply:
 
   template class T
   class user_ptrT
   {
   public:
   explicit user_ptr(unsigned long addr);
   void copy_from(T to); // throws EFAULT
   void copy_to(const T from); // throws EFAULT
   private:
   unsigned long addr;
   };

This does not allow simple uses such as arithmetic, void, builtin
types, sizeof, arrays, NULL comparizon, inheritance, cast,
memory management.

Examples to ponder: what is the appropriate value of T for void *?
What if you want a shared/auto ptr to manage this memory?

Some of these might be fixable, with a lot of code.
Boost might haver some solutions, I haven't looked.

Meanwhile sparse is already there.

 No need for an additional toolchain.

It's a feature :) This way  you are not forced to rewrite all code each
time you realize you need an extra check, and checks can be added
gradually without breaking build.

 
   Things like __user are easily done in C++.
 
 Some of what sparce does can be done if you create a separate type for
 all address spaces.  This can be done in C too, and the result won't
 be like __user at all.
 
 That's quite a lot of work.
 
  Sparse:  T __user *foo;
  C++: user_ptrT foo;

Sparse has some advantages: it makes the contract obvious so you clearly
see it's a pointer and know -, [], + will work, * and  will not.

  C : struct T_user_ptr { unsigned long addr } foo; + lots of accessors.

Some kind of macro can be closer to user_ptr above.

   We should be adding more annotations instead of throwing existing ones
   out. ctags is also broken with C++ which will make it much harder
   for me to browse the codebase.
 
   C++ does want a good IDE.
 
 For some definitions of good :).
 Let's start a vi versus emacs flamewar?
 
 Like we haven't enough...
 
   C++ support in gdb has some limitations
   if you use overloading, exceptions, templates. The example posted here
   uses two of these, so it would be harder to debug.
 
   I haven't seen issues with overloading or exceptions.
 
 Build your test with -g, fire up gdb from command line,
 try to put a breakpoint in the constructor of
 the fd object, maybe you will see what I mean :)
 
 (gdb) break 'kvm::fd::fd'
 Breakpoint 3 at 0x8049650: file api/kvmxx.cc, line 25.
 Breakpoint 4 at 0x8049628: file api/kvmxx.cc, line 31.
 Breakpoint 5 at 0x8049080: file api/kvmxx.cc, line 21

But it's hard to figure out that you need the kvm namespace.  Your code
only has one namespace, but with multiple namespaces, you don't even
know in which namespace to look up the fd.  With templates you might not
even know the fd class.

 An example of an issue with overloading is that gdb seems unable to resolve
 them properly depending on the current scope.  So you see a call to
 foo() and want to put a breakpoint there, first problem is just to find
 one which namespace it is in. Once you did the best
 it can do it prompt you to select one of the overloaded options.
 How do you know which one do you want? You don't, so you guess. Sometimes
 gdb will guess, because of a complex set of name resolution rules, and
 sometimes it will this wrongly.
 Which is not what I want to spend mental cycles on when I am debugging a 
 problem.
 
 Functions using exceptions can not be called from the gdb prompt
 (gdb is not smart enough to catch them).
 
 There are more issues.
 
 That's not restricted to gdb.  C has just three scopes: block (may
 be nested), file static, and global.  C++ has more.  Stating
 everything leads to verbose code and potential conflicts.  Having
 more scopes allows tighter code usually

 but more head-scratching if
 something goes wrong.

 In my experience conflicts are very rare.  But it's true that when
 they happen they can be surprising.

There is some difference: when you write code, conflicts are rare
because you let the compiler guess the right call from the scope.  When
you read code or debug, conflicts are everywhere.  They are rarely
surprising, they are always time consuming to resolve.

Templates are
   indeed harder to debug, simply because names can become very long.
 
 That's not the only problem. A bigger one is when you type tab to
 complete function name and get a list of options to select from for 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Anthony Liguori

On 11/28/2010 06:27 AM, Michael S. Tsirkin wrote:

On Wed, Nov 24, 2010 at 08:41:26AM -0600, Anthony Liguori wrote:
   

On 11/24/2010 06:59 AM, Alexander Graf wrote:
 

On 24.11.2010, at 11:52, Avi Kivity wrote:

   

Introduce exception-safe objects for calling system, vm, and vcpu ioctls.

Signed-off-by: Avi Kivitya...@redhat.com
 

FWIW, I still disagree with C++ and believe this code to be hardly readable.
   

There's a general prettiness that well written C++ code will have
over C when there's heavy object modelling.  This can be subjective
but for me, it's fairly significant.
 

My guess is this comes from the fact that you are rewriting large pieces
of code from scratch so it suits your personal style perfectly :)
   


That's probably a good observations.


If history teaches us anything, as with most projects in qemu, what we will
end up with is a half done conversion of maybe 30% of the codebase.
The result might be anything: safer, more correct - but it won't be prettier.
   


This is where things need to be different.  I'm not at all interested in 
introducing C++ to QEMU because of exactly what you describe above.


I think the only viable approach is one where we have a segregated code 
base that is correct with an incremental movement of code from the old 
code base to the new way of doing things.


I've always thought that the device model should be a library and I 
think that's the way to structure it.  Have a libqemuhw and only move 
devices into it as they are converted properly.



The fact that objects are easily created on the stack and on the
heap is also pretty significant.
 

Significant how?

To create an object on the stack, you must have the class definition in
a public header and a public constructor/destructor.
This is exactly the same in C.
   


It's really more of a design statement than a statement about C++ vs. C.

In qdev today, we mix object initialization with a user-exposed 
factory.  This means that you cannot do something simple like:


struct i440fx {
   struct piix3 piix;
};

void i440fx_init(struct i440fx_init *obj) {
piix3_init(obj-piix);
}

But rather need to use ugly factory functions with all sorts of 
DO_UPCAST.  This is really unfriendly especially for writing test cases.


But this isn't C vs. C++, this is just about device model design.  I 
think C++ makes it quite a bit more obvious though how to design 
correctly though.



In real hardware, the i8042 (keyboard controller) is actually
implemented in the PIIX3 which is a chip that is part of the i440fx.
The i440fx acts as both the memory controller and as the PCI Host
controller.  So you get something that looks like:

class PIIX3 : public PCIDevice
{
private:
 I8042 i8042;
 RTC rtc;
 // ...
};

class I440FX : public PCIHostController
{
I440FX(void) {
 this-slots[1].plug(this-piix3); // piix3 is always in slot 1
}

private:
PlugPCIDevice *  slots[32]; // slot 0 is the PMC
PIIX3 piix3;
};
 


We can have the same thing today.  In fact, getting rid of the UP_CAST
and opaque pointers should be a priority.
   


I find that you end up writing a lot more boiler plate code trying to do 
this properly in C.   I think gobject is probably the best example of 
this.  If you've ever written a GTK widget from scratch in C and then 
written one in gtkmm, the difference is night and day.



So whereas we have this very complicate machine create function that
attempts to create and composite all of these devices after the
fact, when written in C++, partially due to good design, but
partially due to the fact that the languages forces you to think a
certain way, you get a tremendous simplification.

A proper C++ device model turns a vast majority of our device
creation complexity into a single new I440FX.  Then it's just a
matter of instantiating and plugging the appropriate set of PCI
devices.

Of course, this can be wrapped in a factory to make it drivable via
an API or config file.

Another area that C++ shines is safety.  C++ enables you to inject
safe versions of things that you really can't do in C.  For
instance, the PIT has three channels but the mask to select a
channel is two bits.  There was a kernel exploit that found a way to
trick selection of a forth channel because of a missing check.

In C++, you can convert:

PITChannel channnels[3];

Into:

ArrayPITChannel, 3  channels;

It behaves in every other way just like a normal array.  The memory
is stack allocated, the type has a fixed size.   The only difference
is that you can overload the [] operators and implement bounds
checking for array accesses.  This means that as long as you use
Array, array overflows disappear from the code base.  That's a big
deal.
 

Except that you get used to the fact that [] is safe,
and then forget to check the value in a dynamically
sized array access. Boom.
   


I don't think the fact that you get deterministic vs. non-deterministic 
behavior 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Anthony Liguori

On 11/28/2010 08:40 AM, Michael S. Tsirkin wrote:



This code is not reusable.  Everywhere you use an fd, you have to
repeat this code.
 

But that's not a lot of code. And you can abstract it away at a higher
level. For example kvm_init and kvm_cleanup would setup/cleanup
state in a consistent way.

My experience tells me C++ code has much more boilerplate code that you
are forced to repeat over and over.  This is especially true for unix
system programming:  by the time you are done wrapping all of unix you
have created more LOC than you are ever likely to save.
   


I've said it earlier but I think it's worth repeating--trying to wrap 
libc in pretty C++ interfaces is a waste of time.


In an ideal world, the device model doesn't interact at all with libc.  
Most of the code simply manipulates internal state and some code will 
provide a bridge to well defined internal interfaces.


The nice thing about C++ though is that you can still write C code and 
compile it with g++ (or even gcc if you care).  So you can use objects 
where they make sense and not use them where they don't.



class kvm::fd is reusable, if you embed it in another object you
don't have to worry about errors any more (as long as the object's
methods are exception safe).
 

To get exception safe code, you have to constantly worry about errors.
And it's easier to spot an unhandled return code than exception-unsafe
code:  gcc actually has  __attribute__((warn_unused_result)) which
might help catch common errors. No such tool to catch
exception-unsafe code AFAIK.
   


I tend to agree that writing exception safe code and using exceptions 
for expected errors is a bad idea.  I think exceptions should be used 
primarily for unexpected errors.


Regards,

Anthony Liguori




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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Michael S. Tsirkin
On Sun, Nov 28, 2010 at 04:04:34PM -0600, Anthony Liguori wrote:
 To create an object on the stack, you must have the class definition in
 a public header and a public constructor/destructor.
 This is exactly the same in C.
 
 It's really more of a design statement than a statement about C++ vs. C.
 
 In qdev today, we mix object initialization with a user-exposed
 factory.  This means that you cannot do something simple like:
 
 struct i440fx {
struct piix3 piix;
 };
 
 void i440fx_init(struct i440fx_init *obj) {
 piix3_init(obj-piix);
 }
 
 But rather need to use ugly factory functions with all sorts of
 DO_UPCAST.  This is really unfriendly especially for writing test
 cases.

Yes, I agree. Just moving memory allocation out of there
will fix most of the ugliness.

-- 
MST
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-28 Thread Anthony Liguori

On 11/28/2010 04:28 PM, Michael S. Tsirkin wrote:



But rather need to use ugly factory functions with all sorts of
DO_UPCAST.  This is really unfriendly especially for writing test
cases.
 

Yes, I agree. Just moving memory allocation out of there
will fix most of the ugliness.
   


So here's a short list of things I've been working on that I don't 
believe have nice implementations in C.


1) Factories with string based parameters with natural constructor 
arguments.


I want to have:

I8254(DriftMode mode)

or:

void i8254_init(I8524 *self, DriftMode mode)

And either be able to directly instantiate the object or create it with 
the following command:


dev = create(i8524, mode, catchup, NULL);

In C++, I can do:

static Device *i8524_create(DriftMode mode)
{
 return new I8524(mode);
}

//...
add_factory(i8524, i8524_create, mode);

This works because we can use templates to figure out the argument type 
to create and automatically set things up for the mode parameter.  
Because of overloading, we can have variable arguments so this works for 
1, 2, or 10 arguments.  In C, at best you would have to do something like:


static Device *i8524_create(ParameterList *list)
{
DriftMode mode;
I8524 *i8524;
if (param_list_has(list, mode)) {
 // should we check the type?
 mode = (DriftMode)param_get_as_int(list, mode); // or do we 
teach param about DriftMode?

} else {
 // should we error?
}
i8524 = malloc(sizeof(*i8524));
if (i8524) {
return i8524-dev; // I have to know how to get to this
}
return NULL;
}

struct factory_info i8524_info = {
.args = (FactoryArgument[]){
 { mode, DriftMode },
 { }
}
};

add_factory(i8524, i8524_create, i8524_info);

And there's so many bad decisions I can make in the process.  Do I have 
a mechanism to register new types external to the system and make all 
types convertable?


My C++ example uses a template specialization to convert from types to 
strings.  It's simple and extensible.  There's no list that needs to be 
kept at run time because the compiler does all of the book keeping.


I can let the compiler figure out how to go from I8524 to Device * 
because it knows how to.


The same is true for generic get/set properties.  In C++, I can do 
something like:


class I8524 : public PropertyAccessible {
public:
enum LinkStatus {
LINK_UP,
LINK_DOWN,
};
LinkStatus get_link_status(void);
void set_link_status(void);
};

template 
I8254::LinkStatus type_from_str(std::string value)
{
 if (value == Down) {
  return LINK_DOWN;
 } else if (value == Up) {
  return LINK_UP;
 }
 throw new InvalidTypeConversionException(LinkStatus, value);
}

template 
std::string type_to_str(I8254::LinkStatus status)
{
if (status == LINK_DOWN) {
return Down;
} else {
return Up;
}
}

I8524::I8524(void) {
this-add_property(link_status, I8524::get_link_status, 
I8524::set_link_status);

}

And now I can do:

Device *dev = new I8524();

cout  dev-get(link_status)  endl;

And it will print: Down

Simple and elegant.  The main class has strong error checking, adding 
the property is absolutely painless, supporting new types is absolutely 
painless.  The actual class implementation never sees a string--ever.  
There is only one place string-type conversion happens.


I'm not going to show the C version because I know what it involves and 
I suspect you do too.  It totally sucks and I don't want to spend my 
Sunday evening writing it.  And that's really my motivation for using 
C++.  I get tired of doing the work that the compiler should be doing 
for me.  I want to spend my time doing interesting things like writing 
device model test cases instead of writing code to work around the fact 
that the C type system is about as powerful as a Vespa.


Regars,

Anthony Liguori
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-26 Thread Michael S. Tsirkin
On Wed, Nov 24, 2010 at 12:52:11PM +0200, Avi Kivity wrote:
 Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
 
 Signed-off-by: Avi Kivity a...@redhat.com

ioctlp calls below ignore possible errors.
Somre more comments below.

 ---
  api/kvmxx.cc |  168 
 ++
  api/kvmxx.h  |   80 +++
  2 files changed, 248 insertions(+), 0 deletions(-)
  create mode 100644 api/kvmxx.cc
  create mode 100644 api/kvmxx.h
 
 diff --git a/api/kvmxx.cc b/api/kvmxx.cc
 new file mode 100644
 index 000..2f8fc27
 --- /dev/null
 +++ b/api/kvmxx.cc
 @@ -0,0 +1,168 @@
 +#include kvmxx.h
 +#include fcntl.h
 +#include sys/ioctl.h
 +#include sys/mman.h
 +#include memory
 +#include algorithm
 +
 +namespace kvm {
 +
 +static long check_error(long r)
 +{
 +if (r == -1) {
 + throw errno;
 +}
 +return r;
 +}
 +
 +fd::fd(int fd)
 +: _fd(fd)
 +{
 +}
 +
 +fd::fd(const fd other)
 +: _fd(::dup(other._fd))
 +{
 +check_error(_fd);
 +}
 +
 +fd::fd(std::string device_node, int flags)
 +: _fd(::open(device_node.c_str(), flags))
 +{
 +check_error(_fd);
 +}
 +
 +long fd::ioctl(unsigned nr, long arg)
 +{
 +return check_error(::ioctl(_fd, nr, arg));
 +}
 +
 +vcpu::vcpu(vm vm, int id)
 +: _vm(vm), _fd(vm._fd.ioctl(KVM_CREATE_VCPU, id)), _shared(NULL)
 +{
 +unsigned mmap_size = _vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0);
 +kvm_run *shared = static_castkvm_run*(::mmap(NULL, mmap_size,
 +PROT_READ | PROT_WRITE,
 +MAP_SHARED,
 +_fd.get(), 0));
 +if (shared == MAP_FAILED) {
 + throw errno;
 +}
 +_shared = shared;
 +}
 +
 +vcpu::~vcpu()
 +{
 +unsigned mmap_size = _vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0);

This might throw an exception on destructor path, if this happens
because an exception was thrown terminate is called.

 +munmap(_shared, mmap_size);
 +}
 +
 +void vcpu::run()
 +{
 +_fd.ioctl(KVM_RUN, 0);
 +}
 +
 +kvm_regs vcpu::regs()
 +{
 +kvm_regs regs;
 +_fd.ioctlp(KVM_GET_REGS, regs);
 +return regs;
 +}
 +
 +void vcpu::set_regs(const kvm_regs regs)
 +{
 +_fd.ioctlp(KVM_SET_REGS, const_castkvm_regs*(regs));
 +}
 +
 +kvm_sregs vcpu::sregs()
 +{
 +kvm_sregs sregs;
 +_fd.ioctlp(KVM_GET_SREGS, sregs);
 +return sregs;
 +}
 +
 +void vcpu::set_sregs(const kvm_sregs sregs)
 +{
 +_fd.ioctlp(KVM_SET_SREGS, const_castkvm_sregs*(sregs));
 +}
 +
 +kvm_msrs* vcpu::alloc_msr_list(size_t nmsrs)
 +{
 +size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
 +kvm_msrs* ret = static_castkvm_msrs*(malloc(size));
 +if (!ret) {
 + throw ENOMEM;
 +}
 +return ret;
 +}
 +
 +std::vectorkvm_msr_entry vcpu::msrs(std::vectoruint32_t indices)
 +{
 +std::auto_ptrkvm_msrs msrs(alloc_msr_list(indices.size()));

This looks wrong. auto_ptr frees memory with delete,
alloc_msr_list allocates it with malloc.

 +msrs-nmsrs = indices.size();
 +for (unsigned i = 0; i  msrs-nmsrs; ++i) {
 + msrs-entries[i].index = indices[i];
 +}
 +_fd.ioctlp(KVM_GET_MSRS, msrs.get());
 +return std::vectorkvm_msr_entry(msrs-entries,
 +   msrs-entries + msrs-nmsrs);
 +}
 +
 +void vcpu::set_msrs(const std::vectorkvm_msr_entry msrs)
 +{
 +std::auto_ptrkvm_msrs _msrs(alloc_msr_list(msrs.size()));

As above.

 +_msrs-nmsrs = msrs.size();
 +std::copy(msrs.begin(), msrs.end(), _msrs-entries);
 +_fd.ioctlp(KVM_SET_MSRS, _msrs.get());
 +}
 +
 +void vcpu::set_debug(uint64_t dr[8], bool enabled, bool singlestep)
 +{
 +kvm_guest_debug gd;
 +
 +gd.control = 0;
 +if (enabled) {
 + gd.control |= KVM_GUESTDBG_ENABLE;
 +}
 +if (singlestep) {
 + gd.control |= KVM_GUESTDBG_SINGLESTEP;
 +}
 +for (int i = 0; i  8; ++i) {
 + gd.arch.debugreg[i] = dr[i];
 +}
 +_fd.ioctlp(KVM_SET_GUEST_DEBUG, gd);
 +}
 +
 +vm::vm(system system)
 +: _system(system), _fd(system._fd.ioctl(KVM_CREATE_VM, 0))
 +{
 +}
 +
 +void vm::set_memory_region(int slot, void *addr, uint64_t gpa, size_t len)
 +{
 +struct kvm_userspace_memory_region umr;
 +
 +umr.slot = slot;
 +umr.flags = 0;
 +umr.guest_phys_addr = gpa;
 +umr.memory_size = len;
 +umr.userspace_addr = reinterpret_castuint64_t(addr);
 +_fd.ioctlp(KVM_SET_USER_MEMORY_REGION, umr);
 +}
 +
 +void vm::set_tss_addr(uint32_t addr)
 +{
 +_fd.ioctl(KVM_SET_TSS_ADDR, addr);
 +}
 +
 +system::system(std::string device_node)
 +: _fd(device_node, O_RDWR)
 +{
 +}
 +
 +bool system::check_extension(int extension)
 +{
 +return _fd.ioctl(KVM_CHECK_EXTENSION, extension);
 +}
 +
 +};
 diff --git a/api/kvmxx.h b/api/kvmxx.h
 new file mode 100644
 index 000..716e400
 --- /dev/null
 +++ b/api/kvmxx.h
 @@ -0,0 +1,80 @@
 +#ifndef KVMXX_H
 +#define KVMXX_H
 +
 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-25 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 12:53:00PM -0600, Anthony Liguori wrote:
 On 11/24/2010 12:34 PM, Gleb Natapov wrote:
 Right, and real HW does composition in the PIIX3 device. So let's
 not regret making everything an ISA device later.
 
 You design by packaging not functionality?
 No, if you want the ability to remove devices from the PIIX3, fine,
 but don't call them ISA devices just for the sake of it.
 PIIX3 may be totally implemented in FPGA code. I do not care. This is
 implementation detail. What important is that it provide the same
 functionality as ISA devices in the first IBM PC. That is why they are
 ISA devices and should be modeled as such. Otherwise you will have to
 redesign everything when you'll want to move to another chipset
 emulation that uses new and improved SuperIO-2XT technology inside.
 
 The ISA slots (technically XT) were basically daughter board
 connectors.  They routed pins from a bunch of devices on the
 motherboard to external daughterboards.
 
 This included the *unused* IRQ pins, the left over DMA channels,
 etc.  Everything else was hard wired.
 
 The XT connector only exposes pins 3, 4, 5, 6, and 7.  The ISA
 connector then added IRQs 10, 11, 12, 14, and 15.
 
 So if a device uses IRQ 0, 1, 2, 8, 9, or 13, it's by definition not
 an ISA device.  It was hard wired on the motherboard.
 
I don't understand why do you claim that device that is hard wired on
the motherboard is not ISA device. We have many PCI devices internally
in modern chipsets. They are as PCI devices as add on PCI cards.
 
--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-25 Thread Avi Kivity

On 11/24/2010 04:29 PM, Avi Kivity wrote:

+kvm_msrs* vcpu::alloc_msr_list(size_t nmsrs)
+{
+size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
+kvm_msrs* ret = static_castkvm_msrs*(malloc(size));
+if (!ret) {
+throw ENOMEM;
+}
+return ret;
+}


malloc?

Mixing C and C++ allocations is nasty stuff.  Would be nicer to new 
an object and return it such that delete can be used consistently.


5 years of C.


It has to be a malloc() in fact.  We're allocating a variable size 
object that is not an array.  You're right that we can't give it to an 
auto_ptr though, since that uses delete.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Alexander Graf

On 24.11.2010, at 11:52, Avi Kivity wrote:

 Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
 
 Signed-off-by: Avi Kivity a...@redhat.com


FWIW, I still disagree with C++ and believe this code to be hardly readable.


Alex


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 01:59:14PM +0100, Alexander Graf wrote:
 
 On 24.11.2010, at 11:52, Avi Kivity wrote:
 
  Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
  
  Signed-off-by: Avi Kivity a...@redhat.com
 
 
 FWIW, I still disagree with C++ and believe this code to be hardly readable.
 
 
C++ is so powerful and so easy to write correct code in that real C++
programmer never reads the code twice.
 
--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 04:52 AM, Avi Kivity wrote:

Introduce exception-safe objects for calling system, vm, and vcpu ioctls.

Signed-off-by: Avi Kivitya...@redhat.com
---
  api/kvmxx.cc |  168 ++
  api/kvmxx.h  |   80 +++
  2 files changed, 248 insertions(+), 0 deletions(-)
  create mode 100644 api/kvmxx.cc
  create mode 100644 api/kvmxx.h

diff --git a/api/kvmxx.cc b/api/kvmxx.cc
new file mode 100644
index 000..2f8fc27
--- /dev/null
+++ b/api/kvmxx.cc
@@ -0,0 +1,168 @@
+#include kvmxx.h
+#includefcntl.h
+#includesys/ioctl.h
+#includesys/mman.h
+#includememory
+#includealgorithm
+
+namespace kvm {
+
+static long check_error(long r)
+{
+if (r == -1) {
+   throw errno;
+}
+return r;
+}
   


It's generally nicer for exceptions to be objects and to inherit from 
std::exception.  Otherwise, you can run into nasty issues when catching 
the wrong type.



+fd::fd(int fd)
+: _fd(fd)
+{
+}
   


There's no need to prefix with '_'.  Every compiler has been able to do 
the right thing with : fd(fd) for a long time.



+
+fd::fd(const fd  other)
+: _fd(::dup(other._fd))
+{
+check_error(_fd);
+}
+
+fd::fd(std::string device_node, int flags)
+: _fd(::open(device_node.c_str(), flags))
+{
+check_error(_fd);
+}
+
+long fd::ioctl(unsigned nr, long arg)
+{
+return check_error(::ioctl(_fd, nr, arg));
+}
+
+vcpu::vcpu(vm  vm, int id)
+: _vm(vm), _fd(vm._fd.ioctl(KVM_CREATE_VCPU, id)), _shared(NULL)
+{
+unsigned mmap_size = _vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0);
+kvm_run *shared = static_castkvm_run*(::mmap(NULL, mmap_size,
+  PROT_READ | PROT_WRITE,
+  MAP_SHARED,
+  _fd.get(), 0));
+if (shared == MAP_FAILED) {
+   throw errno;
+}
+_shared = shared;
+}
+
+vcpu::~vcpu()
+{
+unsigned mmap_size = _vm._system._fd.ioctl(KVM_GET_VCPU_MMAP_SIZE, 0);
+munmap(_shared, mmap_size);
+}
+
+void vcpu::run()
+{
+_fd.ioctl(KVM_RUN, 0);
+}
+
+kvm_regs vcpu::regs()
+{
+kvm_regs regs;
+_fd.ioctlp(KVM_GET_REGS,regs);
+return regs;
+}
+
+void vcpu::set_regs(const kvm_regs  regs)
+{
+_fd.ioctlp(KVM_SET_REGS, const_castkvm_regs*(regs));
+}
+
+kvm_sregs vcpu::sregs()
+{
+kvm_sregs sregs;
+_fd.ioctlp(KVM_GET_SREGS,sregs);
+return sregs;
+}
   


I think you're missing an opportunity by just returning the structures 
in their raw form as opposed to wrapping them in an object.



+
+void vcpu::set_sregs(const kvm_sregs  sregs)
+{
+_fd.ioctlp(KVM_SET_SREGS, const_castkvm_sregs*(sregs));
+}
+
+kvm_msrs* vcpu::alloc_msr_list(size_t nmsrs)
+{
+size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
+kvm_msrs* ret = static_castkvm_msrs*(malloc(size));
+if (!ret) {
+   throw ENOMEM;
+}
+return ret;
+}
   


malloc?

Mixing C and C++ allocations is nasty stuff.  Would be nicer to new an 
object and return it such that delete can be used consistently.



+
+std::vectorkvm_msr_entry  vcpu::msrs(std::vectoruint32_t  indices)
+{
+std::auto_ptrkvm_msrs  msrs(alloc_msr_list(indices.size()));
+msrs-nmsrs = indices.size();
+for (unsigned i = 0; i  msrs-nmsrs; ++i) {
+   msrs-entries[i].index = indices[i];
+}
+_fd.ioctlp(KVM_GET_MSRS, msrs.get());
+return std::vectorkvm_msr_entry(msrs-entries,
+ msrs-entries + msrs-nmsrs);
+}
   


auto_ptr has pretty awful semantics.  tr1::shared_ptr is now available.


+
+void vcpu::set_msrs(const std::vectorkvm_msr_entry  msrs)
+{
+std::auto_ptrkvm_msrs  _msrs(alloc_msr_list(msrs.size()));
+_msrs-nmsrs = msrs.size();
+std::copy(msrs.begin(), msrs.end(), _msrs-entries);
+_fd.ioctlp(KVM_SET_MSRS, _msrs.get());
+}
+
+void vcpu::set_debug(uint64_t dr[8], bool enabled, bool singlestep)
+{
+kvm_guest_debug gd;
+
+gd.control = 0;
+if (enabled) {
+   gd.control |= KVM_GUESTDBG_ENABLE;
+}
+if (singlestep) {
+   gd.control |= KVM_GUESTDBG_SINGLESTEP;
+}
+for (int i = 0; i  8; ++i) {
+   gd.arch.debugreg[i] = dr[i];
+}
+_fd.ioctlp(KVM_SET_GUEST_DEBUG,gd);
+}
+
+vm::vm(system  system)
+: _system(system), _fd(system._fd.ioctl(KVM_CREATE_VM, 0))
+{
+}
+
+void vm::set_memory_region(int slot, void *addr, uint64_t gpa, size_t len)
+{
+struct kvm_userspace_memory_region umr;
+
+umr.slot = slot;
+umr.flags = 0;
+umr.guest_phys_addr = gpa;
+umr.memory_size = len;
+umr.userspace_addr = reinterpret_castuint64_t(addr);
+_fd.ioctlp(KVM_SET_USER_MEMORY_REGION,umr);
+}
+
+void vm::set_tss_addr(uint32_t addr)
+{
+_fd.ioctl(KVM_SET_TSS_ADDR, addr);
+}
+
+system::system(std::string device_node)
+: _fd(device_node, O_RDWR)
+{
+}
+
+bool system::check_extension(int extension)
+{
+return _fd.ioctl(KVM_CHECK_EXTENSION, 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 06:59 AM, Alexander Graf wrote:

On 24.11.2010, at 11:52, Avi Kivity wrote:

   

Introduce exception-safe objects for calling system, vm, and vcpu ioctls.

Signed-off-by: Avi Kivitya...@redhat.com
 


FWIW, I still disagree with C++ and believe this code to be hardly readable.
   


Take a look at http://repo.or.cz/w/qemupp.git

Start with test/test-mc146818a.cpp

This test infrastructure is arguably a bad place to start because it 
doesn't benefit really at all from C++.  The object hierarchy is 
extremely simple and most of the time you're interfacing with legacy C 
interfaces so a lot of effort is spent bridging those interfaces.


OTOH, the device models interact very little with the external world and 
the object model is complex is subtle ways.  I think C++ is a much 
better fit there.


In the above repo, I've converted the PIT, RTC, keyboard controller, and 
have started working on the i440fx.  The i440fx is a lot of work but 
it's also one of the more interesting devices to try and model correctly.


For all devices, there are very intensive unit tests that use fuzzing.  
I hope to have something postable for serious consideration by the end 
of the year.


BTW, given the ability to test programmatically, I ended up rewriting a 
good bit of the PIT and RTC.  The way that the unit conversion is 
handled right now in QEMU is a train wreck.  The new version is much 
more accurate and as a consequence, the interrupt catch up logic is much 
more precise.  There are also three different catch up algorithms that 
are selectable at run time.


This is all tested with a time simulation that can simulate random 
amounts of drift over random periods of time.


Regards,

Anthony Liguori



Alex


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 08:18 AM, Anthony Liguori wrote:

On 11/24/2010 06:59 AM, Alexander Graf wrote:

On 24.11.2010, at 11:52, Avi Kivity wrote:

Introduce exception-safe objects for calling system, vm, and vcpu 
ioctls.


Signed-off-by: Avi Kivitya...@redhat.com


FWIW, I still disagree with C++ and believe this code to be hardly 
readable.


Take a look at http://repo.or.cz/w/qemupp.git


repo.or.cz seems to be down so:

http://git.qemu.org/qemupp.git/

Regards,

Anthony Liguori



Start with test/test-mc146818a.cpp

This test infrastructure is arguably a bad place to start because it 
doesn't benefit really at all from C++.  The object hierarchy is 
extremely simple and most of the time you're interfacing with legacy C 
interfaces so a lot of effort is spent bridging those interfaces.


OTOH, the device models interact very little with the external world 
and the object model is complex is subtle ways.  I think C++ is a much 
better fit there.


In the above repo, I've converted the PIT, RTC, keyboard controller, 
and have started working on the i440fx.  The i440fx is a lot of work 
but it's also one of the more interesting devices to try and model 
correctly.


For all devices, there are very intensive unit tests that use 
fuzzing.  I hope to have something postable for serious consideration 
by the end of the year.


BTW, given the ability to test programmatically, I ended up rewriting 
a good bit of the PIT and RTC.  The way that the unit conversion is 
handled right now in QEMU is a train wreck.  The new version is much 
more accurate and as a consequence, the interrupt catch up logic is 
much more precise.  There are also three different catch up algorithms 
that are selectable at run time.


This is all tested with a time simulation that can simulate random 
amounts of drift over random periods of time.


Regards,

Anthony Liguori



Alex


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html




--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 04:10 PM, Anthony Liguori wrote:

On 11/24/2010 04:52 AM, Avi Kivity wrote:
Introduce exception-safe objects for calling system, vm, and vcpu 
ioctls.


+
+namespace kvm {
+
+static long check_error(long r)
+{
+if (r == -1) {
+throw errno;
+}
+return r;
+}


It's generally nicer for exceptions to be objects and to inherit from 
std::exception.  Otherwise, you can run into nasty issues when 
catching the wrong type.



Yeah, I'm lazy.




+fd::fd(int fd)
+: _fd(fd)
+{
+}


There's no need to prefix with '_'.  Every compiler has been able to 
do the right thing with : fd(fd) for a long time.


Ok.




+
+kvm_sregs vcpu::sregs()
+{
+kvm_sregs sregs;
+_fd.ioctlp(KVM_GET_SREGS,sregs);
+return sregs;
+}


I think you're missing an opportunity by just returning the structures 
in their raw form as opposed to wrapping them in an object.


What would the object do besides adding tons of accessors?




+
+void vcpu::set_sregs(const kvm_sregs  sregs)
+{
+_fd.ioctlp(KVM_SET_SREGS, const_castkvm_sregs*(sregs));
+}
+
+kvm_msrs* vcpu::alloc_msr_list(size_t nmsrs)
+{
+size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
+kvm_msrs* ret = static_castkvm_msrs*(malloc(size));
+if (!ret) {
+throw ENOMEM;
+}
+return ret;
+}


malloc?

Mixing C and C++ allocations is nasty stuff.  Would be nicer to new an 
object and return it such that delete can be used consistently.


5 years of C.




+
+std::vectorkvm_msr_entry  vcpu::msrs(std::vectoruint32_t  indices)
+{
+std::auto_ptrkvm_msrs  msrs(alloc_msr_list(indices.size()));
+msrs-nmsrs = indices.size();
+for (unsigned i = 0; i  msrs-nmsrs; ++i) {
+msrs-entries[i].index = indices[i];
+}
+_fd.ioctlp(KVM_GET_MSRS, msrs.get());
+return std::vectorkvm_msr_entry(msrs-entries,
+  msrs-entries + msrs-nmsrs);
+}


auto_ptr has pretty awful semantics.  tr1::shared_ptr is now available.


For this it's perfectly fine.


+
+class fd {
+public:
+explicit fd(int n);
+explicit fd(std::string path, int flags);
+fd(const fd  other);
+~fd() { ::close(_fd); }
+int get() { return _fd; }
+long ioctl(unsigned nr, long arg);
+long ioctlp(unsigned nr, void *arg) {
+return ioctl(nr, reinterpret_castlong(arg));
+}


I think mixing inline definitions with declarations is bad form.


It is, but on the other hand I hate the verbosity of all those little 
accessors.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 02:59 PM, Alexander Graf wrote:

On 24.11.2010, at 11:52, Avi Kivity wrote:

  Introduce exception-safe objects for calling system, vm, and vcpu ioctls.

  Signed-off-by: Avi Kivitya...@redhat.com


FWIW, I still disagree with C++ and believe this code to be hardly readable.



The equivalent C code would have either no error checking or it would be 
a mess of error handling intermixed with bugs and a few lines which do 
actual work.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 04:18 PM, Anthony Liguori wrote:

On 11/24/2010 06:59 AM, Alexander Graf wrote:

On 24.11.2010, at 11:52, Avi Kivity wrote:

Introduce exception-safe objects for calling system, vm, and vcpu 
ioctls.


Signed-off-by: Avi Kivitya...@redhat.com


FWIW, I still disagree with C++ and believe this code to be hardly 
readable.


Take a look at http://repo.or.cz/w/qemupp.git



repo.or.cz is down.  Now if _that_ doesn't say anything about C++, then 
I don't know what does.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 06:59 AM, Alexander Graf wrote:

On 24.11.2010, at 11:52, Avi Kivity wrote:

   

Introduce exception-safe objects for calling system, vm, and vcpu ioctls.

Signed-off-by: Avi Kivitya...@redhat.com
 


FWIW, I still disagree with C++ and believe this code to be hardly readable.
   


There's a general prettiness that well written C++ code will have over C 
when there's heavy object modelling.  This can be subjective but for me, 
it's fairly significant.


The fact that objects are easily created on the stack and on the heap is 
also pretty significant.  When considering device models, we struggle 
today with device composition.


In real hardware, the i8042 (keyboard controller) is actually 
implemented in the PIIX3 which is a chip that is part of the i440fx.  
The i440fx acts as both the memory controller and as the PCI Host 
controller.  So you get something that looks like:


class PIIX3 : public PCIDevice
{
private:
I8042 i8042;
RTC rtc;
// ...
};

class I440FX : public PCIHostController
{
   I440FX(void) {
this-slots[1].plug(this-piix3); // piix3 is always in slot 1
   }

private:
   PlugPCIDevice * slots[32]; // slot 0 is the PMC
   PIIX3 piix3;
};

So whereas we have this very complicate machine create function that 
attempts to create and composite all of these devices after the fact, 
when written in C++, partially due to good design, but partially due to 
the fact that the languages forces you to think a certain way, you get a 
tremendous simplification.


A proper C++ device model turns a vast majority of our device creation 
complexity into a single new I440FX.  Then it's just a matter of 
instantiating and plugging the appropriate set of PCI devices.


Of course, this can be wrapped in a factory to make it drivable via an 
API or config file.


Another area that C++ shines is safety.  C++ enables you to inject safe 
versions of things that you really can't do in C.  For instance, the PIT 
has three channels but the mask to select a channel is two bits.  There 
was a kernel exploit that found a way to trick selection of a forth 
channel because of a missing check.


In C++, you can convert:

PITChannel channnels[3];

Into:

ArrayPITChannel, 3 channels;

It behaves in every other way just like a normal array.  The memory is 
stack allocated, the type has a fixed size.   The only difference is 
that you can overload the [] operators and implement bounds checking for 
array accesses.  This means that as long as you use Array, array 
overflows disappear from the code base.  That's a big deal.


Another area C++ shines is generating metacode.  Consider the ugliness 
around VMState.  The crux of the problem is that it's not possible to 
write type-neutral code in C.  This all gets simplified with C++.  
Instead of having a bunch of macros like:


VMSTATE_INT8(val0, ...)
VMSTATE_INT16(val1, ...)

You can just have:

vmstate(val0)
vmstate(val1)

And use type overloading to implement different behaviors.  Combined 
with template specialization and an Array wrapper, the same thing works 
for arrays too.


Regards,

Anthony Liguori

Regards,

Anthony Liguori


Alex


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 08:29 AM, Avi Kivity wrote:

On 11/24/2010 04:10 PM, Anthony Liguori wrote:

On 11/24/2010 04:52 AM, Avi Kivity wrote:
Introduce exception-safe objects for calling system, vm, and vcpu 
ioctls.


+
+namespace kvm {
+
+static long check_error(long r)
+{
+if (r == -1) {
+throw errno;
+}
+return r;
+}


It's generally nicer for exceptions to be objects and to inherit from 
std::exception.  Otherwise, you can run into nasty issues when 
catching the wrong type.



Yeah, I'm lazy.




+fd::fd(int fd)
+: _fd(fd)
+{
+}


There's no need to prefix with '_'.  Every compiler has been able to 
do the right thing with : fd(fd) for a long time.


Ok.




+
+kvm_sregs vcpu::sregs()
+{
+kvm_sregs sregs;
+_fd.ioctlp(KVM_GET_SREGS,sregs);
+return sregs;
+}


I think you're missing an opportunity by just returning the 
structures in their raw form as opposed to wrapping them in an object.


What would the object do besides adding tons of accessors?


I would think that you'd have a single object that represented the full 
CPU state and then you'd have methods that allowed individual groups to 
be refreshed.


Something like:

struct x86_vcpu : public vcpu
{
 uint64_t eax;
 uint64_t ebx;
 uint64_t ecx;
 //...

void get_gps(void);
void put_gps(void);
void get_sregs(void);
void put_sregs(void);

std::string repr(void);
};

I'm not of the opinion that all members need getters and setters.  I 
think it's perfectly fine to have public variables if the reads and 
writes don't have side effects.


Regards,

Anthony Liguori






+
+void vcpu::set_sregs(const kvm_sregs  sregs)
+{
+_fd.ioctlp(KVM_SET_SREGS, const_castkvm_sregs*(sregs));
+}
+
+kvm_msrs* vcpu::alloc_msr_list(size_t nmsrs)
+{
+size_t size = sizeof(kvm_msrs) + sizeof(kvm_msr_entry) * nmsrs;
+kvm_msrs* ret = static_castkvm_msrs*(malloc(size));
+if (!ret) {
+throw ENOMEM;
+}
+return ret;
+}


malloc?

Mixing C and C++ allocations is nasty stuff.  Would be nicer to new 
an object and return it such that delete can be used consistently.


5 years of C.




+
+std::vectorkvm_msr_entry  vcpu::msrs(std::vectoruint32_t  indices)
+{
+std::auto_ptrkvm_msrs  msrs(alloc_msr_list(indices.size()));
+msrs-nmsrs = indices.size();
+for (unsigned i = 0; i  msrs-nmsrs; ++i) {
+msrs-entries[i].index = indices[i];
+}
+_fd.ioctlp(KVM_GET_MSRS, msrs.get());
+return std::vectorkvm_msr_entry(msrs-entries,
+  msrs-entries + msrs-nmsrs);
+}


auto_ptr has pretty awful semantics.  tr1::shared_ptr is now available.


For this it's perfectly fine.


+
+class fd {
+public:
+explicit fd(int n);
+explicit fd(std::string path, int flags);
+fd(const fd  other);
+~fd() { ::close(_fd); }
+int get() { return _fd; }
+long ioctl(unsigned nr, long arg);
+long ioctlp(unsigned nr, void *arg) {
+return ioctl(nr, reinterpret_castlong(arg));
+}


I think mixing inline definitions with declarations is bad form.


It is, but on the other hand I hate the verbosity of all those little 
accessors.




--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 04:45 PM, Anthony Liguori wrote:

What would the object do besides adding tons of accessors?



I would think that you'd have a single object that represented the 
full CPU state and then you'd have methods that allowed individual 
groups to be refreshed.


Something like:

struct x86_vcpu : public vcpu
{
 uint64_t eax;
 uint64_t ebx;
 uint64_t ecx;
 //...

void get_gps(void);
void put_gps(void);
void get_sregs(void);
void put_sregs(void);

std::string repr(void);
};

I'm not of the opinion that all members need getters and setters.  I 
think it's perfectly fine to have public variables if the reads and 
writes don't have side effects.


I see.  Well that belongs elsewhere, this is intended as a thin wrapper 
that doesn't allows you to exercise the API directly.  I don't want 
things to happen automatically here, this is for a test framework.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 08:53 AM, Avi Kivity wrote:

struct x86_vcpu : public vcpu
{
 uint64_t eax;
 uint64_t ebx;
 uint64_t ecx;
 //...

void get_gps(void);
void put_gps(void);
void get_sregs(void);
void put_sregs(void);

std::string repr(void);
};

I'm not of the opinion that all members need getters and setters.  I 
think it's perfectly fine to have public variables if the reads and 
writes don't have side effects.



I see.  Well that belongs elsewhere, this is intended as a thin 
wrapper that doesn't allows you to exercise the API directly.  I don't 
want things to happen automatically here, this is for a test framework.


That's fine.

Regards,

Anthony Liguori


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 08:41:26AM -0600, Anthony Liguori wrote:
 On 11/24/2010 06:59 AM, Alexander Graf wrote:
 On 24.11.2010, at 11:52, Avi Kivity wrote:
 
 Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
 
 Signed-off-by: Avi Kivitya...@redhat.com
 
 FWIW, I still disagree with C++ and believe this code to be hardly readable.
 
 There's a general prettiness that well written C++ code will have
 over C when there's heavy object modelling.  This can be subjective
 but for me, it's fairly significant.
 
 The fact that objects are easily created on the stack and on the
 heap is also pretty significant.  When considering device models, we
 struggle today with device composition.
 
 In real hardware, the i8042 (keyboard controller) is actually
 implemented in the PIIX3 which is a chip that is part of the i440fx.
 The i440fx acts as both the memory controller and as the PCI Host
 controller.  So you get something that looks like:
 
 class PIIX3 : public PCIDevice
 {
 private:
 I8042 i8042;
 RTC rtc;
 // ...
 };
 
The fact that in physical implementation they sit in the same silicon
does not mean that logically they belong to the same class. PIIX3
is ISA bridge. It doesn't mean it owns devices on the ISA bus it
provides. The information that you are trying to convey here belongs to
configuration file. Here I go factory design pattern.
 

 class I440FX : public PCIHostController
 {
I440FX(void) {
 this-slots[1].plug(this-piix3); // piix3 is always in slot 1
}
 
 private:
PlugPCIDevice * slots[32]; // slot 0 is the PMC
PIIX3 piix3;
 };
 
 So whereas we have this very complicate machine create function that
 attempts to create and composite all of these devices after the
 fact, when written in C++, partially due to good design, but
 partially due to the fact that the languages forces you to think a
 certain way, you get a tremendous simplification.
 
Forcing to think you in certain way does not make you suddenly make good
design decisions (if only programming was so easy). But it makes it even
harder to fix bad decision since suddenly all you design depends on it. 

 A proper C++ device model turns a vast majority of our device
 creation complexity into a single new I440FX.  Then it's just a
 matter of instantiating and plugging the appropriate set of PCI
 devices.
That is if you are using code as data. With other design you actually
read I440FX configuration from file and build it from smaller parts.
You see C++ doesn't stop us from arguing what design is correct.


 
 Of course, this can be wrapped in a factory to make it drivable via
 an API or config file.
Exactly.

 
 Another area that C++ shines is safety.  C++ enables you to inject
 safe versions of things that you really can't do in C.  For
 instance, the PIT has three channels but the mask to select a
 channel is two bits.  There was a kernel exploit that found a way to
 trick selection of a forth channel because of a missing check.
 
 In C++, you can convert:
 
 PITChannel channnels[3];
 
 Into:
 
 ArrayPITChannel, 3 channels;
 
Any sane modern language gives you that. Why C++?

 It behaves in every other way just like a normal array.  The memory
 is stack allocated, the type has a fixed size.   The only difference
 is that you can overload the [] operators and implement bounds
 checking for array accesses.  This means that as long as you use
 Array, array overflows disappear from the code base.  That's a big
 deal.
 
 Another area C++ shines is generating metacode.  Consider the
 ugliness around VMState.  The crux of the problem is that it's not
 possible to write type-neutral code in C.  This all gets simplified
 with C++.  Instead of having a bunch of macros like:
 
 VMSTATE_INT8(val0, ...)
 VMSTATE_INT16(val1, ...)
 
 You can just have:
 
 vmstate(val0)
 vmstate(val1)
 
 And use type overloading to implement different behaviors.  Combined
 with template specialization and an Array wrapper, the same thing
 works for arrays too.
 
 Regards,
 
 Anthony Liguori
 
 Regards,
 
 Anthony Liguori
 
 Alex
 
 
 --
 To unsubscribe from this list: send the line unsubscribe kvm in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
 
 --
 To unsubscribe from this list: send the line unsubscribe kvm in
 the body of a message to majord...@vger.kernel.org
 More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 09:40 AM, Gleb Natapov wrote:

On Wed, Nov 24, 2010 at 08:41:26AM -0600, Anthony Liguori wrote:
   

On 11/24/2010 06:59 AM, Alexander Graf wrote:
 

On 24.11.2010, at 11:52, Avi Kivity wrote:

   

Introduce exception-safe objects for calling system, vm, and vcpu ioctls.

Signed-off-by: Avi Kivitya...@redhat.com
 

FWIW, I still disagree with C++ and believe this code to be hardly readable.
   

There's a general prettiness that well written C++ code will have
over C when there's heavy object modelling.  This can be subjective
but for me, it's fairly significant.

The fact that objects are easily created on the stack and on the
heap is also pretty significant.  When considering device models, we
struggle today with device composition.

In real hardware, the i8042 (keyboard controller) is actually
implemented in the PIIX3 which is a chip that is part of the i440fx.
The i440fx acts as both the memory controller and as the PCI Host
controller.  So you get something that looks like:

class PIIX3 : public PCIDevice
{
private:
 I8042 i8042;
 RTC rtc;
 // ...
};

 

The fact that in physical implementation they sit in the same silicon
does not mean that logically they belong to the same class. PIIX3
is ISA bridge. It doesn't mean it owns devices on the ISA bus it
provides. The information that you are trying to convey here belongs to
configuration file.


Why would we specify a PIIX3 device based on a configuration file?  
There is only one PIIX3 device in the world.  I don't see a lot of need 
to create arbitrary types of devices.


The real world hierarchy matters when you're trying to model I/O dispatch.


  Here I go factory design pattern.
   


I think it's a lot of abstraction for very little gain and leads to 
bizarreness like treating any platform device as an ISA device.


An RTC is *not* an ISA device.  It may sit *behind* an ISA bus because 
the SuperIO chip happens to be on the ISA bus.  But on modern systems, 
the ISA bus has disappeared in favor of the LPC but that doesn't 
fundamentally change what the RTC is.


The problem with what you describe is that there are far fewer devices 
that actually sit on busses than what QEMU tries to model today.



class I440FX : public PCIHostController
{
I440FX(void) {
 this-slots[1].plug(this-piix3); // piix3 is always in slot 1
}

private:
PlugPCIDevice *  slots[32]; // slot 0 is the PMC
PIIX3 piix3;
};

So whereas we have this very complicate machine create function that
attempts to create and composite all of these devices after the
fact, when written in C++, partially due to good design, but
partially due to the fact that the languages forces you to think a
certain way, you get a tremendous simplification.

 

Forcing to think you in certain way does not make you suddenly make good
design decisions (if only programming was so easy). But it makes it even
harder to fix bad decision since suddenly all you design depends on it.

   

A proper C++ device model turns a vast majority of our device
creation complexity into a single new I440FX.  Then it's just a
matter of instantiating and plugging the appropriate set of PCI
devices.
 

That is if you are using code as data. With other design you actually
read I440FX configuration from file and build it from smaller parts.
You see C++ doesn't stop us from arguing what design is correct.
   


That's fair.  I think 90% of what we need is better design.  I think a 
better language only gives us 10%.



Another area that C++ shines is safety.  C++ enables you to inject
safe versions of things that you really can't do in C.  For
instance, the PIT has three channels but the mask to select a
channel is two bits.  There was a kernel exploit that found a way to
trick selection of a forth channel because of a missing check.

In C++, you can convert:

PITChannel channnels[3];

Into:

ArrayPITChannel, 3  channels;

 

Any sane modern language gives you that. Why C++?
   


Because I don't think we can implement a reasonable device model using a 
garbage collected language.  Garbage collection introduces 
non-determinism and in QEMU we need to ensure that when we're running in 
a VCPU context, we exit back to the guest as quickly as possible.


Regards,

Anthony Liguori
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 05:50 PM, Anthony Liguori wrote:



Any sane modern language gives you that. Why C++?



Because I don't think we can implement a reasonable device model using 
a garbage collected language.  Garbage collection introduces 
non-determinism and in QEMU we need to ensure that when we're running 
in a VCPU context, we exit back to the guest as quickly as possible.


My answer is that C++ is the only language that allows you to evolve 
away from C, with mixed C/C++ source (not just linkage level 
compatibility).  If there are others, I want to know about them.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 09:50:35AM -0600, Anthony Liguori wrote:
 On 11/24/2010 09:40 AM, Gleb Natapov wrote:
 On Wed, Nov 24, 2010 at 08:41:26AM -0600, Anthony Liguori wrote:
 On 11/24/2010 06:59 AM, Alexander Graf wrote:
 On 24.11.2010, at 11:52, Avi Kivity wrote:
 
 Introduce exception-safe objects for calling system, vm, and vcpu ioctls.
 
 Signed-off-by: Avi Kivitya...@redhat.com
 FWIW, I still disagree with C++ and believe this code to be hardly 
 readable.
 There's a general prettiness that well written C++ code will have
 over C when there's heavy object modelling.  This can be subjective
 but for me, it's fairly significant.
 
 The fact that objects are easily created on the stack and on the
 heap is also pretty significant.  When considering device models, we
 struggle today with device composition.
 
 In real hardware, the i8042 (keyboard controller) is actually
 implemented in the PIIX3 which is a chip that is part of the i440fx.
 The i440fx acts as both the memory controller and as the PCI Host
 controller.  So you get something that looks like:
 
 class PIIX3 : public PCIDevice
 {
 private:
  I8042 i8042;
  RTC rtc;
  // ...
 };
 
 The fact that in physical implementation they sit in the same silicon
 does not mean that logically they belong to the same class. PIIX3
 is ISA bridge. It doesn't mean it owns devices on the ISA bus it
 provides. The information that you are trying to convey here belongs to
 configuration file.
 
 Why would we specify a PIIX3 device based on a configuration file?
 There is only one PIIX3 device in the world.  I don't see a lot of
 need to create arbitrary types of devices.
 
Why deny this flexibility from those who need it for modelling
different HW? Besides, as I said, PIIX3 is ISA bridge and this
is what class should implement. We have fw_cfg on ISA bus too
which does not exits on real HW and we may want to have other
devices. We should be able to add them without changing PIIX3
class.

 The real world hierarchy matters when you're trying to model I/O dispatch.
 
Or build device path. Any time we do something not as real HW we
regret it later.

   Here I go factory design pattern.
 
 I think it's a lot of abstraction for very little gain and leads to
 bizarreness like treating any platform device as an ISA device.
 
Why?

 An RTC is *not* an ISA device.  It may sit *behind* an ISA bus
 because the SuperIO chip happens to be on the ISA bus.  But on
 modern systems, the ISA bus has disappeared in favor of the LPC but
 that doesn't fundamentally change what the RTC is.
Agree. This is a device sitting on the ISA bus on a PC, but it can
sit on other buses too. And it happily does so on other architectures.

 
 The problem with what you describe is that there are far fewer
 devices that actually sit on busses than what QEMU tries to model
 today.
All devices sit on some buses.

 
 class I440FX : public PCIHostController
 {
 I440FX(void) {
  this-slots[1].plug(this-piix3); // piix3 is always in slot 1
 }
 
 private:
 PlugPCIDevice *  slots[32]; // slot 0 is the PMC
 PIIX3 piix3;
 };
 
 So whereas we have this very complicate machine create function that
 attempts to create and composite all of these devices after the
 fact, when written in C++, partially due to good design, but
 partially due to the fact that the languages forces you to think a
 certain way, you get a tremendous simplification.
 
 Forcing to think you in certain way does not make you suddenly make good
 design decisions (if only programming was so easy). But it makes it even
 harder to fix bad decision since suddenly all you design depends on it.
 
 A proper C++ device model turns a vast majority of our device
 creation complexity into a single new I440FX.  Then it's just a
 matter of instantiating and plugging the appropriate set of PCI
 devices.
 That is if you are using code as data. With other design you actually
 read I440FX configuration from file and build it from smaller parts.
 You see C++ doesn't stop us from arguing what design is correct.
 
 That's fair.  I think 90% of what we need is better design.  I think
 a better language only gives us 10%.
 
 Another area that C++ shines is safety.  C++ enables you to inject
 safe versions of things that you really can't do in C.  For
 instance, the PIT has three channels but the mask to select a
 channel is two bits.  There was a kernel exploit that found a way to
 trick selection of a forth channel because of a missing check.
 
 In C++, you can convert:
 
 PITChannel channnels[3];
 
 Into:
 
 ArrayPITChannel, 3  channels;
 
 Any sane modern language gives you that. Why C++?
 
 Because I don't think we can implement a reasonable device model
 using a garbage collected language.  Garbage collection introduces
 non-determinism and in QEMU we need to ensure that when we're
 running in a VCPU context, we exit back to the guest as quickly as
 possible.
 
IIRC there are garbage collected languages that allow you to 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:12 PM, Gleb Natapov wrote:


  Why would we specify a PIIX3 device based on a configuration file?
  There is only one PIIX3 device in the world.  I don't see a lot of
  need to create arbitrary types of devices.

Why deny this flexibility from those who need it for modelling
different HW?


The various components exist and can be reused.


Besides, as I said, PIIX3 is ISA bridge and this
is what class should implement.


Isn't it an ISA bridge + a few ISA devices?


We have fw_cfg on ISA bus too
which does not exits on real HW and we may want to have other
devices. We should be able to add them without changing PIIX3
class.


fw_cfg should certainly not be a member of PIIX3.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 06:14:22PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:12 PM, Gleb Natapov wrote:
 
   Why would we specify a PIIX3 device based on a configuration file?
   There is only one PIIX3 device in the world.  I don't see a lot of
   need to create arbitrary types of devices.
 
 Why deny this flexibility from those who need it for modelling
 different HW?
 
 The various components exist and can be reused.
 
So you are saying lets use code as data for some and config files for
others. If you have support for building chipsets from data why not
simply have 440fx.cfg somewhere? Besides what qemu provides no is not
stock PIIX3. We have parts of PIIX4 for power management.

 Besides, as I said, PIIX3 is ISA bridge and this
 is what class should implement.
 
 Isn't it an ISA bridge + a few ISA devices?
 
Why? Because they happen to be on the same silicon? So then in SoC
all devices are in cpu?

 We have fw_cfg on ISA bus too
 which does not exits on real HW and we may want to have other
 devices. We should be able to add them without changing PIIX3
 class.
 
 fw_cfg should certainly not be a member of PIIX3.
 
It is really not much different from others.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:21 PM, Gleb Natapov wrote:

On Wed, Nov 24, 2010 at 06:14:22PM +0200, Avi Kivity wrote:
  On 11/24/2010 06:12 PM, Gleb Natapov wrote:
  
 Why would we specify a PIIX3 device based on a configuration file?
 There is only one PIIX3 device in the world.  I don't see a lot of
 need to create arbitrary types of devices.
  
  Why deny this flexibility from those who need it for modelling
  different HW?

  The various components exist and can be reused.

So you are saying lets use code as data for some and config files for
others. If you have support for building chipsets from data why not
simply have 440fx.cfg somewhere?


I don't object to it.  If it can be done, it's a good thing.

Often integrated chipsets have lots of little special cases though.  For 
example some pins acting as GPIO if an embedded device is disabled.



Besides what qemu provides no is not
stock PIIX3. We have parts of PIIX4 for power management.


That's a bug.


  Besides, as I said, PIIX3 is ISA bridge and this
  is what class should implement.

  Isn't it an ISA bridge + a few ISA devices?

Why? Because they happen to be on the same silicon? So then in SoC
all devices are in cpu?


PIIX3 is what the PIIX3 spec says it is.  We decompose it into the PIIX3 
ISA bridge, real time clock, etc.  Some of these components are 
standardized and can be used stand-alone.



  We have fw_cfg on ISA bus too
  which does not exits on real HW and we may want to have other
  devices. We should be able to add them without changing PIIX3
  class.

  fw_cfg should certainly not be a member of PIIX3.

It is really not much different from others.


I couldn't find it in the PIIX3 spec.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 13:59, Alexander Graf wrote:
 
 On 24.11.2010, at 11:52, Avi Kivity wrote:
 
 Introduce exception-safe objects for calling system, vm, and vcpu ioctls.

 Signed-off-by: Avi Kivity a...@redhat.com
 
 
 FWIW, I still disagree with C++ and believe this code to be hardly readable.

YUCK!

It's got :'s all over the place that makes no sense whatsoever :(

Jes

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 06:25:44PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:21 PM, Gleb Natapov wrote:
 On Wed, Nov 24, 2010 at 06:14:22PM +0200, Avi Kivity wrote:
   On 11/24/2010 06:12 PM, Gleb Natapov wrote:
   
  Why would we specify a PIIX3 device based on a configuration file?
  There is only one PIIX3 device in the world.  I don't see a lot of
  need to create arbitrary types of devices.
   
   Why deny this flexibility from those who need it for modelling
   different HW?
 
   The various components exist and can be reused.
 
 So you are saying lets use code as data for some and config files for
 others. If you have support for building chipsets from data why not
 simply have 440fx.cfg somewhere?
 
 I don't object to it.  If it can be done, it's a good thing.
 
 Often integrated chipsets have lots of little special cases though.
 For example some pins acting as GPIO if an embedded device is
 disabled.
 
 Besides what qemu provides no is not
 stock PIIX3. We have parts of PIIX4 for power management.
 
 That's a bug.
 
   Besides, as I said, PIIX3 is ISA bridge and this
   is what class should implement.
 
   Isn't it an ISA bridge + a few ISA devices?
 
 Why? Because they happen to be on the same silicon? So then in SoC
 all devices are in cpu?
 
 PIIX3 is what the PIIX3 spec says it is.  We decompose it into the
 PIIX3 ISA bridge, real time clock, etc.  Some of these components
 are standardized and can be used stand-alone.
 
So PIIX3 is just a packaging of mostly independent components for cost
and space cutting. Just like SoC.

   We have fw_cfg on ISA bus too
   which does not exits on real HW and we may want to have other
   devices. We should be able to add them without changing PIIX3
   class.
 
   fw_cfg should certainly not be a member of PIIX3.
 
 It is really not much different from others.
 
 I couldn't find it in the PIIX3 spec.
 
I couldn't find it in _any_ spec. Should we get rid of it?

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:29 PM, Gleb Natapov wrote:


 Besides, as I said, PIIX3 is ISA bridge and this
 is what class should implement.
  
 Isn't it an ISA bridge + a few ISA devices?
  
  Why? Because they happen to be on the same silicon? So then in SoC
  all devices are in cpu?

  PIIX3 is what the PIIX3 spec says it is.  We decompose it into the
  PIIX3 ISA bridge, real time clock, etc.  Some of these components
  are standardized and can be used stand-alone.

So PIIX3 is just a packaging of mostly independent components for cost
and space cutting. Just like SoC.


Plus some magic glue.  You can't say it is an ISA bridge.  It's exactly 
what its spec says it is.



 We have fw_cfg on ISA bus too
 which does not exits on real HW and we may want to have other
 devices. We should be able to add them without changing PIIX3
 class.
  
 fw_cfg should certainly not be a member of PIIX3.
  
  It is really not much different from others.

  I couldn't find it in the PIIX3 spec.

I couldn't find it in _any_ spec. Should we get rid of it?


Or write a spec.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:29 PM, Jes Sorensen wrote:


  FWIW, I still disagree with C++ and believe this code to be hardly readable.

YUCK!

It's got :'s all over the place that makes no sense whatsoever :(


You've got two in one sentence! Practice what you preach.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 16:50, Anthony Liguori wrote:
 On 11/24/2010 09:40 AM, Gleb Natapov wrote:
 On Wed, Nov 24, 2010 at 08:41:26AM -0600, Anthony Liguori wrote:
 In real hardware, the i8042 (keyboard controller) is actually
 implemented in the PIIX3 which is a chip that is part of the i440fx.
 The i440fx acts as both the memory controller and as the PCI Host
 controller.  So you get something that looks like:

 class PIIX3 : public PCIDevice
 {
 private:
  I8042 i8042;
  RTC rtc;
  // ...
 };

  
 The fact that in physical implementation they sit in the same silicon
 does not mean that logically they belong to the same class. PIIX3
 is ISA bridge. It doesn't mean it owns devices on the ISA bus it
 provides. The information that you are trying to convey here belongs to
 configuration file.
 
 Why would we specify a PIIX3 device based on a configuration file? 
 There is only one PIIX3 device in the world.  I don't see a lot of need
 to create arbitrary types of devices.

Well the problem here is that the i8042 is in the i440fx.c file, it
shouldn't be there in the first place. The gluing together things in
silicon is really just a way to shorten the wires and make it easier,
they are still separate devices and as long as the i8042 requires ISA
access, and to be treated like an ISA device, we should glue it onto the
virtual ISA bus within QEMU.

What you did above is making the exact same mistake as is done with the
current i440fx.c code.

 I think it's a lot of abstraction for very little gain and leads to
 bizarreness like treating any platform device as an ISA device.
 
 An RTC is *not* an ISA device.  It may sit *behind* an ISA bus because
 the SuperIO chip happens to be on the ISA bus.  But on modern systems,
 the ISA bus has disappeared in favor of the LPC but that doesn't
 fundamentally change what the RTC is.
 
 The problem with what you describe is that there are far fewer devices
 that actually sit on busses than what QEMU tries to model today.

A PCI device is mapped on a PCI bus as a PCI function etc. If the device
is hard wired to a fixed address, or worse a fixed IO port, then it is
an ISA device.

 So whereas we have this very complicate machine create function that
 attempts to create and composite all of these devices after the
 fact, when written in C++, partially due to good design, but
 partially due to the fact that the languages forces you to think a
 certain way, you get a tremendous simplification.

That is clearly dependent on the eyes of the person who looks at it.

 That is if you are using code as data. With other design you actually
 read I440FX configuration from file and build it from smaller parts.
 You see C++ doesn't stop us from arguing what design is correct.

 
 That's fair.  I think 90% of what we need is better design.  I think a
 better language only gives us 10%.

Well the problem is the 10% you are talking about is another 30% loss
because the code is now practically unreadable, plus you open up the can
of worms that people will start using some of the totally broken
features of C++. Sure you can try hard to make sure they don't sneak in,
but down the line they will, and at that point the codebase is totally
ruined.

Avi's unittest code is a perfect example of code that is unreadable for
a C programmer. Or to quote a smart man 'the code is clear as perl!'.
So you have now lost or at least crippled half your developer base,
making it way harder for them to contribute something useful.

This is a big step in the wrong direction :(

Jes
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 10:12 AM, Gleb Natapov wrote:



Why would we specify a PIIX3 device based on a configuration file?
There is only one PIIX3 device in the world.  I don't see a lot of
need to create arbitrary types of devices.

 

Why deny this flexibility from those who need it for modelling
different HW? Besides, as I said, PIIX3 is ISA bridge and this
is what class should implement. We have fw_cfg on ISA bus too
which does not exits on real HW and we may want to have other
devices. We should be able to add them without changing PIIX3
class.
   


Because this flexibility is a misfeature.  It's something that noone 
actually uses and I've never seen anyone ask to have.


It introduces a PC-centric view of the world where you artificially make 
a bunch of devices have bus specific logic that they really don't have.


If you want to go down this route, the right approach to take is to make 
a separate IsaMc161818a device that has a Mc16818a device with a has-a 
relation (i.e. composition).


But I don't see the point.  Just stick the Mc16818a device in the PIIX3 
via composition as it exists on normal hardware and call it a day.


BTW, the only reason any of this works is because of the fact that the 
PIIX3 does subtractive decoding which allows arbitrary ISA devices to be 
plugged into the ISA bus.  But subtractive decoding is very expensive 
and on modern LPC implementations, positive decoding is used which means 
that the chipset has a white list of ports for devices that sit on it.


PCs are simply not as architecturally clean as I think you're advocating 
we try to model them.



The real world hierarchy matters when you're trying to model I/O dispatch.

 

Or build device path. Any time we do something not as real HW we
regret it later.
   


Right, and real HW does composition in the PIIX3 device.  So let's not 
regret making everything an ISA device later.



An RTC is *not* an ISA device.  It may sit *behind* an ISA bus
because the SuperIO chip happens to be on the ISA bus.  But on
modern systems, the ISA bus has disappeared in favor of the LPC but
that doesn't fundamentally change what the RTC is.
 

Agree. This is a device sitting on the ISA bus on a PC, but it can
sit on other buses too. And it happily does so on other architectures.
   


It doesn't sit on the ISA bus.  A SuperIO chip sits on the ISA bus and 
the SuperIO chip decodes the ISA bus traffic and dispatches approriately.


On the PIIX3, the SuperIO chip is part of the chipset.  An ISA 
transaction isn't necessary to talk to the RTC--it would simply be too 
expensive to do this because of subtractive decoding.



The problem with what you describe is that there are far fewer
devices that actually sit on busses than what QEMU tries to model
today.
 

All devices sit on some buses.
   


That's simply not true.  Let's be specific about what a bus is.  A bus 
is a set of lines that is shared by multiple devices with some mechanism 
to arbitrate who's using the bus at any given time.  In PCI, roughly 
speaking, a transaction is sent from the controller to all devices on 
the bus and the device that is to handle the transaction will raise it's 
DEVSEL line to indicate that it's handling it.


But there are plenty of cases where a device is hard wired to another 
device.  In a simple microcontroller, it's extremely common to tie a set 
of GPIO pins to a specific device.  There's no bus here.


The i8042 is another good example.  The i8042 has two ps2 plugs but it's 
not a bus.  The keyboard port takes a keyboard and the aux port takes a 
mouse.  You can't hook up two keyboards and you can't hook up two mice.



Because I don't think we can implement a reasonable device model
using a garbage collected language.  Garbage collection introduces
non-determinism and in QEMU we need to ensure that when we're
running in a VCPU context, we exit back to the guest as quickly as
possible.

 

IIRC there are garbage collected languages that allow you to disable garbage
collection for certain part of the code.


Yeah, but very few languages that I know of are sophisticated here.


  Garbage collection can be done
while vcpu executes guest code and in proper implementation vcpu thread
should execute device model code for a very brief time and do not sleep
there. All this makes me think that garbage collection shouldn't be a
big issue for kvm userspace.


But I don't see the point.  If you look at my repository, there's very 
few memory allocations.  This is largely due to the fact that I don't 
overly abstract busses and rely on simple composition where appropriate.


Plus, with tr1::smart_pointers, you can be leak free without every 
worrying about explicit freeing.  There are, of course, possibilities of 
having circular references but it's not too hard to avoid that in practice.


Regards,

Anthony Liguori



--
Gleb.
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 10:21 AM, Gleb Natapov wrote:

On Wed, Nov 24, 2010 at 06:14:22PM +0200, Avi Kivity wrote:
   

On 11/24/2010 06:12 PM, Gleb Natapov wrote:
 

  Why would we specify a PIIX3 device based on a configuration file?
  There is only one PIIX3 device in the world.  I don't see a lot of
  need to create arbitrary types of devices.

 

Why deny this flexibility from those who need it for modelling
different HW?
   

The various components exist and can be reused.

 

So you are saying lets use code as data for some and config files for
others. If you have support for building chipsets from data why not
simply have 440fx.cfg somewhere? Besides what qemu provides no is not
stock PIIX3. We have parts of PIIX4 for power management.

   

Besides, as I said, PIIX3 is ISA bridge and this
is what class should implement.
   

Isn't it an ISA bridge + a few ISA devices?

 

Why? Because they happen to be on the same silicon? So then in SoC
all devices are in cpu?
   


They *aren't* ISA devices.  Look at the PIIX3 spec.  All of the ports 
for these devices are positively decoded and not sent over the ISA bus.


You could model them as being behind the ISA bus but you could also 
model them as being behind the PCI bus.


Regards,

Anthony Liguori


We have fw_cfg on ISA bus too
which does not exits on real HW and we may want to have other
devices. We should be able to add them without changing PIIX3
class.
   

fw_cfg should certainly not be a member of PIIX3.

 

It is really not much different from others.

--
Gleb.
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 17:34, Avi Kivity wrote:
 On 11/24/2010 06:29 PM, Jes Sorensen wrote:
 
   FWIW, I still disagree with C++ and believe this code to be hardly
 readable.

 YUCK!

 It's got :'s all over the place that makes no sense whatsoever :(
 
 You've got two in one sentence! Practice what you preach.
 

If you want to reject my patches due to my broken English, go ahead. At
least it should be somewhat readable.

Jes

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:40 PM, Jes Sorensen wrote:


  The fact that in physical implementation they sit in the same silicon
  does not mean that logically they belong to the same class. PIIX3
  is ISA bridge. It doesn't mean it owns devices on the ISA bus it
  provides. The information that you are trying to convey here belongs to
  configuration file.

  Why would we specify a PIIX3 device based on a configuration file?
  There is only one PIIX3 device in the world.  I don't see a lot of need
  to create arbitrary types of devices.

Well the problem here is that the i8042 is in the i440fx.c file, it
shouldn't be there in the first place. The gluing together things in
silicon is really just a way to shorten the wires and make it easier,
they are still separate devices and as long as the i8042 requires ISA
access, and to be treated like an ISA device, we should glue it onto the
virtual ISA bus within QEMU.

What you did above is making the exact same mistake as is done with the
current i440fx.c code.


If a real life 440fx has an i8042, then an emulated 440fx should have an 
emulated i8042.  It's not complicated.



  So whereas we have this very complicate machine create function that
  attempts to create and composite all of these devices after the
  fact, when written in C++, partially due to good design, but
  partially due to the fact that the languages forces you to think a
  certain way, you get a tremendous simplification.

That is clearly dependent on the eyes of the person who looks at it.


It's independent of language.  It should be done in C as well.  C++ just 
makes it easier by reducing the boilerplate.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 10:43:57AM -0600, Anthony Liguori wrote:
 On 11/24/2010 10:21 AM, Gleb Natapov wrote:
 On Wed, Nov 24, 2010 at 06:14:22PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:12 PM, Gleb Natapov wrote:
   Why would we specify a PIIX3 device based on a configuration file?
   There is only one PIIX3 device in the world.  I don't see a lot of
   need to create arbitrary types of devices.
 
 Why deny this flexibility from those who need it for modelling
 different HW?
 The various components exist and can be reused.
 
 So you are saying lets use code as data for some and config files for
 others. If you have support for building chipsets from data why not
 simply have 440fx.cfg somewhere? Besides what qemu provides no is not
 stock PIIX3. We have parts of PIIX4 for power management.
 
 Besides, as I said, PIIX3 is ISA bridge and this
 is what class should implement.
 Isn't it an ISA bridge + a few ISA devices?
 
 Why? Because they happen to be on the same silicon? So then in SoC
 all devices are in cpu?
 
 They *aren't* ISA devices.  Look at the PIIX3 spec.  All of the
 ports for these devices are positively decoded and not sent over the
 ISA bus.
 
Over the external ISA bus you mean?

 You could model them as being behind the ISA bus but you could also
 model them as being behind the PCI bus.
 
Just yesterday I checked how different ports behave if you use inw/inl
to read data from them.  They behave very different from what PCI spec
says. This was recent HW.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:44 PM, Jes Sorensen wrote:


  It's got :'s all over the place that makes no sense whatsoever :(

  You've got two in one sentence! Practice what you preach.


If you want to reject my patches due to my broken English, go ahead. At
least it should be somewhat readable.


I was referring to your : count.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 17:47, Avi Kivity wrote:
 On 11/24/2010 06:40 PM, Jes Sorensen wrote:
 Well the problem here is that the i8042 is in the i440fx.c file, it
 shouldn't be there in the first place. The gluing together things in
 silicon is really just a way to shorten the wires and make it easier,
 they are still separate devices and as long as the i8042 requires ISA
 access, and to be treated like an ISA device, we should glue it onto the
 virtual ISA bus within QEMU.

 What you did above is making the exact same mistake as is done with the
 current i440fx.c code.
 
 If a real life 440fx has an i8042, then an emulated 440fx should have an
 emulated i8042.  It's not complicated.

It's a question of how it is accessed, if it is treated like an ISA
device by the silicon, we should treat it like an ISA device in QEMU,
rather than pretend it is something that it isn't.

   So whereas we have this very complicate machine create function that
   attempts to create and composite all of these devices after the
   fact, when written in C++, partially due to good design, but
   partially due to the fact that the languages forces you to think a
   certain way, you get a tremendous simplification.

 That is clearly dependent on the eyes of the person who looks at it.
 
 It's independent of language.  It should be done in C as well.  C++ just
 makes it easier by reducing the boilerplate.

Right we need good design for our C code, which we are lacking to a
large extend. However that has nothing to do with the language, that has
to do with the developers.

Jes
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 06:33:17PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:29 PM, Gleb Natapov wrote:
 
  Besides, as I said, PIIX3 is ISA bridge and this
  is what class should implement.
   
  Isn't it an ISA bridge + a few ISA devices?
   
   Why? Because they happen to be on the same silicon? So then in SoC
   all devices are in cpu?
 
   PIIX3 is what the PIIX3 spec says it is.  We decompose it into the
   PIIX3 ISA bridge, real time clock, etc.  Some of these components
   are standardized and can be used stand-alone.
 
 So PIIX3 is just a packaging of mostly independent components for cost
 and space cutting. Just like SoC.
 
 Plus some magic glue.  You can't say it is an ISA bridge.  It's
 exactly what its spec says it is.
 
First thing my spec says is Bridge Between the PCI Bus and ISA Bus

  We have fw_cfg on ISA bus too
  which does not exits on real HW and we may want to have other
  devices. We should be able to add them without changing PIIX3
  class.
   
  fw_cfg should certainly not be a member of PIIX3.
   
   It is really not much different from others.
 
   I couldn't find it in the PIIX3 spec.
 
 I couldn't find it in _any_ spec. Should we get rid of it?
 
 Or write a spec.
 
It will not make it part of any existing system.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 10:40 AM, Jes Sorensen wrote:

Well the problem here is that the i8042 is in the i440fx.c file, it
shouldn't be there in the first place. The gluing together things in
silicon is really just a way to shorten the wires and make it easier,
they are still separate devices and as long as the i8042 requires ISA
access, and to be treated like an ISA device, we should glue it onto the
virtual ISA bus within QEMU.
   


Nope.  The PC is much, much uglier than everyone seems to realize.

Part of the reason the PIIX3 implements the i8042 (and the i440fx 
implements the PIIX3) is because the i8042 is needed to lower the a20 
line.  IOW, the i8042 has to signal to the memory controller to modify 
accesses to memory addresses from the CPU.


It's not just a statement of cost savings.  One of the reasons 
everything's in the same piece of silicon is because of the horribly 
incestuous nature of the PC architecture.  It's not a nice tree of 
parent busses and children devices.  It's an interbreeding group of 
devices who's parent's are their siblings and brother's are their uncles.



I think it's a lot of abstraction for very little gain and leads to
bizarreness like treating any platform device as an ISA device.

An RTC is *not* an ISA device.  It may sit *behind* an ISA bus because
the SuperIO chip happens to be on the ISA bus.  But on modern systems,
the ISA bus has disappeared in favor of the LPC but that doesn't
fundamentally change what the RTC is.

The problem with what you describe is that there are far fewer devices
that actually sit on busses than what QEMU tries to model today.
 

A PCI device is mapped on a PCI bus as a PCI function etc. If the device
is hard wired to a fixed address, or worse a fixed IO port, then it is
an ISA device.
   


Wrong.   The PCI controller sends all port and memory I/O operations 
over the bus.  Any PCI device can select to handle any address they want 
by simply issuing a DEVSEL.  The ability to do switching wasn't 
introduced until PCI-X.


The way a PCI-to-ISA bridge works is by waiting for a full bus cycle to 
see that no device has issued a DEVSEL, and then issuing a DEVSEL.  This 
is called subtractive decoding.  It then forwards the I/O request over 
the ISA bus and roughly the same thing happens on the ISA bus.



That is if you are using code as data. With other design you actually
read I440FX configuration from file and build it from smaller parts.
You see C++ doesn't stop us from arguing what design is correct.

   

That's fair.  I think 90% of what we need is better design.  I think a
better language only gives us 10%.
 

Well the problem is the 10% you are talking about is another 30% loss
because the code is now practically unreadable, plus you open up the can
of worms that people will start using some of the totally broken
features of C++.


Did you look at my code or Avi's code?

Look at my code and then tell me it's practically unreadable.

http://git.qemu.org/qemupp.git/tree/test/test-mc146818a.cpp


  Sure you can try hard to make sure they don't sneak in,
but down the line they will, and at that point the codebase is totally
ruined.

Avi's unittest code is a perfect example of code that is unreadable for
a C programmer. Or to quote a smart man 'the code is clear as perl!'.
So you have now lost or at least crippled half your developer base,
making it way harder for them to contribute something useful.

This is a big step in the wrong direction :(
   


I wouldn't have written the unittest code to use classes or exceptions 
at all.  I don't think it's a good fit.


Regards,

Anthony Liguori


Jes
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 06:47:28PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:40 PM, Jes Sorensen wrote:
 
   The fact that in physical implementation they sit in the same silicon
   does not mean that logically they belong to the same class. PIIX3
   is ISA bridge. It doesn't mean it owns devices on the ISA bus it
   provides. The information that you are trying to convey here belongs to
   configuration file.
 
   Why would we specify a PIIX3 device based on a configuration file?
   There is only one PIIX3 device in the world.  I don't see a lot of need
   to create arbitrary types of devices.
 
 Well the problem here is that the i8042 is in the i440fx.c file, it
 shouldn't be there in the first place. The gluing together things in
 silicon is really just a way to shorten the wires and make it easier,
 they are still separate devices and as long as the i8042 requires ISA
 access, and to be treated like an ISA device, we should glue it onto the
 virtual ISA bus within QEMU.
 
 What you did above is making the exact same mistake as is done with the
 current i440fx.c code.
 
 If a real life 440fx has an i8042, then an emulated 440fx should
 have an emulated i8042.  It's not complicated.
 
Correct. But it can be achieved by making 440fx a class that includes
other classes or by building it from different classes linked through
common interfaces.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 10:48 AM, Gleb Natapov wrote:

They *aren't* ISA devices.  Look at the PIIX3 spec.  All of the
ports for these devices are positively decoded and not sent over the
ISA bus.

 

Over the external ISA bus you mean?
   


There is no internal ISA bus.  The reality is that the PIIX3 is a 
microcontroller and most of the platform devices are probably written in 
microcode.  That's certainly the case with modern SuperIO chips.


Very specifically, the PIIX3 has a white list of addresses that when it 
sees the a PCI bus transaction for those addresses, it asserts DEVSEL# 
and then routes the request to the write part of the chip to handle it.  
For unhandled transactions, it then forwards them to the ISA bus.


Regards,

Anthony Liguori

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:52 PM, Gleb Natapov wrote:

  Plus some magic glue.  You can't say it is an ISA bridge.  It's
  exactly what its spec says it is.

First thing my spec says is Bridge Between the PCI Bus and ISA Bus


It's the first item in a list of features.  Be serious.


  
 I couldn't find it in the PIIX3 spec.
  
  I couldn't find it in _any_ spec. Should we get rid of it?

  Or write a spec.

It will not make it part of any existing system.



That is not a requirement.  We have virtio as well.

When we do have a spec for something, we should implement it as the spec 
says, not according to our ideas of how it should be.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 10:51 AM, Jes Sorensen wrote:

On 11/24/10 17:47, Avi Kivity wrote:
   

On 11/24/2010 06:40 PM, Jes Sorensen wrote:
 

Well the problem here is that the i8042 is in the i440fx.c file, it
shouldn't be there in the first place. The gluing together things in
silicon is really just a way to shorten the wires and make it easier,
they are still separate devices and as long as the i8042 requires ISA
access, and to be treated like an ISA device, we should glue it onto the
virtual ISA bus within QEMU.

What you did above is making the exact same mistake as is done with the
current i440fx.c code.
   

If a real life 440fx has an i8042, then an emulated 440fx should have an
emulated i8042.  It's not complicated.
 

It's a question of how it is accessed, if it is treated like an ISA
device by the silicon, we should treat it like an ISA device in QEMU,
rather than pretend it is something that it isn't.
   


Does anyone have any evidence that the i8042 has anything to do with the 
ISA bus at all other than the fact that people have some weird notion in 
their head that if a pio/mmio operation isn't for a PCI device, it must 
be ISA?


Regards,

Anthony Liguori
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:51 PM, Jes Sorensen wrote:

On 11/24/10 17:47, Avi Kivity wrote:
  On 11/24/2010 06:40 PM, Jes Sorensen wrote:
  Well the problem here is that the i8042 is in the i440fx.c file, it
  shouldn't be there in the first place. The gluing together things in
  silicon is really just a way to shorten the wires and make it easier,
  they are still separate devices and as long as the i8042 requires ISA
  access, and to be treated like an ISA device, we should glue it onto the
  virtual ISA bus within QEMU.

  What you did above is making the exact same mistake as is done with the
  current i440fx.c code.

  If a real life 440fx has an i8042, then an emulated 440fx should have an
  emulated i8042.  It's not complicated.

It's a question of how it is accessed, if it is treated like an ISA
device by the silicon, we should treat it like an ISA device in QEMU,
rather than pretend it is something that it isn't.


No one is saying it shouldn't be an ISA device if that's how PIIX3 
treats it.  But if PIIX3 contains it, then the code that emulates PIIX3 
should contain the code that emulates i8042.



 So whereas we have this very complicate machine create function that
 attempts to create and composite all of these devices after the
 fact, when written in C++, partially due to good design, but
 partially due to the fact that the languages forces you to think a
 certain way, you get a tremendous simplification.

  That is clearly dependent on the eyes of the person who looks at it.

  It's independent of language.  It should be done in C as well.  C++ just
  makes it easier by reducing the boilerplate.

Right we need good design for our C code, which we are lacking to a
large extend. However that has nothing to do with the language, that has
to do with the developers.


I'm sure patches will be welcome.

C++ doesn't enforce good design.  But it allows a good design to be 
enforced.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:55 PM, Gleb Natapov wrote:

  
  What you did above is making the exact same mistake as is done with the
  current i440fx.c code.

  If a real life 440fx has an i8042, then an emulated 440fx should
  have an emulated i8042.  It's not complicated.

Correct. But it can be achieved by making 440fx a class that includes
other classes or by building it from different classes linked through
common interfaces.


Both are fine, and not in conflict with the example that started this.

If the i8042 is completely stock, we write

class i440fx {
private:
i8042 kbc;
}

(or the C equivalent)

If it's not completely stock, we substitute some subclass that takes 
care of the differences.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 06:56:52PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:52 PM, Gleb Natapov wrote:
   Plus some magic glue.  You can't say it is an ISA bridge.  It's
   exactly what its spec says it is.
 
 First thing my spec says is Bridge Between the PCI Bus and ISA Bus
 
 It's the first item in a list of features.  Be serious.
 
I am serious. The fact that it provides IDE or kbd doesn't make this IDE
or kbd special. It means that it has gates that provide functionality of
those chips. Just like SoC really. IDE doesn't become part of ARM cpu
just because some SoC somewhere include them on the same silicon.

   
  I couldn't find it in the PIIX3 spec.
   
   I couldn't find it in _any_ spec. Should we get rid of it?
 
   Or write a spec.
 
 It will not make it part of any existing system.
 
 
 That is not a requirement.  We have virtio as well.
 
 When we do have a spec for something, we should implement it as the
 spec says, not according to our ideas of how it should be.
 
PIIX3 is composite device. It is not one device. To emulate it you need
to provide functionality of all devices included om PIIX3. Spec says
nothing about how it should be implemented. 

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 17:53, Anthony Liguori wrote:
 On 11/24/2010 10:40 AM, Jes Sorensen wrote: 
 Well the problem is the 10% you are talking about is another 30% loss
 because the code is now practically unreadable, plus you open up the can
 of worms that people will start using some of the totally broken
 features of C++.
 
 Did you look at my code or Avi's code?

Yes I looked at Avi's patch before commenting, it is unreadable! I have
no clue what is going on in that code. Random use of :: and bleh which
makes no sense whatsoever.

 Look at my code and then tell me it's practically unreadable.
 
 http://git.qemu.org/qemupp.git/tree/test/test-mc146818a.cpp

Looked at that, and there is nothing in that file that couldn't been
done just as cleanly in pure C.

   Sure you can try hard to make sure they don't sneak in,
 but down the line they will, and at that point the codebase is totally
 ruined.

 Avi's unittest code is a perfect example of code that is unreadable for
 a C programmer. Or to quote a smart man 'the code is clear as perl!'.
 So you have now lost or at least crippled half your developer base,
 making it way harder for them to contribute something useful.

 This is a big step in the wrong direction :( 
 
 I wouldn't have written the unittest code to use classes or exceptions
 at all.  I don't think it's a good fit.

I don't see qemupp being a good fit either :(

Jes
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 10:56:15AM -0600, Anthony Liguori wrote:
 On 11/24/2010 10:48 AM, Gleb Natapov wrote:
 They *aren't* ISA devices.  Look at the PIIX3 spec.  All of the
 ports for these devices are positively decoded and not sent over the
 ISA bus.
 
 Over the external ISA bus you mean?
 
 There is no internal ISA bus.  The reality is that the PIIX3 is a
 microcontroller and most of the platform devices are probably
 written in microcode.  That's certainly the case with modern SuperIO
 chips.
 
Qemu also does not have ISA bus. It has code that emulates ISA bus. It
is not important how legacy functionality is implemented as long as it
is compliant to legacy specification.

 Very specifically, the PIIX3 has a white list of addresses that when
 it sees the a PCI bus transaction for those addresses, it asserts
 DEVSEL# and then routes the request to the write part of the chip to
 handle it.  For unhandled transactions, it then forwards them to the
 ISA bus.
 
Yeah. In other words it serves some ISA transactions internally and
others forward to external bus.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 17:59, Avi Kivity wrote:
 On 11/24/2010 06:51 PM, Jes Sorensen wrote:
 Right we need good design for our C code, which we are lacking to a
 large extend. However that has nothing to do with the language, that has
 to do with the developers.
 
 I'm sure patches will be welcome.
 
 C++ doesn't enforce good design.  But it allows a good design to be
 enforced.

Sorry but that is utterly and completely bogus! The enforcement is only
as good as the developers and maintainers make it, and C++ has more
trapdoors than C has ever had. Sure you can shoot yourself in the foot
in C, in C++ you take the whole leg off instead.

Jes


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:02 PM, Gleb Natapov wrote:

On Wed, Nov 24, 2010 at 06:56:52PM +0200, Avi Kivity wrote:
  On 11/24/2010 06:52 PM, Gleb Natapov wrote:
 Plus some magic glue.  You can't say it is an ISA bridge.  It's
 exactly what its spec says it is.
  
  First thing my spec says is Bridge Between the PCI Bus and ISA Bus

  It's the first item in a list of features.  Be serious.

I am serious. The fact that it provides IDE or kbd doesn't make this IDE
or kbd special. It means that it has gates that provide functionality of
those chips. Just like SoC really. IDE doesn't become part of ARM cpu
just because some SoC somewhere include them on the same silicon.


They aren't special.  They're just part of the PIIX3 device.


  When we do have a spec for something, we should implement it as the
  spec says, not according to our ideas of how it should be.

PIIX3 is composite device. It is not one device. To emulate it you need
to provide functionality of all devices included om PIIX3. Spec says
nothing about how it should be implemented.


Right, we could (and probably should) implement it as

  class PIIX3 {
  private:
  class isa_bridge {  };
  isa_bridge isa_bridge;
  i8042 kbc;
  ...
  }

So the thing becomes just a glue layer for various components.  But when 
pc.c says PIIX3, it gets what the spec says, not something else.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 18:07, Avi Kivity wrote:
 On 11/24/2010 07:02 PM, Gleb Natapov wrote:
 On Wed, Nov 24, 2010 at 06:56:52PM +0200, Avi Kivity wrote:
   On 11/24/2010 06:52 PM, Gleb Natapov wrote:
  Plus some magic glue.  You can't say it is an ISA bridge.  It's
  exactly what its spec says it is.
   
   First thing my spec says is Bridge Between the PCI Bus and ISA Bus
 
   It's the first item in a list of features.  Be serious.
 
 I am serious. The fact that it provides IDE or kbd doesn't make this IDE
 or kbd special. It means that it has gates that provide functionality of
 those chips. Just like SoC really. IDE doesn't become part of ARM cpu
 just because some SoC somewhere include them on the same silicon.
 
 They aren't special.  They're just part of the PIIX3 device.

No, it is the other way round, the PIIX3 device is a glue together of
these different devices.

Jes
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:06 PM, Jes Sorensen wrote:

On 11/24/10 17:59, Avi Kivity wrote:
  On 11/24/2010 06:51 PM, Jes Sorensen wrote:
  Right we need good design for our C code, which we are lacking to a
  large extend. However that has nothing to do with the language, that has
  to do with the developers.

  I'm sure patches will be welcome.

  C++ doesn't enforce good design.  But it allows a good design to be
  enforced.

Sorry but that is utterly and completely bogus! The enforcement is only
as good as the developers and maintainers make it,


  class File {
  public:
  virtual ~File() {}
  virtual void read(...) = 0;
  virtual void write(...) = 0;
  };

Anyone wishing to implement this interface is forced to implement read 
and write methods (callbacks) with exactly the right signature.  The 
compiler will complain if they don't.  So if File is a good interface, 
we can make the compiler force people to use it correctly.


We can emulate this in C with -ops- things, but that's just 
boilerplate and more places for people to get things wrong, or lazy and 
take shortcuts.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:10 PM, Jes Sorensen wrote:

On 11/24/10 18:07, Avi Kivity wrote:
  On 11/24/2010 07:02 PM, Gleb Natapov wrote:
  On Wed, Nov 24, 2010 at 06:56:52PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:52 PM, Gleb Natapov wrote:
 Plus some magic glue.  You can't say it is an ISA bridge.  It's
 exactly what its spec says it is.
 
 First thing my spec says is Bridge Between the PCI Bus and ISA Bus
  
 It's the first item in a list of features.  Be serious.
  
  I am serious. The fact that it provides IDE or kbd doesn't make this IDE
  or kbd special. It means that it has gates that provide functionality of
  those chips. Just like SoC really. IDE doesn't become part of ARM cpu
  just because some SoC somewhere include them on the same silicon.

  They aren't special.  They're just part of the PIIX3 device.

No, it is the other way round, the PIIX3 device is a glue together of
these different devices.


That's exactly what I'm saying.  PIIX3 contains all those devices.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 11:07 AM, Avi Kivity wrote:

On 11/24/2010 07:02 PM, Gleb Natapov wrote:

On Wed, Nov 24, 2010 at 06:56:52PM +0200, Avi Kivity wrote:
  On 11/24/2010 06:52 PM, Gleb Natapov wrote:
Plus some magic glue.  You can't say it is an ISA bridge.  It's
exactly what its spec says it is.
 
 First thing my spec says is Bridge Between the PCI Bus and ISA Bus

  It's the first item in a list of features.  Be serious.

I am serious. The fact that it provides IDE or kbd doesn't make this IDE
or kbd special. It means that it has gates that provide functionality of
those chips. Just like SoC really. IDE doesn't become part of ARM cpu
just because some SoC somewhere include them on the same silicon.


They aren't special.  They're just part of the PIIX3 device.


So based on the IRC discussion that pbrook and I have been having, you 
can think of things like this:


class PIIX3 {
public:
   PlugI8042 i8042;
};

A plug allows conditional composition whereas the absence of a plug 
means unconditional composition.  There is a mechanism to name plugs and 
you can have an i8042 factory to create the device and then 
conditionally attach it to the plug.


This is fine even though I think it's unnecessary abstraction.  What I 
object to is introducing an artificial ISA bus layering.


A PlugType is basically a Type * except it has some additional 
features.  It provides null-pointer dereference checking, provides a 
marshalling interface, and supports the ability to be locked which 
enables a device to enforce that plugging cannot happen after the device 
is realized (power-on).



  When we do have a spec for something, we should implement it as the
  spec says, not according to our ideas of how it should be.

PIIX3 is composite device. It is not one device. To emulate it you need
to provide functionality of all devices included om PIIX3. Spec says
nothing about how it should be implemented.


Right, we could (and probably should) implement it as

  class PIIX3 {
  private:
  class isa_bridge {  };
  isa_bridge isa_bridge;


No, PIIX3 is an PCI-to-ISA bridge.

It's a fundamental part of the definition of it as a PCI device.

Regards,

Anthony Liguori


  i8042 kbc;
  ...
  }

So the thing becomes just a glue layer for various components.  But 
when pc.c says PIIX3, it gets what the spec says, not something else.




--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 07:01:00PM +0200, Avi Kivity wrote:
 On 11/24/2010 06:55 PM, Gleb Natapov wrote:
   
   What you did above is making the exact same mistake as is done with the
   current i440fx.c code.
 
   If a real life 440fx has an i8042, then an emulated 440fx should
   have an emulated i8042.  It's not complicated.
 
 Correct. But it can be achieved by making 440fx a class that includes
 other classes or by building it from different classes linked through
 common interfaces.
 
 Both are fine, and not in conflict with the example that started this.
 
 If the i8042 is completely stock, we write
 
 class i440fx {
 private:
 i8042 kbc;
 }
 
 (or the C equivalent)
 
 If it's not completely stock, we substitute some subclass that takes
 care of the differences.
 
And if you want to connect ISA sound blaster to that you make subclass
with SB device? No. You make ISA bus functionality available from i440fx
and connect SB there. So now you have bunch of devices that are part of
i440fx class and others that are connected via ISA bus functionality and
all that because you read to deeply into PIIX3 spec?
 
--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 18:11, Avi Kivity wrote:
 On 11/24/2010 07:06 PM, Jes Sorensen wrote:
 Sorry but that is utterly and completely bogus! The enforcement is only
 as good as the developers and maintainers make it,
 
   class File {
   public:
   virtual ~File() {}
   virtual void read(...) = 0;
   virtual void write(...) = 0;
   };
 
 Anyone wishing to implement this interface is forced to implement read
 and write methods (callbacks) with exactly the right signature.  The
 compiler will complain if they don't.  So if File is a good interface,
 we can make the compiler force people to use it correctly.
 
 We can emulate this in C with -ops- things, but that's just
 boilerplate and more places for people to get things wrong, or lazy and
 take shortcuts.

In the mean time we spend our time debugging the runtime because the
virtual functions don't behave as expected. In C we know what is going
on, in C++ it is pray and hope.

Jes
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:17 PM, Jes Sorensen wrote:


  Anyone wishing to implement this interface is forced to implement read
  and write methods (callbacks) with exactly the right signature.  The
  compiler will complain if they don't.  So if File is a good interface,
  we can make the compiler force people to use it correctly.

  We can emulate this in C with -ops-  things, but that's just
  boilerplate and more places for people to get things wrong, or lazy and
  take shortcuts.

In the mean time we spend our time debugging the runtime because the
virtual functions don't behave as expected. In C we know what is going
on, in C++ it is pray and hope.


That is pure bullshit.  All major browsers are written in C++, all major 
office suites, one leading free desktop, google, countless other 
projects.  There is a lot more C++ code in the world than C code.  If 
virtual functions didn't behave as expected, surely we'd hear by now.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:16 PM, Gleb Natapov wrote:


  If the i8042 is completely stock, we write

  class i440fx {
  private:
  i8042 kbc;
  }

  (or the C equivalent)

  If it's not completely stock, we substitute some subclass that takes
  care of the differences.

And if you want to connect ISA sound blaster to that you make subclass
with SB device? No. You make ISA bus functionality available from i440fx
and connect SB there.


Correct.  A PIIX3 doesn't contain an SB device.


  So now you have bunch of devices that are part of
i440fx class and others that are connected via ISA bus functionality and
all that because you read to deeply into PIIX3 spec?


Yes.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 11:17 AM, Jes Sorensen wrote:

On 11/24/10 18:11, Avi Kivity wrote:
   

On 11/24/2010 07:06 PM, Jes Sorensen wrote:
 

Sorry but that is utterly and completely bogus! The enforcement is only
as good as the developers and maintainers make it,
   

   class File {
   public:
   virtual ~File() {}
   virtual void read(...) = 0;
   virtual void write(...) = 0;
   };

Anyone wishing to implement this interface is forced to implement read
and write methods (callbacks) with exactly the right signature.  The
compiler will complain if they don't.  So if File is a good interface,
we can make the compiler force people to use it correctly.

We can emulate this in C with -ops-  things, but that's just
boilerplate and more places for people to get things wrong, or lazy and
take shortcuts.
 

In the mean time we spend our time debugging the runtime because the
virtual functions don't behave as expected. In C we know what is going
on, in C++ it is pray and hope.
   


The alternative in C is:

struct file_operations {
   void (*release)(void);
   void (*read)(...);
   void (*write)(...);
};

struct file {
  struct file_operations *ops;
};

If I do:

static file_operations posix_file_ops = {
  .read = posix_file_read,
  .write = posix_file_write,
};

struct posix_file {
  struct file parent;
  int fd;
};

void posix_file_init(struct posix_file *obj)
{
obj-parent.ops = posix_file_ops;
obj-fd = ...;
};

The compiler won't generate an error.  Only upon a call to 
file_release() will a null pointer dereference happens whereas in C++, 
because this paradigm is structured in the language, the compiler can 
help assist you.


Regards,

Anthony Liguori


Jes
   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 18:25, Avi Kivity wrote:
 On 11/24/2010 07:17 PM, Jes Sorensen wrote:
 In the mean time we spend our time debugging the runtime because the
 virtual functions don't behave as expected. In C we know what is going
 on, in C++ it is pray and hope.
 
 That is pure bullshit.  All major browsers are written in C++, all major
 office suites, one leading free desktop, google, countless other
 projects.  There is a lot more C++ code in the world than C code.  If
 virtual functions didn't behave as expected, surely we'd hear by now.

And those office suites and web browsers all work s well :(

Jes
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 06:57 PM, Anthony Liguori wrote:

It's a question of how it is accessed, if it is treated like an ISA
device by the silicon, we should treat it like an ISA device in QEMU,
rather than pretend it is something that it isn't.


Does anyone have any evidence that the i8042 has anything to do with 
the ISA bus at all other than the fact that people have some weird 
notion in their head that if a pio/mmio operation isn't for a PCI 
device, it must be ISA?




It cannot be an ISA device since ISA does not provide a way to assert IRQ1.

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:28 PM, Jes Sorensen wrote:

On 11/24/10 18:25, Avi Kivity wrote:
  On 11/24/2010 07:17 PM, Jes Sorensen wrote:
  In the mean time we spend our time debugging the runtime because the
  virtual functions don't behave as expected. In C we know what is going
  on, in C++ it is pray and hope.

  That is pure bullshit.  All major browsers are written in C++, all major
  office suites, one leading free desktop, google, countless other
  projects.  There is a lot more C++ code in the world than C code.  If
  virtual functions didn't behave as expected, surely we'd hear by now.

And those office suites and web browsers all work s well :(


Let's see the C alternatives.  Anyone for elinks?

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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 10:40:05AM -0600, Anthony Liguori wrote:
 On 11/24/2010 10:12 AM, Gleb Natapov wrote:
 
 Why would we specify a PIIX3 device based on a configuration file?
 There is only one PIIX3 device in the world.  I don't see a lot of
 need to create arbitrary types of devices.
 
 Why deny this flexibility from those who need it for modelling
 different HW? Besides, as I said, PIIX3 is ISA bridge and this
 is what class should implement. We have fw_cfg on ISA bus too
 which does not exits on real HW and we may want to have other
 devices. We should be able to add them without changing PIIX3
 class.
 
 Because this flexibility is a misfeature.  It's something that noone
 actually uses and I've never seen anyone ask to have.
 
 It introduces a PC-centric view of the world where you artificially
 make a bunch of devices have bus specific logic that they really
 don't have.
 
Actually other way around. Non PC embedded systems are those that needs
this flexibility the most.


 If you want to go down this route, the right approach to take is to
 make a separate IsaMc161818a device that has a Mc16818a device with
 a has-a relation (i.e. composition).
There are many devices in qemu that accessed via isa bus on PCI and via
MMIO in other archs, so the thing you propose here is logical and
actually implemented this way in qdev.

 
 But I don't see the point.  Just stick the Mc16818a device in the
 PIIX3 via composition as it exists on normal hardware and call it a
 day.
Shortcuts, shortcuts. I think this is how qemu was written initially. 
Lets put this here and call it a day!

 
 BTW, the only reason any of this works is because of the fact that
 the PIIX3 does subtractive decoding which allows arbitrary ISA
 devices to be plugged into the ISA bus.  But subtractive decoding is
 very expensive and on modern LPC implementations, positive decoding
 is used which means that the chipset has a white list of ports for
 devices that sit on it.
 
 PCs are simply not as architecturally clean as I think you're
 advocating we try to model them.
 
 The real world hierarchy matters when you're trying to model I/O dispatch.
 
 Or build device path. Any time we do something not as real HW we
 regret it later.
 
 Right, and real HW does composition in the PIIX3 device.  So let's
 not regret making everything an ISA device later.
 
You design by packaging not functionality?

 An RTC is *not* an ISA device.  It may sit *behind* an ISA bus
 because the SuperIO chip happens to be on the ISA bus.  But on
 modern systems, the ISA bus has disappeared in favor of the LPC but
 that doesn't fundamentally change what the RTC is.
 Agree. This is a device sitting on the ISA bus on a PC, but it can
 sit on other buses too. And it happily does so on other architectures.
 
 It doesn't sit on the ISA bus.  A SuperIO chip sits on the ISA bus
 and the SuperIO chip decodes the ISA bus traffic and dispatches
 approriately.
 
 On the PIIX3, the SuperIO chip is part of the chipset.  An ISA
 transaction isn't necessary to talk to the RTC--it would simply be
 too expensive to do this because of subtractive decoding.
 
You are talking about internal chip implementation. I am talking about
functionality. Qemu also doesn't exactly has ISA bus inside.

 The problem with what you describe is that there are far fewer
 devices that actually sit on busses than what QEMU tries to model
 today.
 All devices sit on some buses.
 
 That's simply not true.  Let's be specific about what a bus is.  A
 bus is a set of lines that is shared by multiple devices with some
 mechanism to arbitrate who's using the bus at any given time.  In
 PCI, roughly speaking, a transaction is sent from the controller to
 all devices on the bus and the device that is to handle the
 transaction will raise it's DEVSEL line to indicate that it's
 handling it.
 
 But there are plenty of cases where a device is hard wired to
 another device.  In a simple microcontroller, it's extremely common
 to tie a set of GPIO pins to a specific device.  There's no bus
 here.
Agree. We could call thous GPIO pins ad-hoc bus too. But I see you
point.

 
 The i8042 is another good example.  The i8042 has two ps2 plugs but
 it's not a bus.  The keyboard port takes a keyboard and the aux port
 takes a mouse.  You can't hook up two keyboards and you can't hook
 up two mice.
 
 Because I don't think we can implement a reasonable device model
 using a garbage collected language.  Garbage collection introduces
 non-determinism and in QEMU we need to ensure that when we're
 running in a VCPU context, we exit back to the guest as quickly as
 possible.
 
 IIRC there are garbage collected languages that allow you to disable garbage
 collection for certain part of the code.
 
 Yeah, but very few languages that I know of are sophisticated here.
 
   Garbage collection can be done
 while vcpu executes guest code and in proper implementation vcpu thread
 should execute device model code for a very brief time and 

Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:27 PM, Anthony Liguori wrote:


The alternative in C is:

struct file_operations {
   void (*release)(void);
   void (*read)(...);
   void (*write)(...);
};

struct file {
  struct file_operations *ops;
};

If I do:

static file_operations posix_file_ops = {
  .read = posix_file_read,
  .write = posix_file_write,
};

struct posix_file {
  struct file parent;
  int fd;
};

void posix_file_init(struct posix_file *obj)
{
obj-parent.ops = posix_file_ops;
obj-fd = ...;
};

The compiler won't generate an error.  Only upon a call to 
file_release() will a null pointer dereference happens whereas in C++, 
because this paradigm is structured in the language, the compiler can 
help assist you.


You forgot to mention:

  static void posix_file_read(struct file *_file, ...)
  {
   struct posix_file *file = container_of(_file, struct posix_file, 
parent);


   ...
  }

Even more boilerplate and potential for error.  But I think the worst 
thing about this is that it makes it hard to do the right thing, so 
people hack quick and dirty workarounds.  C++ makes this pattern trivial 
(if : laden), so people are encouraged to use it.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 07:25:08PM +0200, Avi Kivity wrote:
 On 11/24/2010 07:17 PM, Jes Sorensen wrote:
 
   Anyone wishing to implement this interface is forced to implement read
   and write methods (callbacks) with exactly the right signature.  The
   compiler will complain if they don't.  So if File is a good interface,
   we can make the compiler force people to use it correctly.
 
   We can emulate this in C with -ops-  things, but that's just
   boilerplate and more places for people to get things wrong, or lazy and
   take shortcuts.
 
 In the mean time we spend our time debugging the runtime because the
 virtual functions don't behave as expected. In C we know what is going
 on, in C++ it is pray and hope.
 
 That is pure bullshit.  All major browsers are written in C++, all
 major office suites, one leading free desktop, google, countless
 other projects.  There is a lot more C++ code in the world than C
 code.  If virtual functions didn't behave as expected, surely we'd
 hear by now.
 
Google don't use exceptions though :) They claim it is hard to integrate
with legacy code if exceptions are used. Our case BTW.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 18:27, Anthony Liguori wrote:

 The compiler won't generate an error.  Only upon a call to
 file_release() will a null pointer dereference happens whereas in C++,
 because this paradigm is structured in the language, the compiler can
 help assist you.

Explicit code means you know what is going on, it means you can debug it
in gdb and match it. That is a *good* thing!

Jes

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:33 PM, Gleb Natapov wrote:


  But I don't see the point.  If you look at my repository, there's
The point is that C++ is ugly language. The short code Avi sent remind
me perl (aka line noise). It is almost impossible to parse it into
what code it actually does. Most symbols are there for C++ syntax not
functionality.


No.  They're there for error handling.  A C++ wrapper, doesn't add any 
functionality, so you can say that all of the lines of codes do nothing 
and are just syntax.  But they do allow you to pair init and uninit (in 
the constructor and destructor).  When you use the wrapper (as opposed 
to the bare C interface) you get the value by not having to code long 
error handling sequences (with a high probability of getting them wrong 
and never finding out in testing).


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 07:39:39PM +0200, Avi Kivity wrote:
 On 11/24/2010 07:33 PM, Gleb Natapov wrote:
 
   But I don't see the point.  If you look at my repository, there's
 The point is that C++ is ugly language. The short code Avi sent remind
 me perl (aka line noise). It is almost impossible to parse it into
 what code it actually does. Most symbols are there for C++ syntax not
 functionality.
 
 No.  They're there for error handling.  A C++ wrapper, doesn't add
 any functionality, so you can say that all of the lines of codes do
 nothing and are just syntax.  But they do allow you to pair init and
 uninit (in the constructor and destructor).  When you use the
 wrapper (as opposed to the bare C interface) you get the value by
 not having to code long error handling sequences (with a high
 probability of getting them wrong and never finding out in testing).
 
So how errors are handled there? By throwing exceptions? Sorry this is
not error handling.

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Avi Kivity

On 11/24/2010 07:36 PM, Jes Sorensen wrote:

On 11/24/10 18:27, Anthony Liguori wrote:

  The compiler won't generate an error.  Only upon a call to
  file_release() will a null pointer dereference happens whereas in C++,
  because this paradigm is structured in the language, the compiler can
  help assist you.

Explicit code means you know what is going on, it means you can debug it
in gdb and match it. That is a *good* thing!


Implicit code means that you don't need to debug it.  The compiler gets 
it right every time.


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

--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Gleb Natapov
On Wed, Nov 24, 2010 at 07:41:48PM +0200, Avi Kivity wrote:
 On 11/24/2010 07:36 PM, Jes Sorensen wrote:
 On 11/24/10 18:27, Anthony Liguori wrote:
 
   The compiler won't generate an error.  Only upon a call to
   file_release() will a null pointer dereference happens whereas in C++,
   because this paradigm is structured in the language, the compiler can
   help assist you.
 
 Explicit code means you know what is going on, it means you can debug it
 in gdb and match it. That is a *good* thing!
 
 Implicit code means that you don't need to debug it.  The compiler
 gets it right every time.
 
Best joke ever!

--
Gleb.
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 18:41, Avi Kivity wrote:
 On 11/24/2010 07:36 PM, Jes Sorensen wrote:
 On 11/24/10 18:27, Anthony Liguori wrote:

   The compiler won't generate an error.  Only upon a call to
   file_release() will a null pointer dereference happens whereas in C++,
   because this paradigm is structured in the language, the compiler can
   help assist you.

 Explicit code means you know what is going on, it means you can debug it
 in gdb and match it. That is a *good* thing!
 
 Implicit code means that you don't need to debug it.  The compiler gets
 it right every time.

Except when it doesn't, or when you don't know why something happened
and you ended up where you did

Jes
--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Anthony Liguori

On 11/24/2010 11:36 AM, Jes Sorensen wrote:

On 11/24/10 18:27, Anthony Liguori wrote:

   

The compiler won't generate an error.  Only upon a call to
file_release() will a null pointer dereference happens whereas in C++,
because this paradigm is structured in the language, the compiler can
help assist you.
 

Explicit code means you know what is going on, it means you can debug it
in gdb and match it. That is a *good* thing!
   


So I take it you avoid switch statements, while, or for loops in your C 
code.


Regards,

Anthony Liguori


Jes

   


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

2010-11-24 Thread Jes Sorensen
On 11/24/10 18:43, Anthony Liguori wrote:
 On 11/24/2010 11:36 AM, Jes Sorensen wrote:
 On 11/24/10 18:27, Anthony Liguori wrote:

   
 The compiler won't generate an error.  Only upon a call to
 file_release() will a null pointer dereference happens whereas in C++,
 because this paradigm is structured in the language, the compiler can
 help assist you.
  
 Explicit code means you know what is going on, it means you can debug it
 in gdb and match it. That is a *good* thing!

 
 So I take it you avoid switch statements, while, or for loops in your C
 code.

Those map easily to assembly code and gdb.

Jes


--
To unsubscribe from this list: send the line unsubscribe kvm in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >