Re: [Qemu-devel] KVM call minutes for Feb 8

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 14, 2011 at 10:53 PM, Anthony Liguori <anthony@xxxxxxxxxxxxx> wrote:
> On 02/14/2011 11:31 AM, Blue Swirl wrote:
>>
>> I don't understand. The caller just does
>> if (isa_serial_init()) {
>> Â error();
>> }
>> or
>> if (serial_init()) {
>> Â error();
>> }
>>
>> If you mean inside isa_serial_init() vs. serial_init(), that may be
>> true since isa_serial_init has to check for qdev failures, but the to
>> the caller both should be identical.
>>
>
> The problem with qdev is there's too much boiler plate code which makes it
> hard to give examples :-) ÂHere's precisely what I'm talking about:
>
> static int serial_isa_initfn(ISADevice *dev)
> {
> Â Âstatic int index;
> Â ÂISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
> Â ÂSerialState *s = &isa->state;
>
> Â Âif (isa->index == -1)
> Â Â Â Âisa->index = index;
> Â Âif (isa->index >= MAX_SERIAL_PORTS)
> Â Â Â Âreturn -1;
> Â Âif (isa->iobase == -1)
> Â Â Â Âisa->iobase = isa_serial_io[isa->index];
> Â Âif (isa->isairq == -1)
> Â Â Â Âisa->isairq = isa_serial_irq[isa->index];
> Â Âindex++;
>
> Â Âs->baudbase = 115200;
> Â Âisa_init_irq(dev, &s->irq, isa->isairq);
> Â Âserial_init_core(s);
> Â Âqdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
>
> Â Âregister_ioport_write(isa->iobase, 8, 1, serial_ioport_write, s);
> Â Âregister_ioport_read(isa->iobase, 8, 1, serial_ioport_read, s);
> Â Âisa_init_ioport_range(dev, isa->iobase, 8);
> Â Âreturn 0;
> }
>
> SerialState *serial_init(int base, qemu_irq irq, int baudbase,
> Â Â Â Â Â Â Â Â Â Â Â Â CharDriverState *chr)
> {
> Â ÂSerialState *s;
>
> Â Âs = qemu_mallocz(sizeof(SerialState));
>
> Â Âs->irq = irq;
> Â Âs->baudbase = baudbase;
> Â Âs->chr = chr;
> Â Âserial_init_core(s);
>
> Â Âvmstate_register(NULL, base, &vmstate_serial, s);
>
> Â Âregister_ioport_write(base, 8, 1, serial_ioport_write, s);
> Â Âregister_ioport_read(base, 8, 1, serial_ioport_read, s);
> Â Âreturn s;
> }
>
> static ISADeviceInfo serial_isa_info = {
> Â Â.qdev.name Â= "isa-serial",
> Â Â.qdev.size Â= sizeof(ISASerialState),
> Â Â.qdev.vmsd Â= &vmstate_isa_serial,
>  Â.init    = serial_isa_initfn,
> Â Â.qdev.props = (Property[]) {
> Â Â Â ÂDEFINE_PROP_UINT32("index", ISASerialState, index, Â -1),
> Â Â Â ÂDEFINE_PROP_HEX32("iobase", ISASerialState, iobase, Â-1),
> Â Â Â ÂDEFINE_PROP_UINT32("irq", Â ISASerialState, isairq, Â-1),
> Â Â Â ÂDEFINE_PROP_CHR("chardev", ÂISASerialState, state.chr),
> Â Â Â ÂDEFINE_PROP_END_OF_LIST(),
> Â Â},
> };
>
> static void serial_register_devices(void)
> {
> Â Âisa_qdev_register(&serial_isa_info);
> }
>
> device_init(serial_register_devices)
>
>
> To create a device, I need to do:
>
> {
> Â Â ISADevice *dev;
>
> Â Â dev = isa_create("isa-serial");
> Â Â if (dev == NULL) {
> Â Â Â Â Âreturn error;
> Â Â }
> Â Â if (qdev_set_uint32(&dev->qdev, "index", index)) {
> Â Â Â Â Âgoto err;
> Â Â }
> Â Â if (qdev_set_uint32(&dev->qdev, "iobase", iobase)) {
> Â Â Â Â Âgoto err;
> Â Â }
> Â Â if (qdev_set_uint32(&dev->qdev, "irq", irq)) {
> Â Â Â Â goto err;
> Â Â }
> Â Â if (qdev_set_chr(&dev->qdev, "chardev", chr)) {
> Â Â Â Â goto err;
> Â Â }
> Â Â if (qdev_init(&dev->qdev)) {
> Â Â Â Â goto err;
> Â Â }
> Â Â return 0;
> err:
> Â Â qdev_destroy(&dev->qdev);
> Â Â return -1;
> }
>
> This is simply not a reasonable API to use to create devices.

