Refer to : https://blog.csdn.net/alex_mianmian/article/details/118678510
1. Code Architecture
In host_driver:
tranx_card.c is the MDEV driver. It's actully mtty.c. I just modified it as following:
This modification is set new PCIe configure space vendor ID,device ID, class ID and subsystem ID. The purpose is create my own MDEV virtual device.
The Makefile is same to mtty Makefile(https://blog.csdn.net/alex_mianmian/article/details/118678510).
The test_app.c is the test on host. It can check virtual device's state by ioctl.
The steps.txt is the steps of create virtual device and add virtual device to virtual machine as following:
sudo modprobe vfio-mdev
lsmod | grep vfio #should see vfio_mdev
sudo insmod tranx_card.ko
lsmod | grep vfio #should see vfio_mdev,tranx_card
sudo chmod 777 /sys/devices/virtual/tranx_mdev/tranx_mdev/mdev_supported_types/tranx_mdev-2/create
sudo echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1002" > /sys/devices/virtual/tranx_mdev/tranx_mdev/mdev_supported_types/tranx_mdev-2/create
virsh start ubuntu18.04
virsh attach-device ubuntu18.04 tranx_mdev.xml
The tranx_mdev.xml is the virtual device configure file of the virtual machine.
In vm_driver:
vm_tranx_pci.c is the virtual device driver in the virtual machine. We need build it and insmod it in the virtual machine. it looks like following:
/*
* Alex Xie Test.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/bitops.h>
#include <asm/byteorder.h>
#include <asm/io.h>
#define PCI_MY_ID 0x9999
#define PCI_VM_TRANX_ID 0x8787
/*
* Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card.
*/
static int
vm_tranx_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
pr_info("%s\n",__func__);
return 0;
}
static void vm_tranx_remove(struct pci_dev *dev)
{
pr_info("%s\n",__func__);
}
static const struct pci_device_id vm_tranx_pci_tbl[] = {
{ PCI_MY_ID, PCI_VM_TRANX_ID,
PCI_ANY_ID, PCI_ANY_ID,
0,0,0},
{ 0, }
};
MODULE_DEVICE_TABLE(pci, vm_tranx_pci_tbl);
static struct pci_driver vm_tranx_driver = {
.name = "vm_tranx",
.probe = vm_tranx_probe,
.remove = vm_tranx_remove,
.driver = {
.pm = NULL,
},
.id_table = vm_tranx_pci_tbl,
};
static int __init vm_tranx_init(void)
{
return pci_register_driver(&vm_tranx_driver);
}
static void __exit vm_tranx_cleanup(void)
{
pci_unregister_driver(&vm_tranx_driver);
}
module_init(vm_tranx_init);
module_exit(vm_tranx_cleanup);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("KVM tranx driver module");
It's PCI driver which will match MY vendor ID and device ID as I setup in the host MDEV driver.
The Makefile is same to host_driver/Makefile.
2. Steps:
1) Host Side: build host_driver
cd host_driver
make
sudo insmod tranx_card.ko
sudo chmod 777 /sys/devices/virtual/tranx_mdev/tranx_mdev/mdev_supported_types/tranx_mdev-2/create
sudo echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1002" > /sys/devices/virtual/tranx_mdev/tranx_mdev/mdev_supported_types/tranx_mdev-2/create
virsh start ubuntu18.04
After all these steps, you can refer to mtty blog to check the virtual device.
2) VM side: build vm_driver
Copy vm_driver to virtual machine, build it and insmod it. And you should find it as following:
3) Host Side: add virtual device to virtual machine
virsh attach-device ubuntu18.04 tranx_mdev.xml
And you can see the device on virtual machine as:
And we can see my vm_driver in virtual machine found my virtual device as:
Here we can see vm_tranx_probe() was called.
3. Conclusion
With MDEV, we can easily add PCI device for virtual machine.
We just need generate PCI device's configure space on host driver and add virtual PCI device's virtual driver in virtual machine.
The virtual machine actually has no idea this PCI device is a virtual device.