kvm qemu世界中的pci总线与virtio总线-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 1560867
  • 博文数量: 77
  • 博客积分: 1205
  • 博客等级: 少尉
  • 技术积分: 4476
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-22 21:48
文章分类
文章存档

2018年(1)

2017年(1)

2015年(1)

2014年(18)

2013年(12)

2012年(44)

相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: 虚拟化

2014-09-12 11:33:27

这篇文章的背景是通过9p文件系统在host os与guest os间共享一个目录,或许更专业点的叫法是file system passthru. 因此需要配置guest os中linux内核,使之支持下面的选项(.config)

config_net_9p=y

config_net_9p_virtio=m

config_9p_fs=y

config_9p_fs_posix_acl=y

但是本文不讨论如何使用9p文件系统来达成这一目标的具体步骤,而是讨论其幕后实现中的一个技术细节:pci总线与virtio总线的关系。

在上述的背景下,如果我们使用qemu命令行来启动一个vm,在命令行中加入类似: -device virtio-9p-pci 这样的参数选项时, 那么在guest os中不但在/sys/bus/pci/devices中出现一个对应的pci设备,而且在/sys/bus/virtio/devices中也会出现一个virtio类型设备。


我们知道pci总线是现代计算机体系结构中普遍存在的一个物理总线,而virtio总线则纯粹是软件定义的,在kvm qemu的世界里,两者之间到底是何关系?或者假设我们现在想在qemu kvm中添加一个新的virtio设备及其驱动,应该怎么做?

 

通常,guest os在初始化过程中会扫描pci bus num = 0的host bridge,也就是北桥,通过它来发现其下挂载的一系列pci设备(包括桥设备),所以我们想添加的的新的virtio设备必须对外展现出一个pci的接口。因为host bridge本身就是靠qemu模拟出来的,所以在qemu中模拟一个新的pci设备也是很简单的事情。如果qemu成功模拟了一个挂在host bridge上的pci设备,那么guest os将会通过pci总线扫描发现之,继而通过device_add函数把该设备添加到系统中,这将导致:
1. 在guest os中的/sys/bus/pci/devices目录下出现一个新的pci设备(被qemu模拟出的)  
2. 在guest os中与该pci设备对应的驱动程序将会被加载(围绕着pci总线的bind)。

 

到目前为止,都是pci的作用范围,跟virtio总线没有什么关系。那么guest os中/sys/bus/virtio/devices下面出现的设备及其驱动又是如何产生的?

 

答案是pci设备驱动中定义的virtio_pci_probe().  在drivers/virtio/virtio_pci.c中:

 

/* qumranet donated their vendor id for devices 0x1000 thru 0x10ff. */

static define_pci_device_table(virtio_pci_id_table) = {

{ pci_device(0x1af4, pci_any_id) },

{ 0 }

};

 

module_device_table(pci, virtio_pci_id_table);

 

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_sleep

.driver.pm        = &virtio_pci_pm_ops,

#endif

};

 

virtio-pci的vendor id是0x1af4, 这个是当初开发kvm的qumranet公司pci vendor id。所以,如果在qemu侧模拟一个pci设备,其vendor id=0x1af4,那么当guest os扫描到该设备时,将会将其加入到系统,于是使得上述的virtio_pci_driver被加载,该过程导致在/sys/bus/pci/devices中出现一个vendor id = 0x1af4的pci设备,同时该设备指向一个名为"virtio-pci"的驱动程序。这期间很重要的一个环节是"virtio-pci"驱动中的.probe成员,也即virtio_pci_probe().

 

在virtio_pci_probe()函数中,它将调用register_virtio_device(),后者将把一个virtio类型(struct  virtio_device)的设备加入到系统,由于该设备所属的总线是virtio bus(源码在drivers/virtio/virtio.c), 导致/sys/bus/virtio/devices/目录下出现一个新的设备:

int register_virtio_device(struct virtio_device *dev)

{

dev->dev.bus = &virtio_bus;

}

 

所以围绕virtio bus导致该设备的驱动被加载。(以上的过程很类似一个pci接口的fc hba卡的驱动模式:先pci总线,后scsi总线).这个virtio_device的设备驱动定义在net/9p/trans_virtio.c中。

因为os启动过程中会扫描pci总线,所以必要使得一个设备先能被系统识别(基于pci),然后再做下一步的处理(基于scsi或者virtio...)。更形象地说,一个披着羊皮的狼才能被羊群所接纳,然后再脱掉羊皮变成狼,显现狼的行为。

阅读(21929) | 评论(1) | 转发(6) |
给主人留下些什么吧!~~

2014-09-26 11:39:55

好文啊,我表示是来学习的

|
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图