Page 1 of 1

Custom VirtIO device development

Posted: 28. Jun 2019, 11:30
by where-is-s
Hello! I'm trying to develop a simple custom VirtIO-based device that would pass the data between Linux guest and Windows host. However I got stuck in the beginning because I cannot find enough info to start off. There are almost no examples or documentation. By now I have managed to compile a simple VBox device that would initialize as a vpci device. It is constructed successfully and I'm able to see it in guest OS but that's it. I can't understand how virtual queues work and how I could exchange messages between host and guest. I have spent days reading VirtualBox sources (including virtio-net) but they are too complicated for me, especially since the driver/device area is pretty new to me and there are no code comments. Are there any working examples for a really simple VirtIO device? Can anybody help me with that?

Re: Custom VirtIO device development

Posted: 2. Jul 2019, 06:55
by where-is-s
A forum member suggested that I list here some problems I have. First problem was that VirtualBox did not construct my device. That issue has already been discussed on this forum (viewtopic.php?f=10&t=69802). After applying the fix from that thread I still could not start a VM with my virtual device connected. It turned out that I also needed to check that device .so name matched szName in PDMDEVREG structure. After I used the same name in those places I've finally managed to launch the VM.
After that I have initialized virtual PCI device like this:

Code: Select all

rc = vpciConstruct(pDevIns, &pThis->VPCI, iInstance,
  VBOXSAMPLEDEVICE_NAME_FMT, VIRTIO_CUSTOM_ID,
  VBOXSAMPLEDEVICE_PCI_CLASS, VBOXSAMPLEDEVICE_N_QUEUES);
Here VIRTIO_CUSTOM_ID is equal to 25 which is a new value different from all other VirtIO device ids. I've chosen this value to make sure that my driver detects this device unambiguously. After adding this code I have found a new PCI device in guest OS using lsmod command. Next, I have proceeded to implement the driver. Here is its main declaration part:

Code: Select all

static struct virtio_device_id id_table[] = {
  { VIRTIO_CUSTOM_ID, VIRTIO_DEV_ANY_ID }, // device id the same as ID in the device (25), vendor is any
  { 0 },
};

static struct virtio_driver virtio_custom_driver = {
  .driver.name         = "VBoxSampleDevice",
  .driver.owner        = THIS_MODULE,
  .feature_table       = features,
  .feature_table_size  = ARRAY_SIZE(features),
  .id_table            = id_table,
  .probe               = custom_probe,
  .remove              = custom_remove,
};
However I don't get probe method called. I have turned on kernel module using insmod or modprobe but printk tracing still doesn't output anything into /dev/kmsg or dmesg. I think this happens because VirtIO somehow doesn't find this driver suitable for the device. What other things should I check here, besides driver name and device id?

UPD: Spent the whole day debugging, turns out the device was not initialized correctly. Device has been successfully registered and it is present in lspci output. Nevertheless it hasn't been initialized correctly, that explains why guest OS didn't even try matching it with the driver. The issue is that vpciConstruct fails with message "Failed to attach the status LUN". I'm not sure yet what to do with that.

Re: Custom VirtIO device development

Posted: 2. Jul 2019, 22:50
by RicV
Please clarify what you mean by successfully registered but not initialized correctly.

If the PDM device was correctly registered at construction time, then the Faux BIOS should perform a little test on your BAR registers to determine your memory requirements, and then assign memory address to the BARs that require it. Do you see it doing that?

What is the actual output of lspci -vvv (when run as root)?

I have no idea about the driver side, as I have never needed to explore that part in my own use case.