QEMU-KVM Virtio Virtualization-----Linux Client Virtio Device initialization __linux

Source: Internet
Author: User
Tags goto
Linux Client Virtio Device initialization
The Virtio device is physically connected to the PCI physical bus and logically connected to the Virtio virtual bus. As a PCI device, it facilitates resource allocation and configuration, and facilitates management and organization in the logical device model.
Virtio PCI devices provided by 1.QEMU-KVM
VIRTIO-BLK (hard disk), virtio-net (Network), Virtio-balloon (balloon), such as PCI devices, these devices are connected to the PCI bus. Code is located in Qemu:hw/virtio-pci.c
Static Pcideviceinfo virtio_info[] = {
{
. Qdev.name = "Virtio-blk-pci",
},{
. Qdev.name = "Virtio-net-pci",
},{
. Qdev.name = "Virtio-serial-pci",
},{
. Qdev.name = "Virtio-balloon-pci",
},
}
static void Virtio_pci_register_devices (void)
{
Pci_qdev_register_many (Virtio_info);
}

2. Client PCI devices for enumeration and resource allocation
When the Linux client system is started, the PCI device is enumerated and resource allocated (configuring PCI configuration space), typically completed by the BIOS. However, the Linux system provides a way, one is implemented by the BIOS, the other is the implementation of the enumeration and resource allocation function. Code is located in kernel:arch/x86/pci/init.c
static __init int pci_arch_init (void)
{
#ifdef Config_pci_direct
int type = 0;

Type = Pci_direct_probe ();
#endif

#endif
#ifdef Config_pci_bios
Pci_pcbios_init ();
#endif
}
Real device enumeration and resource allocation start here
static int __init pci_legacy_init (void)
{
PRINTK ("pci:probing PCI hardware\n");
Pci_root_bus = pcibios_scan_root (0);
if (Pci_root_bus)
Pci_bus_add_devices (Pci_root_bus);

return 0;
}
Pcibios_scan_root ()---->pci_scan_bus_parented ()---->pci_scan_child_bus ()--->pci_scan_slot ()--->PCI _scan_single_device ()----->pci_device_add ()
Adding devices on the PCI bus to the list
void Pci_device_add (struct pci_dev *dev struct pci_bus)
{
/*
* Add the device to our list of discovered devices
* and the bus list for fixup functions, etc.
*/
Down_write (&pci_bus_sem);
List_add_tail (&dev->bus_list, &bus->devices);
Up_write (&pci_bus_sem);
}
The above procedure is completed and the Virtio PCI device is created in the/sys/devices/pci0000:00 directory. And in the/sys/bus/pci/devices/directory, create the corresponding symbolic connection for the PCI device, while in the/sys/bus/pci/drivers/directory, create the VIRTIO-PCI directory, there is a supporting device symbol connection file under the directory.

3.virtio bus definition and registration, Virtio bus for virtual bus, for the purpose of equipment management and organizational needs. The code is located at:
static struct Bus_type Virtio_bus = {
. Name = "Virtio",
. match = Virtio_dev_match,
. Dev_attrs = Virtio_dev_attrs,
. uevent = Virtio_uevent,
. Probe = Virtio_dev_probe,
. remove = Virtio_dev_remove,
};

static int virtio_init (void)
{
if (Bus_register (&virtio_bus)!= 0)
Panic ("Virtio Bus registration failed");
return 0;
}
The above registration function call was completed, and in the/sys/bus/directory, a new directory Virtio was created, in which two folders were created for devices and drivers. Represents the creation of the Virtio bus, the bus support device with the driver devices and the drivers directory.

4. VIRTIO-PCI Device driver loading
static struct Pci_driver Virtio_pci_driver = {
. Name = "Virtio-pci",
. id_table = virtio_pci_id_table,
. Probe = Virtio_pci_probe,
. remove = Virtio_pci_remove,
#ifdef CONFIG_PM
. Suspend = Virtio_pci_suspend,
. Resume = Virtio_pci_resume,
#endif
};
static int __init virtio_pci_init (void)
{

Virtio_pci_root = Root_device_register ("Virtio-pci");
Err = Pci_register_driver (&virtio_pci_driver);
return err;
}
The above registration function call was performed and the Virtio-pci folder was created under the/sys/bus/pci/drivers and/sys/devices directories

5,virtio Bus Sub Device registration
In step 2 above, an enumeration of PCI devices and resource allocations are described, and the enumerated devices are already associated with the bus list. The function call Pci_register_driver (&virtio_pci_driver) is the detection of each PCI device in the list, whether the driver supports the device, and if it is supported, calls the drive probe function, completes enabling the PCI device, Register the device at the same time on the Virtio bus.
Bus_for_each_dev (Drv->bus, NULL, DRV, __driver_attach);
if (drv->probe) {
ret = Drv->probe (dev);
}

static int __devinit virtio_pci_probe (struct Pci_dev *pci_dev,
const struct PCI_DEVICE_ID *id)
{
struct Virtio_pci_device *vp_dev;
int err;

/* We only own devices >= 0x1000 and <= 0x103f:leave the rest. */
if (Pci_dev->device < 0x1000 | | | pci_dev->device > 0x103f)
Return-enodev;

/* Allocate our structure and fill it out * *
Vp_dev = kzalloc (sizeof (struct virtio_pci_device), gfp_kernel);
if (Vp_dev = NULL)
Return-enomem;

Vp_dev->vdev.dev.parent = Virtio_pci_root;
Vp_dev->vdev.dev.release = Virtio_pci_release_dev;
Vp_dev->vdev.config = &virtio_pci_config_ops;
Vp_dev->pci_dev = Pci_dev;
Init_list_head (&vp_dev->virtqueues);
Spin_lock_init (&vp_dev->lock);
/* Disable Msi/msix to bring device to a known good state. */
Pci_msi_off (Pci_dev);

* Enable the device * *
Err = Pci_enable_device (Pci_dev);
if (ERR)
Goto out;

Err = Pci_request_regions (Pci_dev, "Virtio-pci");
if (ERR)
Goto Out_enable_device;

VP_DEV-&GT;IOADDR = Pci_iomap (pci_dev, 0, 0);
if (vp_dev->ioaddr = NULL)
Goto out_req_regions;

Pci_set_drvdata (Pci_dev, Vp_dev);

/* We use the Subsystem Vendor/device ID as the Virtio vendor/device
* ID. This allows us to use the same PCI Vendor/device ID for all
* Virtio devices and to identify the particular virtio by
* The Subsytem IDs * *
Vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor;
Vp_dev->vdev.id.device = pci_dev->subsystem_device;
/* Finally register the virtio device * *
Err = Register_virtio_device (&vp_dev->vdev);
if (ERR)
Goto Out_set_drvdata;

return 0;

}
The above registration function call execution completes,/sys/devices/virtio-pci/creates the corresponding child device {Virtio1,virtio2,virtio3}, and creates three symbolic connection files under/sys/bus/virtio/devices. Virtio1,virtio2,virtio3}

6. Virtio Bus sub device driver registration.
When the Virtio bus registers the device Register_virtio_device, the probe function of the Virtio bus is invoked: Virtio_dev_probe (). The function traverses the driver and finds a support driver associated with the device.
Register_virtio_device ()--->bus_probe_device ()---->device_attach ();
Bus_for_each_drv (Dev->bus, NULL, Dev, __device_attach);
if (dev->bus->probe) {
ret = Dev->bus->probe (dev);
}

static int virtio_dev_probe (struct device *_d)
{
int err, I;
struct Virtio_device *dev = container_of (_d,struct virtio_device,dev);
struct Virtio_driver *drv = container_of (Dev->dev.driver,
struct virtio_driver, driver);
U32 Device_features;

/* We have a driver! */
Add_status (Dev, virtio_config_s_driver);

/* Figure out what features the device supports. */
Device_features = Dev->config->get_features (dev);

/* Features supported by both device and driver into Dev->features. */
memset (dev->features, 0, sizeof (dev->features));
for (i = 0; i < drv->feature_table_size; i++) {
unsigned int f = drv->feature_table[i];
Bug_on (f >= 32);
if (Device_features & (1 << f))
Set_bit (f, dev->features);
}

/* Transport features always preserved to the finalize_features. */
for (i = Virtio_transport_f_start i < virtio_transport_f_end; i++)
if (Device_features & (1 << i))
Set_bit (i, dev->features);

Dev->config->finalize_features (Dev);
Err = Drv->probe (dev);
if (ERR)
Add_status (Dev, virtio_config_s_failed);
Else
Add_status (Dev, virtio_config_s_driver_ok);

return err;
}
Virtio_balloon Device Driver Instance
static struct Virtio_driver Virtio_balloon_driver = {
. feature_table = Features,
. Feature_table_size = Array_size (Features),
. Driver.name = Kbuild_modname,
. Driver.owner = This_module,
. id_table = id_table,
. Probe = Virtballoon_probe,
. remove = __devexit_p (Virtballoon_remove),
. config_changed = virtballoon_changed,
};

static int __init init (void)
{
Return Register_virtio_driver (&virtio_balloon_driver);
}
At the same time, create three files {Virtio_balloon,virtio_blk,virtio_console} under/sys/bus/virtio/drivers and associate with the device
//////////////////////////////
Hot-swappable events are often generated by bus-driven logic, so the bus generally provides event-sending functions. For example Virtio Bus event function virtio_uevent.
static int virtio_uevent (struct device *_DV, St

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.