All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] Error checking and qemu_thread_create
@ 2017-03-18 18:15 Anton Volkov
  2017-03-18 21:15 ` [Qemu-devel] Strange behaviour in network device initialization Marc Bommert
  0 siblings, 1 reply; 4+ messages in thread
From: Anton Volkov @ 2017-03-18 18:15 UTC (permalink / raw)
  To: qemu-devel

Hello.

I want to make qemu_thread_create return a flag as described here (http://wiki.qemu-project.org/BiteSizedTasks), but I’m not sure how callers should behave if it fails.
I could make it so they would call something like error_report() and then call abort(), but then it is almost a copy of existing behavior.
Would the described behavior be acceptable? Or it should be different?

Best regards,
Anton Volkov

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

* [Qemu-devel] Strange behaviour in network device initialization.
  2017-03-18 18:15 [Qemu-devel] Error checking and qemu_thread_create Anton Volkov
@ 2017-03-18 21:15 ` Marc Bommert
  2017-03-18 22:22   ` Peter Maydell
  0 siblings, 1 reply; 4+ messages in thread
From: Marc Bommert @ 2017-03-18 21:15 UTC (permalink / raw)
  To: qemu-devel

Hello development,

I ran into some behaviour I don't understand and which may be a qemu problem but which may also be my fault, since I haven't investigated much on QOM so far.
I am currently writing a NIC sysbus device based on the structure of hw/net/smc91c111.c

qemu is invoked as:

  $ qemu-system-arm -M mymachine -m 8 -kernel kernel.elf -nographic -net nic,id=myid -netdev tap,ifname=tap0,id=myid,script=no,downscript=no -device mydevice,netdev=myid


The initialization structure is a little special here. A "legacy helper" initialization function is called from the board module mymachine.c:

   for(n = 0; n < nb_nics; n++) {
        nd = &nd_table[n];
        
        if (!nd->model || strcmp(nd->model, "mydevice") == 0) {
            mydevice_init(nd, MYDEVICE_BASE, pic[17]);
            break;
        } else {
        /* We don't know this NIC model */
        }
    }
    
The init function is provided by the device module mydevice.c:

    /* Legacy helper function.  Should go away when machine config files are implemented.  */
    void mydevice_init(NICInfo *nd, uint32_t base, qemu_irq irq)
    {
        DeviceState *dev;
        SysBusDevice *s;
    
        qemu_check_nic_model(nd, "mydevice");
        dev = qdev_create(NULL, TYPE_MYDEVICE);
        s = SYS_BUS_DEVICE(dev);
        mydevice_state *state = MY_DEVICE(dev);
        
        qdev_set_nic_properties(dev, nd);
        qdev_init_nofail(dev);
        sysbus_mmio_map(s, 0, base);
        sysbus_connect_irq(s, 0, irq);
    }
    
and the actual class/instance initializers are:

    static int mydevice_init1(Object *obj)
    {
        DeviceState *dev = DEVICE(obj);
        mydevice_state *s = MY_DEVICE(dev);
        SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
        
        memory_region_init_io(&s->mmio, OBJECT(s), &mydevice_mem_ops, s,
                            "mydevice-mmio", 0x40000);
        sysbus_init_mmio(sbd, &s->mmio);
        sysbus_init_irq(sbd, &s->irq);
        
        qemu_macaddr_default_if_unset(&s->conf.macaddr);
        s->nic = qemu_new_nic(&net_mydevice_info, &s->conf,
                            object_get_typename(OBJECT(dev)), dev->id, s);
        qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
        mydevice_reset(s);
        return 0;
    }

    static void mydevice_class_init(ObjectClass *klass, void *data)
    {
        DeviceClass *dc = DEVICE_CLASS(klass);
        SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

        k->init = mydevice_init1;
        dc->reset = mydevice_reset;
        dc->vmsd = &vmstate_mydevice;
        dc->props = mydevice_properties;
    }

    static const TypeInfo mydevice_info = {
        .name          = TYPE_MYDEVICE,
        .parent        = TYPE_SYS_BUS_DEVICE,
        .instance_size = sizeof(mydevice_state),
        .class_init    = mydevice_class_init,
    };
    
    
Now, the actual problem is that mydevice_init1() is called twice and the device state is also instantiated twice. Thus, s->irq is initialized twice, but only the first one gets connected. During runtime, the second state instance is passed with a NULL s->irq in the device state to the memops. The IRQ never fires.

Here are the stack traces of the both initialization calls:

#0  mydevice_init1 (obj=0x5555573bb010) at /home/brightwise/qemu-2.8.0/hw/mymachine/mydevice.c:700
#1  0x0000555555a020f5 in sysbus_device_init (dev=0x5555573bb010) at hw/core/sysbus.c:211
#2  0x00005555559fae58 in device_realize (dev=0x5555573bb010, errp=0x7fffffffdbd0) at hw/core/qdev.c:213
#3  0x00005555559fc96f in device_set_realized (obj=0x5555573bb010, value=true, errp=0x7fffffffdd70) at hw/core/qdev.c:918
#4  0x0000555555bd733c in property_set_bool (obj=0x5555573bb010, v=0x5555573bdb20, name=0x5555560bd162 "realized", opaque=0x55555738eca0, errp=0x7fffffffdd70) at qom/object.c:1854
#5  0x0000555555bd5847 in object_property_set (obj=0x5555573bb010, v=0x5555573bdb20, name=0x5555560bd162 "realized", errp=0x7fffffffdd70) at qom/object.c:1088
#6  0x0000555555bd866f in object_property_set_qobject (obj=0x5555573bb010, value=0x5555573bda90, name=0x5555560bd162 "realized", errp=0x7fffffffdd70) at qom/qom-qobject.c:27
#7  0x0000555555bd5aea in object_property_set_bool (obj=0x5555573bbst ask on the mailing list for someone else to do it on your behalf (self-creation is prohibited to cut down on spam accounts).
Start with reading the QEMU wiki.
Contribute to the QEMU wiki by adding new topics or im010, value=true, name=0x5555560bd162 "realized", errp=0x7fffffffdd70) at qom/object.c:1157
#8  0x00005555559fb423 in qdev_init_nofail (dev=0x5555573bb010) at hw/core/qdev.c:358
#9  0x000055555585705e in mydevice_init (nd=0x555556b40280 <nd_table>, base=1310720, irq=0x555557334550) at /home/brightwise/qemu-2.8.0/hw/mymachine/mydevice.c:776
#10 0x000055555585459a in mymachine_init (machine=0x555557038dc0, board_id=256) at /home/brightwise/qemu-2.8.0/hw/mymachine/mymachine.c:341
#11 0x00005555558546ad in _machine_init (machine=0x555557038dc0) at /home/brightwise/qemu-2.8.0/hw/mymachine/mymachine.c:377
#12 0x000055555596ec3d in main (argc=14, argv=0x7fffffffe358, envp=0x7fffffffe3d0) at vl.c:4548

and 

#0  mydevice_init1 (obj=0x5555573eaea0) at /home/brightwise/qemu-2.8.0/hw/mymachine/mydevice.c:700
#1  0x0000555555a020f5 in sysbus_device_init (dev=0x5555573eaea0) at hw/core/sysbus.c:211
#2  0x00005555559fae58 in device_realize (dev=0x5555573eaea0, errp=0x7fffffffdcf0) at hw/core/qdev.c:213
#3  0x00005555559fc96f in device_set_realized (obj=0x5555573eaea0, value=true, errp=0x7fffffffdea0) at hw/core/qdev.c:918
#4  0x0000555555bd733c in property_set_bool (obj=0x5555573eaea0, v=0x5555573eda40, name=0x55555607cce6 "realized", opaque=0x5555573bef50, errp=0x7fffffffdea0) at qom/object.c:1854
#5  0x0000555555bd5847 in object_property_set (obj=0x5555573eaea0, v=0x5555573eda40, name=0x55555607cce6 "realized", errp=0x7fffffffdea0) at qom/object.c:1088
#6  0x0000555555bd866f in object_property_set_qobject (obj=0x5555573eaea0, value=0x5555573ed930, name=0x55555607cce6 "realized", errp=0x7fffffffdea0) at qom/qom-qobject.c:27
#7  0x0000555555bd5aea in object_property_set_bool (obj=0x5555573eaea0, value=true, name=0x55555607cce6 "realized", errp=0x7fffffffdea0) at qom/object.c:1157
#8  0x0000555555957364 in qdev_device_add (opts=0x555556fdbc90, errp=0x7fffffffdf18) at qdev-monitor.c:623
#9  0x0000555555969a13 in device_init_func (opaque=0x0, opts=0x555556fdbc90, errp=0x0) at vl.c:2373
#10 0x0000555555cc801b in qemu_opts_foreach (list=0x55555659e120 <qemu_device_opts>, func=0x5555559699d5 <device_init_func>, opaque=0x0, errp=0x0) at util/qemu-option.c:1116
#11 0x000055555596ecf0 in main (argc=14, argv=0x7fffffffe358, envp=0x7fffffffe3d0) at vl.c:4574


Any help on this is greatly appreciated. Questions are:

- Is this a specific problem of the network device smc91c111.c (and maybe others, too) in the first place and I've cloned that issue when copying the structure of that device module? I haven't tested smc91c111.c. Should I? I guess this stuff is widely used and should work?

- If not, what is the problem here? I would guess it is related to the "realized" property which is not set with the first initialization and eventually, the device is initialized a second time.

Sorry, if this turn out the be a noobish question. I've got it running in a hacked version, but I wanted to figure out what the exact problem is. Any ideas?

TIA
Marc

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

* Re: [Qemu-devel] Strange behaviour in network device initialization.
  2017-03-18 21:15 ` [Qemu-devel] Strange behaviour in network device initialization Marc Bommert
