[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