From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:44499) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QljeX-0008Mj-DU for qemu-devel@nongnu.org; Tue, 26 Jul 2011 11:34:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QljeV-0000L3-IK for qemu-devel@nongnu.org; Tue, 26 Jul 2011 11:34:37 -0400 Received: from mail-yi0-f45.google.com ([209.85.218.45]:54947) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QljeV-0000Kv-Cv for qemu-devel@nongnu.org; Tue, 26 Jul 2011 11:34:35 -0400 Received: by yia25 with SMTP id 25so399709yia.4 for ; Tue, 26 Jul 2011 08:34:34 -0700 (PDT) Message-ID: <4E2EDE86.7020807@codemonkey.ws> Date: Tue, 26 Jul 2011 10:34:30 -0500 From: Anthony Liguori 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> In-Reply-To: <4E2ED0AA.3020101@redhat.com> 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: Paolo Bonzini Cc: Peter Maydell , qemu-devel@nongnu.org On 07/26/2011 09:35 AM, Paolo Bonzini wrote: > On 07/26/2011 04:02 PM, Anthony Liguori wrote: >>> Also because there is no hierarchy, composition in host devices can be >>> done very easily. A decorator for char/block devices, such as a "tee" >>> device, can treat the wrapped object(s) the same independent of the >>> actual class. A simple vtable works very well. GObject would also do >>> well, unifying the introspection at the cost of significantly more >>> boilerplate. >> >> The polymorphism model of QOM is identical to GObject so I'm not sure >> what you mean here. > > GObject instead of QOM (just so that we have something that is already > written). > >> In the case of tee, it's just an object with two sockets. > > Yes, understood. > >> I have PCI patches, but didn't post them in the series. Here's how it >> works: >> >> The PCI host controller, the i440fx, has 32 sockets of PCIDevice. >> PCIDevice is a base class. > > 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. > >> The PCI host controller implements a PCIBus interface. The PCIDevices >> have a socket of a PCIBus >> >> Connecting a PCIDevice to the host bus involves setting the socket on >> the PCI host controller with the PCIDevice and then setting the >> PCIDevice's bus socket with the host controller. >> >> A PCIDevice can also be a PCIBus by implementing the PCIBus interface. >> This is what enables a PCI bridge to make sense in this model. >> >> If you're interested, the tree that has this is >> http://repo.or.cz/w/qemu/aliguori.git/tree/qdev2:/devices > > 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. The common solution is to have the ability to has-a implementation of the interface. >>> 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. >> There are no properties of the socket. >> >> If you look at something like adding a PCI device in qdev, you add a >> child and set properties of the child to identify how the device sits on >> the PCI bus. >> >> I'd characterize this as awkward, at best. The slot index is not a >> property of the device, it's a property of how the device is connected >> to the PCI bus. > > Yes, for a PCI address I agree. But in a (parallel) SCSI bus, the LUN is > logically a property of the device. > 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); }; I don't know enough about SCSI to know whether it makes sense to have LUN be a property of the bus or the device. If LUN negotiation is aided by the controller and fixed after startup, then I think it makes sense for there to be a fixed number of sockets in the bus and then for the bus to do LUN assignment at realize (possibly looking at each device to see what the requested LUN is). > 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? > >> i440fx->slots[3] = mydevice >> >> Likewise, if slot 4 contains a PCI-to-PCI bridge that ends up being bus >> 1, and you want to assign to bus 1, slot 2, fn 0: >> >> i440fx->slots[4]->slots[2] = myotherdevice; >> >> Now you may observe that this is awkward compared to saying "bus 1". > > No, I have no problem with that. :) > >> 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. You can think of it as a very simple MUX circuit where the pin decodes the single group of 40 wires into two distinct groups of 39 wires, each group being a different port on the bus. 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). > >>> 5) convert buses to compound properties. Rather than inheriting from >>> PCIDevice, a PCI device would inherit straight from DeviceState and >>> include a PCIDevice struct that defines the backlink from a device to >>> its parent. Note that since we're using C, this is not a big change from >>> what we're doing now! (Inheritance by containment is a special case of >>> containment.) And it allows to define very flexibly a device that would >>> have to sit on two or more buses in the current qdev model. More >>> importantly, it keeps the effectiveness of the qbus ops model, while >>> removing the constraint of a tree topology. >> >> Interfaces are the right way to do this. Getting MI right is fairly hard > > 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 :-) Making has-a work well is one of the issues I had with GObject. GObject is not very good for expressing has-a. > >> 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. Regards, Anthony Liguori > > Paolo >