virtio blk原理

作者: mqddb | 来源:发表于2017-07-26 12:24 被阅读0次

    别人写的virtio blk原理

    virtio的原理说起来挺简单的,两边是front-driver,backend-driver,中间是virtio和vring。关键是front-driver如何将io操作传到backend-driver,backend-driver又是如何将这些io操作解析出来,执行完,通知回front-driver的?这里面的细节,细思极恐!
    问题一:Guest,Hypervisor,Host是如何建立联系的?本质就是初始化过程!

    virtio初始化函数很有规律基本就是:virtio_*_init,这种形式,那就好搞了,用systemtap抓取初始化的调用:

    各种class初始化:
    call virtio_device_class_init
    call virtio_blk_class_init
    call virtio_rng_class_init
    call virtio_serial_port_class_init
    call virtio_pci_class_init
    call virtio_serial_pci_class_init
    call virtio_bus_class_init
    call virtio_pci_bus_class_init
    call virtio_scsi_pci_class_init
    call virtio_balloon_pci_class_init
    call virtio_serial_class_init
    call virtio_balloon_class_init
    call virtio_mmio_bus_class_init
    call virtio_scsi_common_class_init
    call virtio_net_class_init
    call virtio_mmio_class_init
    call virtio_9p_class_init
    call virtio_blk_pci_class_init
    call virtio_scsi_class_init
    call virtio_9p_pci_class_init
    call virtio_rng_pci_class_init
    call virtio_net_pci_class_init
    
    virtio-serial-pci初始化(这个是个什么设备):
    call virtio_serial_pci_instance_init
    call virtio_pci_init
    call virtio_serial_pci_init
    
    我们的主角virtio blk初始化:
    call virtio_blk_pci_instance_init
    call virtio_pci_init
    call virtio_blk_pci_init
    
    我在虚拟机里面添加了virtio balloon设备:
    call virtio_balloon_pci_instance_init
    call virtio_pci_init
    call virtio_balloon_pci_init
    

    virtio blk的Qemu相关参数有两个:

    -drive file=/home/mq/Documents/IDV/idv-update/login.img,if=none,id=drive-virtio-disk1,format=qcow2 
    -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x8,drive=drive-virtio-disk1,id=virtio-disk1,bootindex=1
    

    可以看到virtio blk的TypeInfo name是:"virtio-blk-pci"。
    Instance结构:

    struct PCIDevice {
        DeviceState qdev;
    
        /* PCI config space */
        uint8_t *config;
    
        /* Used to enable config checks on load. Note that writable bits are
         * never checked even if set in cmask. */
        uint8_t *cmask;
    
        /* Used to implement R/W bytes */
        uint8_t *wmask;
    
        /* Used to implement RW1C(Write 1 to Clear) bytes */
        uint8_t *w1cmask;
    
        /* Used to allocate config space for capabilities. */
        uint8_t *used;
    
        /* the following fields are read only */
        PCIBus *bus;
        int32_t devfn;
        /* Cached device to fetch requester ID from, to avoid the PCI
         * tree walking every time we invoke PCI request (e.g.,
         * MSI). For conventional PCI root complex, this field is
         * meaningless. */
        PCIReqIDCache requester_id_cache;
        char name[64];
        PCIIORegion io_regions[PCI_NUM_REGIONS];
        AddressSpace bus_master_as;
        MemoryRegion bus_master_container_region;
        MemoryRegion bus_master_enable_region;
    
        /* do not access the following fields */
        PCIConfigReadFunc *config_read;
        PCIConfigWriteFunc *config_write;
    
        /* Legacy PCI VGA regions */
        MemoryRegion *vga_regions[QEMU_PCI_VGA_NUM_REGIONS];
        bool has_vga;
    
        /* Current IRQ levels.  Used internally by the generic PCI code.  */
        uint8_t irq_state;
    
        /* Capability bits */
        uint32_t cap_present;
    
        /* Offset of MSI-X capability in config space */
        uint8_t msix_cap;
    
        /* MSI-X entries */
        int msix_entries_nr;
    
        /* Space to store MSIX table & pending bit array */
        uint8_t *msix_table;
        uint8_t *msix_pba;
        /* MemoryRegion container for msix exclusive BAR setup */
        MemoryRegion msix_exclusive_bar;
        /* Memory Regions for MSIX table and pending bit entries. */
        MemoryRegion msix_table_mmio;
        MemoryRegion msix_pba_mmio;
        /* Reference-count for entries actually in use by driver. */
        unsigned *msix_entry_used;
        /* MSIX function mask set or MSIX disabled */
        bool msix_function_masked;
        /* Version id needed for VMState */
        int32_t version_id;
    
        /* Offset of MSI capability in config space */
        uint8_t msi_cap;
    
        /* PCI Express */
        PCIExpressDevice exp;
    
        /* SHPC */
        SHPCDevice *shpc;
    
        /* Location of option rom */
        char *romfile;
        bool has_rom;
        MemoryRegion rom;
        uint32_t rom_bar;
    
        /* INTx routing notifier */
        PCIINTxRoutingNotifier intx_routing_notifier;
    
        /* MSI-X notifiers */
        MSIVectorUseNotifier msix_vector_use_notifier;
        MSIVectorReleaseNotifier msix_vector_release_notifier;
        MSIVectorPollNotifier msix_vector_poll_notifier;
    };
    struct VirtIOPCIProxy {
        PCIDevice pci_dev;
        MemoryRegion bar;
        VirtIOPCIRegion common;
        VirtIOPCIRegion isr;
        VirtIOPCIRegion device;
        VirtIOPCIRegion notify;
        VirtIOPCIRegion notify_pio;
        MemoryRegion modern_bar;
        MemoryRegion io_bar;
        MemoryRegion modern_cfg;
        AddressSpace modern_as;
        uint32_t legacy_io_bar_idx;
        uint32_t msix_bar_idx;
        uint32_t modern_io_bar_idx;
        uint32_t modern_mem_bar_idx;
        int config_cap;
        uint32_t flags;
        bool disable_modern;
        bool ignore_backend_features;
        OnOffAuto disable_legacy;
        uint32_t class_code;
        uint32_t nvectors;
        uint32_t dfselect;
        uint32_t gfselect;
        uint32_t guest_features[2];
        VirtIOPCIQueue vqs[VIRTIO_QUEUE_MAX];
    
        VirtIOIRQFD *vector_irqfd;
        int nvqs_with_notifiers;
        VirtioBusState bus;
    };
    struct VirtIOBlkPCI {
        VirtIOPCIProxy parent_obj;
        VirtIOBlock vdev;
    };
    

    上面的结构体有个规律,逐渐由pci device往blk device转变,VirtIOPCIProxy,VirtIOBlock两个就是pci device和blk device的桥梁。

    相关文章

      网友评论

        本文标题:virtio blk原理

        本文链接:https://www.haomeiwen.com/subject/uvlwkxtx.html