This can be wrapped in a static inline function, with similar
signature to what you propose:

static inline ISADevice *serial_init(int base, qemu_irq irq, int
baudbase, CharDriverState *chr);

> ÂThere are two
> ways we can make this more managable. ÂThe first is gobject-style vararg
> constructor coupled with a type safe wrapper. ÂSo...
>
> ISASerialDevice *isa_serial_device_new(uint32_t index, uint32_t iobase,
> uint32_t irq, CharDriverState *chr)
> {
> Â Â Âreturn isa_device_create_va("isa-seral", "index", index, "iobase",
> iobase, "irq", irq, "chardev", chr, NULL);
> }
>
> Now this can be used in a reasonable fashion. ÂHowever, we can do even
> better if we change the way qdev is done. Â Consider the following:
>
> SerialState *serial_init(int base, qemu_irq irq, int baudbase,
> Â Â Â Â Â Â Â Â Â Â Â Â CharDriverState *chr)
> {
> Â ÂSerialState *s;
>
> Â Âs = qemu_mallocz(sizeof(SerialState));
>
> Â Âs->irq = irq;
> Â Âs->baudbase = baudbase;
> Â Âs->chr = chr;
> Â Âserial_init_core(s);
>
> Â Âvmstate_register(NULL, base, &vmstate_serial, s);
>
> Â Âregister_ioport_write(base, 8, 1, serial_ioport_write, s);
> Â Âregister_ioport_read(base, 8, 1, serial_ioport_read, s);
> Â Âreturn s;
> }
>
> ISASerialDevice *isa_serial_new(uint32_t index, uint32_t iobase, uint32_t
> irq, CharDriverState *chr)
> {
> Â Âstatic int index;
> Â ÂISADevice *dev = isa_create("isa-serial");
> Â ÂISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
> Â ÂSerialState *s = &isa->state;
>
> Â Âif (index == -1)
> Â Â Â Âindex = index;
> Â Âif (index >= MAX_SERIAL_PORTS)
> Â Â Â Âreturn NULL;
> Â Âif (iobase == -1)
> Â Â Â Âiobase = isa_serial_io[index];
> Â Âif (isairq == -1)
> Â Â Â Âisairq = isa_serial_irq[index];
> Â Âindex++;
>
> Â Âs->baudbase = 115200;
> Â Âisa_init_irq(dev, &s->irq, isairq);
> Â Âserial_init_core(s);
> Â Âqdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
>
> Â Âregister_ioport_write(isa->iobase, 8, 1, serial_ioport_write, s);
> Â Âregister_ioport_read(isa->iobase, 8, 1, serial_ioport_read, s);
> Â Âisa_init_ioport_range(dev, isa->iobase, 8);
> Â Âreturn isa;
> }
>
> static ISADevice *isa_seral_init_qdev(QemuOpts *opts)
> {
> Â Â Âuint32_t index = qemu_opt_get_uint32(opts, "index", -1);
> Â Â Âuint32_t irq = qemu_opt_get_uint32(opts, "irq", -1);
> Â Â Âuint32_t iobase = qemu_opt_get_uint32(opts, "iobase", -1);
> Â Â ÂCharDriverState *chr = qemu_opt_get_chr(opts, "chardev");
>
> Â Â Âreturn isa_serial_new(index, irq, iobase, chr);
> }
>
> static void serial_register_devices(void)
> {
> Â Âisa_qdev_register("isa-serial", isa_serial_init_qdev);
> }
>
> device_init(serial_register_devices)
>
> The advantage of this model is that we can totally ignore the factory
> interface for devices that we don't care about exposing to the user. ÂSo the
> isa_seral_init_qdev part is totally optional.

I'd still like to have the inline wrapper over the factory interface,
probably with similar signature to isa_serial_new. Then there would be
two functions, one going through qdev and the other bypassing it. I
don't see how that would be useful.

The callers of the direct interface would force linkage between them
and so it would be impossible to build QEMU with that device. We don't
need that flexibility for every device though, but I don't see any
advantages for using the direct interface either.

Why shouldn't we want all devices to be exposed to the user? For
example, there are still devices which don't show up in 'info qtree',
which is a shame.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux