Full analysis of QEMU source code - virtio (10)

Continuing from the previous article:

Starting from the last chapter, along the calling line of device_set_realized() -> pci_qdev_realize() -> virtio_pci_realize(), the virtio_pci_realize function was analyzed in detail. Finally, the last step of the virtio_pci_realize function calls the virtio_balloon_pci_realize function. This time we will analyze the virtio_balloon_pci_realize function.

The virtio_balloon_pci_realize function is in hw/virtio/virtio-balloon-pci.c, as follows:

static void virtio_balloon_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev);
    DeviceState *vdev = DEVICE(&dev->vdev);

    vpci_dev->class_code = PCI_CLASS_OTHERS;
    qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
}

The virtio_balloon_pci_realize function first converts the VirtIOPCIxy type device to a VirtIOBalloonPCI device through the VIRTIO_BALLOON_PCI macro, which is equivalent to converting from a parent class to a subclass. The code snippet is:

    VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(vpci_dev);

Next, get the VirtIOBalloon part of the device VirtIOBalloonPCI, which is the actual virtio balloon device. .The code snippet is:

    DeviceState *vdev = DEVICE(&dev->vdev);

Next, call the qdev_realize function in hw/core/qdev.c. The code snippet is as follows:

    qdev_realize(vdev, BUS(&vpci_dev->bus), errp);

The qdev_realize function code is as follows:

bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp)
{
    assert(!dev->realized && !dev->parent_bus);

    if (bus) {
        if (!qdev_set_parent_bus(dev, bus, errp)) {
            return false;
        }
    } else {
        assert(!DEVICE_GET_CLASS(dev)->bus_type);
    }

    return object_property_set_bool(OBJECT(dev), "realized", true, errp);
}

The qdev_realize function mainly does two things:

1) Set the bus of the virtio balloon device to the bus member in the VirtIOPCIProxy device, that is, hang the virtio balloon device on the virtio bus.

2) Call the object_property_bool function to materialize the virtio balloon device, which will lead to the execution of the virtio_device_realize function.

Note: In fact, in the old version, there is no qdev_realize function, and the two tasks in it are completed directly in the virtio_balloon_pci_realize function.

The virtio_device_realize function is in hw/virtio/virtio.c, the code is as follows:

static void virtio_device_realize(DeviceState *dev, Error **errp)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
    Error *err = NULL;

    /* Devices should either use vmsd or the load/save methods */
    assert(!vdc->vmsd || !vdc->load);

    if (vdc->realize != NULL) {
        vdc->realize(dev, &err);
        if (err != NULL) {
            error_propagate(errp, err);
            return;
        }
    }

    virtio_bus_device_plugged(vdev, &err);
    if (err != NULL) {
        error_propagate(errp, err);
        vdc->unrealize(dev);
        return;
    }

    vdev->listener.commit = virtio_memory_listener_commit;
    vdev->listener.name = "virtio";
    memory_listener_register(&vdev->listener, vdev->dma_as);
    QTAILQ_INSERT_TAIL(&virtio_list, vdev, next);
}

For an in-depth analysis of the virtio_device_realize function, please see the next chapter.

Guess you like

Origin blog.csdn.net/phmatthaus/article/details/135028701