@ 2017-03-18 22:22   ` Peter Maydell
  2017-03-19 13:41     ` Marc Bommert
  0 siblings, 1 reply; 4+ messages in thread
From: Peter Maydell @ 2017-03-18 22:22 UTC (permalink / raw)
  To: Marc Bommert; +Cc: QEMU Developers

On 18 March 2017 at 21:15, Marc Bommert <marc@brightwise.de> wrote:
> I ran into some behaviour I don't understand and which may be a qemu problem but which may also be my fault, since I haven't investigated much on QOM so far.
> I am currently writing a NIC sysbus device based on the structure of hw/net/smc91c111.c
>
> qemu is invoked as:
>
>   $ qemu-system-arm -M mymachine -m 8 -kernel kernel.elf -nographic -net nic,id=myid -netdev tap,ifname=tap0,id=myid,script=no,downscript=no -device mydevice,netdev=myid
>
>
> The initialization structure is a little special here. A "legacy helper" initialization function is called from the board module mymachine.c:
>
>    for(n = 0; n < nb_nics; n++) {
>         nd = &nd_table[n];
>
>         if (!nd->model || strcmp(nd->model, "mydevice") == 0) {
>             mydevice_init(nd, MYDEVICE_BASE, pic[17]);
>             break;
>         } else {
>         /* We don't know this NIC model */
>         }
>     }


