qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] Strange behaviour in network device initialization.


From: Marc Bommert
Subject: [Qemu-devel] Strange behaviour in network device initialization.
Date: Sat, 18 Mar 2017 22:15:07 +0100 (CET)

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]