[Qemu-devel] Trying to write a new device / virtio-i2c ?
Hello, I'm new to QEMU and kinda new to driver & QEMU programming in general, so please excuse my questions... I want to develop a new QEMU i2c device (qemu x86), that would get/send data to an application running on the guest. Thing is : I need these data onto the host, as a daemon will send/get the same kind of data to the guest. After reading code, documentation and available things, I've been trying to write something like a "virtio-i2c" : I wrote a virtio-i2c module for my kernel (I used some examples from virtio-pci and virtio-console), it seems that it created a "i2c-1" device in /dev, My device that I launch with QEMU (-chardev socket,path=/tmp/test0,server,nowait,id=bob -device virtio-i2c,chardev=bob) doesn't seem to be recognized by the kernel driver : my probe function doesn't run. I might have missed something : how does a kernel driver uses the "probe" function with a QEMU device ? Hoping that it doesn't look too confused...
Re: [Qemu-devel] Trying to write a new device / virtio-i2c ?
Thanks for all your answers. I understand that what I want to achieve seemed pretty confused. I will try to clarify : On real hardware, I have an I2C device used to get temperatures, pressure etc... and it works on x86 and there were no QEMU virtualized hardware corresponding. I don't really need to simulate the I2C hardware in QEMU. Indeed, there are few of them just sending regular i2c data. For some tests, I want to be able to send/receive these ones from my daemon on the host. After some researches, what I was thinking about was : 1) Use virtio-serial and write an I2C driver (guest kernel) that would give/take data to/from i2c-1 and read/write to vportp0... Seemed a bit ugly, so I wanted to try something else. 2) Write virtio-i2c (using i2c-driver and virtio kernel basics) that would register, for example, i2c-1 and get/send data from my guest app, and use virtio to send these data to host. What I have done for now : I used virtio-serial / virtio-console in linux kernel and inspired from virtio-pci to try to registers these "vport0pX" as i2c-1, i2c-2 etc... and as i2c devices. I also wrote a virtio-i2c QEMU-side to register as this hardware using virtio-i2c drivers. I think my understanding of the architecture is probably not complete, as it seems that this QEMU device doesn't automatically registers as a "virtio-i2c" hardware that would launch my guest kernel driver. My printk's in the "probe" are not printed. My driver is then never used. My questions were then : - My solution might be a bit complicated assuming I don't have that much knowledge in the architecture (however I'm interested into learning...) - Are there solutions that seems more adapted to my case ? Like using USB-I2C bridge ? 2014-02-14 17:45 GMT+01:00 Paolo Bonzini : > Il 14/02/2014 17:31, Andreas Färber ha scritto: > > While that is certainly possible in case host passthrough was desired, >> maybe virtio was mixed up with VFIO? >> > > I don't think so, VFIO is mostly about IOMMUs and protecting from DMA. > > Paolo >
[Qemu-devel] Fwd: Trying to write a new device / virtio-i2c ?
2014-02-17 10:19 GMT+01:00 Paolo Bonzini : > Il 17/02/2014 09:35, Alex David ha scritto: > > - Are there solutions that seems more adapted to my case ? Like using >> USB-I2C bridge ? >> > > From an upstream point of view, a host passthrough device pair (one object > talking to /dev/i2c-N on the host, and one device per sensor talking to the > other object) would be the best. > i2c-N is on the guest, that's why I want to virtualize an i2c hardware on QEMU. My idea was getting the data on a socket on the host => read these data from my daemon. That's why virtio-serial seemed like a good thing to use / adapt as i2c. I'll look on the parallel solution, I don't think there's a virtio-parallel, right ?
Re: [Qemu-devel] Fwd: Trying to write a new device / virtio-i2c ?
2014-02-17 11:38 GMT+01:00 Paolo Bonzini : > Il 17/02/2014 11:01, Alex David ha scritto: > > I indeed don't use paravirtualization. >> > > Virtio _is_ paravirtualization. :) > > Ok, now that seems much more understandable... I missed that point ha. > > I'm emulating a bunch of sensors/actuators. >> >> If I virtualize my sensors and attach them to the i2c-dev with -device, >> how do I get those data on the host then ? >> > > It depends on your use case. > > It could be that you can make them return a constant value. > > Otherwise, you may want to use a chardev for that purpose, or finally a > QOM (QEMU Object Model) property. For example, add > > CONFIG_TMP105=y > > to default-configs/x86_64-softmmu.mak before building QEMU, then do the > following (indented = in the guest): > > $ x86_64-softmmu/qemu-system-x86_64 --enable-kvm ~/test2.img -m 256 \ >-device tmp105,id=sensor,address=0x50 \ >-qmp unix:$HOME/qmp.sock,server,nowait > $ qmp/qom-list -s ~/qmp.sock /machine/peripheral/sensor > temperature > @parent_bus/ > address > hotpluggable > realized > type > $ scripts/qmp/qmp-shell ~/qmp.sock > (QEMU) qom-get path=/machine/peripheral/sensor property=temperature > {u'return': 0} > (QEMU) qom-get path=sensor property=address > {u'return': 80} > > # modprobe i2c-dev > # i2cget -y 0 0x50 0 w > 0x > > (QEMU) qom-set path=sensor property=temperature value=2 > {u'return': {}} > > # i2cget -y 0 0x50 0 w > 0x0014 > > For this particular sensor, you have to swap the two bytes and the result > is 8.8 fixed-point. > > Paolo > > > Thanks for your help. As you may see, I'm not that experienced in >> QEMU/Linux kernel. >> > > Ok, I'm gonna try these things. I might try to use a chardev also. Thanks for your help !
Re: [Qemu-devel] Fwd: Trying to write a new device / virtio-i2c ?
> > > >> >> I'm emulating a bunch of sensors/actuators. >>> >>> If I virtualize my sensors and attach them to the i2c-dev with -device, >>> how do I get those data on the host then ? >>> >> >> It depends on your use case. >> >> It could be that you can make them return a constant value. >> >> Otherwise, you may want to use a chardev for that purpose, or finally a >> QOM (QEMU Object Model) property. For example, add >> >> CONFIG_TMP105=y >> >> to default-configs/x86_64-softmmu.mak before building QEMU, then do the >> following (indented = in the guest): >> >> $ x86_64-softmmu/qemu-system-x86_64 --enable-kvm ~/test2.img -m 256 \ >>-device tmp105,id=sensor,address=0x50 \ >>-qmp unix:$HOME/qmp.sock,server,nowait >> $ qmp/qom-list -s ~/qmp.sock /machine/peripheral/sensor >> temperature >> @parent_bus/ >> address >> hotpluggable >> realized >> type >> $ scripts/qmp/qmp-shell ~/qmp.sock >> (QEMU) qom-get path=/machine/peripheral/sensor property=temperature >> {u'return': 0} >> (QEMU) qom-get path=sensor property=address >> {u'return': 80} >> >> # modprobe i2c-dev >> # i2cget -y 0 0x50 0 w >> 0x >> >> (QEMU) qom-set path=sensor property=temperature value=2 >> {u'return': {}} >> >> # i2cget -y 0 0x50 0 w >> 0x0014 >> >> For this particular sensor, you have to swap the two bytes and the result >> is 8.8 fixed-point. >> >> Paolo >> >> >> Thanks for your help. As you may see, I'm not that experienced in >>> QEMU/Linux kernel. >>> >> >> > Ok, I'm gonna try these things. I might try to use a chardev also. Thanks > for your help ! > I've tried using tmp105. As my linux isn't 64bits, i'm using qemu-system-i386... It crashes my computer when I use it with my linux image (it's a debian .qcow2..., easy to do some tests...). I will most probably need a chardev anyways, I will need to read/write data when I want to. I'm gonna be annoying and ask another basic question : I wrote this in my i2c_device_test.c (QEMU device) : static const TypeInfo mydevice_i2c_type_info = { .name= TYPE_MYDEVICE_I2C, .parent= TYPE_I2C_SLAVE, .instance_size= sizeof(MYDEVICEI2CState), .instance_init= MYDEVICE_i2c_init, .class_init= mydevice_i2c_class_init, }; I will be able to add a chardev using the properties, right ? static void mydevice_i2c_class_init(ObjectClass *klass, void *data) { printf("Test init2\n"); I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); sc->init = mydevice_i2c_init; sc->event = mydevice_i2c_event; sc->recv = mydevice_i2c_recv; sc->send = mydevice_i2c_send; dc->vmsd = &mydevice_i2c_vmstate; dc->props = mydevice_i2c_properties; dc->realize = mydevice_i2c_realize; } Does this seems ok for you ? So far, I understood the "props" are needed for when I'm gonna declare the device at QEMU launch. I am not sure if it's needed (my i2c-0 should be created anyways), but in that case, how do I "plug" it on my socket on the host ? Thanks !
Re: [Qemu-devel] Fwd: Trying to write a new device / virtio-i2c ?
2014-02-17 14:19 GMT+01:00 Paolo Bonzini : > Il 17/02/2014 14:11, Alex David ha scritto: > > I've tried using tmp105. As my linux isn't 64bits, i'm using >> qemu-system-i386... It crashes my computer when I use it with my linux >> image (it's a debian .qcow2..., easy to do some tests...). >> > > You mean crashes your host? > Yes, my host crashes... I need to hard-reboot my computer. > > I will most probably need a chardev anyways, I will need to read/write >> data when I want to. >> > > Depends on how much data. If it's just one or two ints, like tmp105, QOM > would work too. qmp-shell talks to QEMU via a simple JSON protocol, and it > has simple Python bindings too. > > > static const TypeInfo mydevice_i2c_type_info = { >> .name= TYPE_MYDEVICE_I2C, >> .parent= TYPE_I2C_SLAVE, >> .instance_size= sizeof(MYDEVICEI2CState), >> .instance_init= MYDEVICE_i2c_init, >> .class_init= mydevice_i2c_class_init, >> }; >> >> I will be able to add a chardev using the properties, right ? >> > > Yes, using dc->props. > > > Does this seems ok for you ? So far, I understood the "props" are needed >> for when I'm gonna declare the device at QEMU launch. >> I am not sure if it's needed (my i2c-0 should be created anyways), but >> in that case, how do I "plug" it on my socket on the host ? >> > > Your device is not i2c-0. i2c-0 is provided by the PC board. Your device > will get one address, e.g. 0x42, on the i2c bus. You'll be able to access > it with i2cget and i2cset using "0" as the bus address (for i2c-0) and 0x42 > as the device address on bus 0. > > So you'll indeed have to do something like "-chardev socket,id=foo -device > myi2c,address=0x42,chr=foo" if you go for sockets, or just "-device > myi2c,address=0x42" if you go for QOM. The "chr" property should go into > dc->props, while "address" is provided by the abstract class TYPE_I2C_SLAVE. > > Paolo > That seems fairly easy. But that leaves me with another problem as I now understand how I2C works on linux... I, in fact, need at least 3 busses (for my at least 3 devices) - so i2c-0, i2c-1, i2c-2 ... There are applications I can't change on the guest and opening / writing / reading on i2c-0, i2c-1 etc... Can I just declare these busses using i2c-dev ?
Re: [Qemu-devel] Fwd: Trying to write a new device / virtio-i2c ?
2014-02-17 15:30 GMT+01:00 Paolo Bonzini : > So you cannot configure the three devices on the same bus, with three > different addresses? Each sensor is different on the original hardware, they are connected on different busses. As my guest apps are calling i2c-1, i2c-2, ,i2c-N (and I can't change them), I will need to create those busses... > If you need more than one bus, you need a new device exposing the I2C bus, > besides the new sensor devices. USB-I2C could be one such device. > So let me see if I understood well. USB-I2C (host QEMU device) seems a good idea, I could normally do : qemu-system-i386 -device usb-I2c,chardev=foo -device usb-i2c,chardev=bar -chardev socket,path=/tmp/test0,server,nowait,id=foo -chardev socket,path=/tmp/test1,server,nowait,id=bar. I need a "USB-I2C guest kernel driver" that would register a bus (i2c-1 for chardev foo, i2c-2 for chardev bar etc...), I guess ?
Re: [Qemu-devel] Fwd: Trying to write a new device / virtio-i2c ?
2014-02-17 17:11 GMT+01:00 Paolo Bonzini : > Il 17/02/2014 16:33, Alex David ha scritto: > > If you need more than one bus, you need a new device exposing the >> I2C bus, besides the new sensor devices. USB-I2C could be one such >> device. >> >> So let me see if I understood well. USB-I2C (host QEMU device) seems a >> good idea, I could normally do : qemu-system-i386 -device >> usb-I2c,chardev=foo -device usb-i2c,chardev=bar -chardev >> socket,path=/tmp/test0,server,nowait,id=foo -chardev >> socket,path=/tmp/test1,server,nowait,id=bar. >> > > Almost. For QOM: > > -device usb-i2c,id=usb-i2c-0 > -device i2c-my-sensor,address=0x48,bus=usb-i2c-0.0 > > For chardev: > > -device usb-i2c,id=usb-i2c-0 > -chardev socket,path=/tmp/test0,server,nowait,id=chr-foo-0 > -device i2c-my-sensor,address=0x48,bus=usb-i2c-0.0,chardev=chr-foo-0 > > Repeat for the other buses, replacing -0 with -1 and -2. > > > I need a "USB-I2C guest kernel driver" that would register a bus (i2c-1 >> for chardev foo, i2c-2 for chardev bar etc...), I guess ? >> > > It exists already, drivers/i2c/busses/i2c-tiny-usb.c. > I'm now trying to write this new USB-I2C device, I look through some of the code (dev-serial, dev-...), I used dev-serial code and removed the code that wanted to declare a chardev (I don't need one to create my bus, right ?). Now I'm wondering, how will be i2c-tiny-usb launched and declare a new /dev/i2c-N, with my device. I found : static struct usb_device_id i2c_tiny_usb_table [] = { { USB_DEVICE(0x0403, 0xc631) }, /* FTDI */ { USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */ { } /* Terminating entry */ }; So I figured my USB-I2C should register using these numbers ? static const USBDesc desc_i2c = { .id = { .idVendor = 0x0403, .idProduct = 0xc631, .bcdDevice = 0x0400, .iManufacturer = STR_MANUFACTURER, .iProduct = STR_PRODUCT_I2C, .iSerialNumber = STR_SERIALNUMBER, }, .full = &desc_device, .str = desc_strings, }; However, this doesn't work, after a $ qemu-system-i386 debian_wheezy_i386_standard.qcow2 -usb -device USB-I2C,id=usb-i2c-0, the driver doesn't seem to be used (/sys/class/i2c-dev/i2c-0/name isn't for it...), even if I modprobe i2c-tiny-usb... The dmesg shows it doesn't go into the "probe" function. What did I miss ?
Re: [Qemu-devel] Fwd: Trying to write a new device / virtio-i2c ?
Ok, thank you very much for your help then. I'm gonna spend some time on this. If qemu-dev / you are interested in what I've done later, I'll send a new mail. 2014-02-18 14:05 GMT+01:00 Paolo Bonzini : > Il 18/02/2014 13:48, Alex David ha scritto: > >> >> 2014-02-17 17:11 GMT+01:00 Paolo Bonzini > <mailto:pbonz...@redhat.com>>: >> >> >> Il 17/02/2014 16:33, Alex David ha scritto: >> >> If you need more than one bus, you need a new device >> exposing the >> I2C bus, besides the new sensor devices. USB-I2C could be >> one such >> device. >> >> So let me see if I understood well. USB-I2C (host QEMU device) >> seems a >> good idea, I could normally do : qemu-system-i386 -device >> usb-I2c,chardev=foo -device usb-i2c,chardev=bar -chardev >> socket,path=/tmp/test0,server,__nowait,id=foo -chardev >> socket,path=/tmp/test1,server,__nowait,id=bar. >> >> >> >> Almost. For QOM: >> >> -device usb-i2c,id=usb-i2c-0 >> -device i2c-my-sensor,address=0x48,__bus=usb-i2c-0.0 >> >> For chardev: >> >> -device usb-i2c,id=usb-i2c-0 >> -chardev socket,path=/tmp/test0,server,__nowait,id=chr-foo-0 >> -device >> i2c-my-sensor,address=0x48,__bus=usb-i2c-0.0,chardev=chr-__foo-0 >> >> >> Repeat for the other buses, replacing -0 with -1 and -2. >> >> >> I need a "USB-I2C guest kernel driver" that would register a bus >> (i2c-1 >> for chardev foo, i2c-2 for chardev bar etc...), I guess ? >> >> >> It exists already, drivers/i2c/busses/i2c-tiny-usb.c. >> >> >> I'm now trying to write this new USB-I2C device, I look through some of >> the code (dev-serial, dev-...), I used dev-serial code and removed the >> code that wanted to declare a chardev (I don't need one to create my >> bus, right ?). >> >> Now I'm wondering, how will be i2c-tiny-usb launched and declare a new >> /dev/i2c-N, with my device. I found : >> >> static struct usb_device_id i2c_tiny_usb_table [] = { >> { USB_DEVICE(0x0403, 0xc631) }, /* FTDI */ >> { USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */ >> { } /* Terminating entry */ >> }; >> >> So I figured my USB-I2C should register using these numbers ? >> >> static const USBDesc desc_i2c = { >> .id = { >> .idVendor = 0x0403, >> .idProduct = 0xc631, >> .bcdDevice = 0x0400, >> .iManufacturer = STR_MANUFACTURER, >> .iProduct = STR_PRODUCT_I2C, >> .iSerialNumber = STR_SERIALNUMBER, >> }, >> .full = &desc_device, >> .str = desc_strings, >> }; >> >> However, this doesn't work, after a $ qemu-system-i386 >> debian_wheezy_i386_standard.qcow2 -usb -device USB-I2C,id=usb-i2c-0, the >> driver doesn't seem to be used (/sys/class/i2c-dev/i2c-0/name isn't for >> it...), even if I modprobe i2c-tiny-usb... >> The dmesg shows it doesn't go into the "probe" function. >> >> What did I miss ? >> > > I honestly don't know, you'll have to debug it. > > Paolo >