> Now, the actual problem is that mydevice_init1() is called twice and
> the device state is also instantiated twice.

This is expected, because you're creating two devices.
Device 1 is the one that's created by calling
mydevice_init() here in the board code.
Device 2 is created because you say "-device mydevice"
on the command line.

smc91c111 is an "embedded" device which is memory mapped
into a particular address in the memory space and directly
wired up to an interrupt line. (QEMU calls these "sysbus
devices".) These can't be sensibly created from the command
line because there's no way to specify how to wire them
up and where they live in memory.

Conversely, the -device command line option is for
devices which go in pluggable buses, like PCI and
ISA devices. The -device option says "create one
of these and plug it into some available bus of
the right type"; it creates devices in addition to
any that the board creates itself.

The slightly odd thing is that -device mydevice
doesn't fail for you -- if you try that for smc91c111 it
will complain:
 "Device smc91c111 cannot be dynamically instantiated"
to let you know that the command line option is wrong.

PS: smc91c111 is not a very good model to copy,
because that device code is very old, and doesn't
necessarily follow current QEMU coding practices.
Looking at a device that's been added to QEMU
more recently may be a better idea.

thanks
-- PMM

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

* Re: [Qemu-devel] Strange behaviour in network device initialization.
  2017-03-18 22:22   ` Peter Maydell
@ 2017-03-19 13:41     ` Marc Bommert
  0 siblings, 0 replies; 4+ messages in thread
From: Marc Bommert @ 2017-03-19 13:41 UTC (permalink / raw)
  To: Peter Maydell; +Cc: QEMU Developers

> Peter Maydell <peter.maydell@linaro.org> hat am 18. März 2017 um 23:22 geschrieben:
> 
> This is expected, because you're creating two devices.
> Device 1 is the one that's created by calling
> mydevice_init() here in the board code.
> Device 2 is created because you say "-device mydevice"
> on the command line.

I see. Already played around with omitting it, but I also have sporadic connectivity issues with the tap device, so I thought I would need it to link the device with the NIC on the command line. Oops.
 
> The slightly odd thing is that -device mydevice
> doesn't fail for you -- if you try that for smc91c111 it
> will complain:
>  "Device smc91c111 cannot be dynamically instantiated"
> to let you know that the command line option is wrong.

I suppose this is the output of add_fdt_node() in hw/arm/sysbus-fdt.c, so I'll try to reverse why that succeeds for my platform. That's a good pointer.

> PS: smc91c111 is not a very good model to copy,
> because that device code is very old, and doesn't
> necessarily follow current QEMU coding practices.
> Looking at a device that's been added to QEMU
> more recently may be a better idea.

I'll stick with it for prototyping. Probably I picked versatilepb as a blueprint because it is better understandable and complete, with lesser indirections.

Still, so many opportunities to make errors when you work your way into this stuff.
Thank you for your time, Peter.

- Marc

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

end of thread, other threads:[~2017-03-19 13:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-18 18:15 [Qemu-devel] Error checking and qemu_thread_create Anton Volkov
2017-03-18 21:15 ` [Qemu-devel] Strange behaviour in network device initialization Marc Bommert
2017-03-18 22:22   ` Peter Maydell
2017-03-19 13:41     ` Marc Bommert

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.