From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:50067) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QlmKr-0001LQ-5x for qemu-devel@nongnu.org; Tue, 26 Jul 2011 14:26:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QlmKm-0002QX-0r for qemu-devel@nongnu.org; Tue, 26 Jul 2011 14:26:29 -0400 Received: from mail-gx0-f173.google.com ([209.85.161.173]:47879) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QlmKl-0002QN-RK for qemu-devel@nongnu.org; Tue, 26 Jul 2011 14:26:23 -0400 Received: by gxk26 with SMTP id 26so558313gxk.4 for ; Tue, 26 Jul 2011 11:26:23 -0700 (PDT) Sender: Paolo Bonzini Message-ID: <4E2F06C8.30403@redhat.com> Date: Tue, 26 Jul 2011 20:26:16 +0200 From: Paolo Bonzini MIME-Version: 1.0 References: <1311558293-5855-1-git-send-email-aliguori@us.ibm.com> <4E2EBA1E.90006@redhat.com> <4E2EC90E.8090409@codemonkey.ws> <4E2ED0AA.3020101@redhat.com> <4E2EDE86.7020807@codemonkey.ws> In-Reply-To: <4E2EDE86.7020807@codemonkey.ws> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [RFC][PATCH 0/21] QEMU Object Model List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Anthony Liguori Cc: Peter Maydell , qemu-devel@nongnu.org On 07/26/2011 05:34 PM, Anthony Liguori wrote: >> And as such it can add data members. But when a device is on two buses, >> you cannot have both of them adding data members. I know MI is hard to >> get right, and in fact I'm not proposing to do MI---not even interface >> inheritance. I don't want to have any base class but DeviceState. > > I could use a concrete example here, but here's how this would be > expressed: > > class MyWeirdDevice : public MyBaseDevice, implements PciDevice, IsaDevice > { > PciBus *pci_bus; > IsaDevice *isa_bus; > }; > > Which actually models hw pretty well. A device that exists on two busses > has to have two sockets that can accept the plugs from the busses > they're joining. > > It's pretty much exactly how it works in real life. You could just as well say that real life works like this: class PciSocket { PciBus *pci_bus; uint8_t *config; uint8_t *cmask; uint8_t *wmask; uint8_t *w1cmask; uint8_t *used; uint32_t devfn; char name[64]; PCIIORegion io_regions[PCI_NUM_REGIONS]; ... }; class IsaSocket { IsaBus *isa_bus; uint32_t isairq[2]; // not sure this is a good idea, just int nirqs; // mimicking qdev uint16_t ioports[32];// statically assigned unlike PCI bars int nioports; } class MyWeirdDevice : public MyBaseDevice { PciSocket pci; IsaSocket isa; }; >> Yes, this is pretty much what I had imagined. But it does not scale to a >> topology where you have two parents, both of which want to add data >> members. > > Which would be true MI. The problem with true MI is that you'll end up > with a diamond if you try to have anything useful (like properties) in > the base. See above for how you would avoid that. >>>> 1) in a flexible manner, so that it can express complex topologies (as >>>> long as "plugs" and "sockets" have the same shape of course); >>> >>> Right, this is what we do today in QOM. Plugs and Sockets are typed. >>> Those types can be interfaces or base classes so there's a lot of >>> flexibility. >> >> Interfaces (is-a) are less flexible than embedded objects (has-a). > > It depends on what you're trying to model I guess. In some cases where > the interface is more or less stateless or that state isn't common among > implementations, interfaces are quite nice. Yes, I'm not sure this is the case here. :) > > Same as IDE when you used to set >> jumpers to choose master/slave. Or ISA interrupt lines. > > The ISA dip switches literally select which line of the bus gets routed > to the device. All devices have access to all interrupt lines through > the bus. > > So when modelling, it makes sense to have the irq be a property of the > device and then to have the bus interface expose the irqs. For instance: > > struct IsaBusClass > { > void (*set_irq_level)(IsaBus *bus, int irq, bool level); > }; Agreed. Though I'm not sure that the same is true for all fields in qemu's current PCIDevice. >> Once you have something like this for a device that bridges two buses, >> interfaces require a lot of boilerplate for useless getters/setters. > > Can you elaborate? If you store data (configuration space etc.) in the device, and the bus has to access it, you need getters/setters in the interface. Letting the bus hold an interior reference to the PciSocket (perhaps adding a single get_device_for_socket function to the PciSocketOps) solves the problem. >>> The same applies equally to IDE. >>> >>> ide->primary.master = disk1; >>> ide->secondary.master = cdrom; >> >> For IDE, an equally good model would be: >> >> ide->primary.add(disk1); >> disk1.masterSlave = MASTER; >> ide->secondary.add(cdrom); >> cdrom.masterSlave = MASTER; > > There's a pin in the IDE cable that determines master or slave depending > on whether it's raised high. Yes, that's the "newer" way. There used to be jumpers to choose between master, slave and cable-select. > I think modelling it that way makes more sense from an end user > perspective since it prevents the possibility of have two master devices > (which is incorrect). ... but you could do that, if for some reason you wanted to model the jumper-based world. But this is a mostly irrelevant digression. >>> Interfaces are the right way to do this. Getting MI right is fairly hard >> >> But we don't need is-a, we need has-a. Multiple is-a is harder than >> single is-a. Multiple has-a does not add any complication. > > Yeah, that's what plug properties are for :-) I agree, but at the cost of pointer chasing and making it harder to implement get_device_for_socket for buses that need it (in the above sketch it can be a simple container_of). >>> I think all of the requirements you've outlined are currently handled in >>> QOM. >> >> They more than likely are. The question is whether they're handled in >> the most programmer-efficient manner, and whether the advantages of a >> single grand unified object model for host and guest devices is worth >> the effort. > > Indeed. I think that it's a no brainer for the backends and that's why > I'm starting there. I don't think it's a no brainer. It's simply much easier, but right now it is also a solution in search of a problem (if all you want is dynamic creation of character devices, you could do that without a generic object model). If starting from a blank slate, I would be much more enthusiastic. But all that QEMU does _not_ need is yet another incomplete transition. Paolo