Linux客户机 virtio设备初始化
virtio设备物理上连接在pci物理总线上,逻辑上连接在virtio虚拟总线。做为pci设备便于资源分配与配置,逻辑设备模型中,便于管理与组织。
1.qemu-kvm提供的virtio pci设备
virtio-blk(硬盘),virtio-net(网络),virtio-balloon(气球)等pci设备,这些设备连接在pci总线上。代码位于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.客户机PCI设备进行枚举和资源分配
当Linux客户机系统启动时,对PCI设备进行枚举和资源分配(配置PCI的配置空间),通常由BIOS完成。不过对Linux系统提供方式,一种由BIOS实现,另一种自己实现枚举和资源分配功能。代码位于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
}
真正设备枚举和资源分配由这里开始
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()
将PCI总线上的设备添加到链表
void pci_device_add(struct pci_dev *dev, struct pci_bus *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);
}
上述过程执行完成,在/sys/devices/pci0000:00目录下,创建virtio pci设备。并且在/sys/bus/pci/devices/目录下,创建相应对于pci设备的符号连接,同时在/sys/bus/pci/drivers/目录下,创建virtio-pci目录,目录下存在支持设备符号连接文件。
3.virtio总线定义与注册,virtio总线为虚拟的总线,目的为了设备管理与组织需要。代码位于:
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)
virtio设备物理上连接在pci物理总线上,逻辑上连接在virtio虚拟总线。做为pci设备便于资源分配与配置,逻辑设备模型中,便于管理与组织。
1.qemu-kvm提供的virtio pci设备
virtio-blk(硬盘),virtio-net(网络),virtio-balloon(气球)等pci设备,这些设备连接在pci总线上。代码位于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.客户机PCI设备进行枚举和资源分配
当Linux客户机系统启动时,对PCI设备进行枚举和资源分配(配置PCI的配置空间),通常由BIOS完成。不过对Linux系统提供方式,一种由BIOS实现,另一种自己实现枚举和资源分配功能。代码位于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
}
真正设备枚举和资源分配由这里开始
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()
将PCI总线上的设备添加到链表
void pci_device_add(struct pci_dev *dev, struct pci_bus *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);
}
上述过程执行完成,在/sys/devices/pci0000:00目录下,创建virtio pci设备。并且在/sys/bus/pci/devices/目录下,创建相应对于pci设备的符号连接,同时在/sys/bus/pci/drivers/目录下,创建virtio-pci目录,目录下存在支持设备符号连接文件。
3.virtio总线定义与注册,virtio总线为虚拟的总线,目的为了设备管理与组织需要。代码位于:
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)