searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Qemu Vfio代码分析

2022-12-29 10:19:49
175
0

Vfio初始化:

Vfio实例:qemu-kvm -m 16G -smp 8 -net none -device vfio-pci,host=0000:81:10.0

初始化入口函数vfio_realize是从vfio pci classclass init函数vfio_pci_dev_class_init 初始化。

调用栈:

Breakpoint 1, vfio_realize (pdev=0x555557874d00, errp=0x7fffffffdde0) at /usr/src/debug/qemu-kvm-2.12.0/hw/vfio/pci.c:2801

2801 {

(gdb) bt

#0 0x00005555558df180 in vfio_realize (pdev=0x555557874d00, errp=0x7fffffffdde0) at /usr/src/debug/qemu-kvm-2.12.0/hw/vfio/pci.c:2801

#1 0x0000555555a292c1 in pci_qdev_realize (qdev=0x555557874d00, errp=0x7fffffffde80) at hw/pci/pci.c:2028

#2 0x00005555559c849b in device_set_realized (obj=<optimized out>, value=<optimized out>, errp=0x7fffffffdfb8) at hw/core/qdev.c:852

#3 0x0000555555abf5ae in property_set_bool (obj=0x555557874d00, v=<optimized out>, name=<optimized out>, opaque=0x55555882f180, errp=0x7fffffffdfb8) at qom/object.c:1925

#4 0x0000555555ac35df in object_property_set_qobject (obj=0x555557874d00, value=<optimized out>, name=0x555555c72fcf "realized", errp=0x7fffffffdfb8) at qom/qom-qobject.c:27

#5 0x0000555555ac11d5 in object_property_set_bool (obj=0x555557874d00, value=<optimized out>, name=0x555555c72fcf "realized", errp=0x7fffffffdfb8) at qom/object.c:1188

#6 0x0000555555971519 in qdev_device_add (opts=0x555557042f00, errp=errp@entry=0x7fffffffe090) at qdev-monitor.c:626

#7 0x0000555555973807 in device_init_func (opaque=<optimized out>, opts=<optimized out>, errp=<optimized out>) at vl.c:2383

#8 0x0000555555bad33a in qemu_opts_foreach (list=<optimized out>, func=func@entry=0x5555559737e0 <device_init_func>, opaque=opaque@entry=0x0, errp=errp@entry=0x0) at util/qemu-option.c:1104

#9 0x0000555555841277 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4667

关键函数分析:入参是vfio设备的pci bfd,通过/sys/目录找到该设备对应的iommu group id,然后调用vfio_get_group

通过内核提供的/dev/vfio/group接口获取groupfd,在vfio_connect_container打开/dev/vfio/vfio获取containerfd, 在vfio_init_container中将groud放置在container中,并且获取iommu的类型。然后再根据iommu获取具体的iommu信息,设置host winiommupagesize等。

vfio_kvm_device_add_groupvfio设备信息注册给内核的kvm模块。

Container有一个listener,将监听内存的变化情况,在register的时候会触发listenerregion_add函数,将虚拟内存信息注册到内核iommu,建立相应地址空间映射。这部分内容后面再详细描述。

接下来的是vfio_populate_device,填充pci信息,主要是进行一些基本检查,搜集bar信息,pci配置空间。

Vfio_region_setup中先获取region信息,然后初始化region对应的内存访问操作vfio_region_ops, 以及支持mmap

Vfio_region_ops, 根据regionoffset,通过内核提供的ioctl接口进行读写

读取硬件的pci配置空间信息来填充vfio设备的pci空间,并根据需要设置vfio需要模拟的空间

设置bar信息:vfio_bars_prepare

初始化msixvfio_msix_early_setup, 发现硬件的msix能力,根据msi相关信息,主要是msi table baroffsetpending interrupt baroffset等。并根据msi的需要的bar调整其空间大小,bar设备的访问需要单独模拟,不能直接对硬件设备进行操作。

Vfio bar register:初始化barmr,这个是整个bar空间的container,添加之前的region.mem, 并进行mmap

最后调用pci_register_bar注册bar信息。

vfio_add_capabilities: 添加pci设备的capabilities,主要分成stdext的,std中最重要的msi中断相关的:vfio_msix_setupext基本透传,除了sriov等特性外

Msix初始化:pci设备的msix tableregion访问将由msix_table_mmio_ops提供,这部分的功能后面再详细分析。

vfio_pci_dev_class_init在初始过程中,还初始化将pci 配置空间的读写初始化跟vfio相关的。

Bar空间的映射:

系统在初始化期间,会对pci总线进行扫描和配置,驱动会根据bar的信息分配相应的地址空间等,qemu默认的pci框架实现了对bar访问的操作。

Pci_update_mappings 根据驱动写入的地址进行映射。

0条评论
0 / 1000
阳****光
1文章数
0粉丝数
阳****光
1 文章 | 0 粉丝
阳****光
1文章数
0粉丝数
阳****光
1 文章 | 0 粉丝
原创

Qemu Vfio代码分析

2022-12-29 10:19:49
175
0

Vfio初始化:

Vfio实例:qemu-kvm -m 16G -smp 8 -net none -device vfio-pci,host=0000:81:10.0

初始化入口函数vfio_realize是从vfio pci classclass init函数vfio_pci_dev_class_init 初始化。

调用栈:

Breakpoint 1, vfio_realize (pdev=0x555557874d00, errp=0x7fffffffdde0) at /usr/src/debug/qemu-kvm-2.12.0/hw/vfio/pci.c:2801

2801 {

(gdb) bt

#0 0x00005555558df180 in vfio_realize (pdev=0x555557874d00, errp=0x7fffffffdde0) at /usr/src/debug/qemu-kvm-2.12.0/hw/vfio/pci.c:2801

#1 0x0000555555a292c1 in pci_qdev_realize (qdev=0x555557874d00, errp=0x7fffffffde80) at hw/pci/pci.c:2028

#2 0x00005555559c849b in device_set_realized (obj=<optimized out>, value=<optimized out>, errp=0x7fffffffdfb8) at hw/core/qdev.c:852

#3 0x0000555555abf5ae in property_set_bool (obj=0x555557874d00, v=<optimized out>, name=<optimized out>, opaque=0x55555882f180, errp=0x7fffffffdfb8) at qom/object.c:1925

#4 0x0000555555ac35df in object_property_set_qobject (obj=0x555557874d00, value=<optimized out>, name=0x555555c72fcf "realized", errp=0x7fffffffdfb8) at qom/qom-qobject.c:27

#5 0x0000555555ac11d5 in object_property_set_bool (obj=0x555557874d00, value=<optimized out>, name=0x555555c72fcf "realized", errp=0x7fffffffdfb8) at qom/object.c:1188

#6 0x0000555555971519 in qdev_device_add (opts=0x555557042f00, errp=errp@entry=0x7fffffffe090) at qdev-monitor.c:626

#7 0x0000555555973807 in device_init_func (opaque=<optimized out>, opts=<optimized out>, errp=<optimized out>) at vl.c:2383

#8 0x0000555555bad33a in qemu_opts_foreach (list=<optimized out>, func=func@entry=0x5555559737e0 <device_init_func>, opaque=opaque@entry=0x0, errp=errp@entry=0x0) at util/qemu-option.c:1104

#9 0x0000555555841277 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4667

关键函数分析:入参是vfio设备的pci bfd,通过/sys/目录找到该设备对应的iommu group id,然后调用vfio_get_group

通过内核提供的/dev/vfio/group接口获取groupfd,在vfio_connect_container打开/dev/vfio/vfio获取containerfd, 在vfio_init_container中将groud放置在container中,并且获取iommu的类型。然后再根据iommu获取具体的iommu信息,设置host winiommupagesize等。

vfio_kvm_device_add_groupvfio设备信息注册给内核的kvm模块。

Container有一个listener,将监听内存的变化情况,在register的时候会触发listenerregion_add函数,将虚拟内存信息注册到内核iommu,建立相应地址空间映射。这部分内容后面再详细描述。

接下来的是vfio_populate_device,填充pci信息,主要是进行一些基本检查,搜集bar信息,pci配置空间。

Vfio_region_setup中先获取region信息,然后初始化region对应的内存访问操作vfio_region_ops, 以及支持mmap

Vfio_region_ops, 根据regionoffset,通过内核提供的ioctl接口进行读写

读取硬件的pci配置空间信息来填充vfio设备的pci空间,并根据需要设置vfio需要模拟的空间

设置bar信息:vfio_bars_prepare

初始化msixvfio_msix_early_setup, 发现硬件的msix能力,根据msi相关信息,主要是msi table baroffsetpending interrupt baroffset等。并根据msi的需要的bar调整其空间大小,bar设备的访问需要单独模拟,不能直接对硬件设备进行操作。

Vfio bar register:初始化barmr,这个是整个bar空间的container,添加之前的region.mem, 并进行mmap

最后调用pci_register_bar注册bar信息。

vfio_add_capabilities: 添加pci设备的capabilities,主要分成stdext的,std中最重要的msi中断相关的:vfio_msix_setupext基本透传,除了sriov等特性外

Msix初始化:pci设备的msix tableregion访问将由msix_table_mmio_ops提供,这部分的功能后面再详细分析。

vfio_pci_dev_class_init在初始过程中,还初始化将pci 配置空间的读写初始化跟vfio相关的。

Bar空间的映射:

系统在初始化期间,会对pci总线进行扫描和配置,驱动会根据bar的信息分配相应的地址空间等,qemu默认的pci框架实现了对bar访问的操作。

Pci_update_mappings 根据驱动写入的地址进行映射。

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0