追蹤QEMU中PCI設備的初始化過程



首先需要知道的一些背景知識:PCI是總線的名稱,同時也可以是一個PCI bridge,這個bridge就是一個設備了。在這個bridge上可以掛多種PCI設備,例如virtio-block,virtio-net等設備,這些block或者net設備邏輯上掛載到PCI總線上,物理上連接到PCI bridge上。

pci_qdev_realize這個函數位置設置斷點。
bt棧如下:

Thread 1 "qemu-system-x86" hit Breakpoint 1, pci_qdev_realize (qdev=0x555556cb67f0, errp=0x7fffffffda40) at hw/pci/pci.c:2070
2070	{
(gdb) bt
#0  pci_qdev_realize (qdev=0x555556cb67f0, errp=0x7fffffffda40) at hw/pci/pci.c:2070
#1  0x0000555555a68aae in device_set_realized (obj=0x555556cb67f0, value=true, errp=0x7fffffffdc00) at hw/core/qdev.c:834
#2  0x0000555555c4ba4f in property_set_bool (obj=0x555556cb67f0, v=0x555556cbb020, name=0x555555f6aa11 "realized", opaque=0x555556c7fdb0,
    errp=0x7fffffffdc00) at qom/object.c:2079
#3  0x0000555555c49cb9 in object_property_set (obj=0x555556cb67f0, v=0x555556cbb020, name=0x555555f6aa11 "realized", errp=0x7fffffffdc00)
    at qom/object.c:1271
#4  0x0000555555c4cdc4 in object_property_set_qobject (obj=0x555556cb67f0, value=0x555556cbaf70, name=0x555555f6aa11 "realized", errp=0x7fffffffdc00)
    at qom/qom-qobject.c:26
#5  0x0000555555c49f97 in object_property_set_bool (obj=0x555556cb67f0, value=true, name=0x555555f6aa11 "realized", errp=0x7fffffffdc00)
    at qom/object.c:1337
#6  0x0000555555a67790 in qdev_init_nofail (dev=0x555556cb67f0) at hw/core/qdev.c:321
#7  0x0000555555b224c2 in pci_create_simple_multifunction (bus=0x555556c7f270, devfn=0, multifunction=false, name=0x555555f35b65 "i440FX")
    at hw/pci/pci.c:2131
#8  0x0000555555b22526 in pci_create_simple (bus=0x555556c7f270, devfn=0, name=0x555555f35b65 "i440FX") at hw/pci/pci.c:2142
#9  0x0000555555b199fe in i440fx_init (host_type=0x555555f35b6c "i440FX-pcihost", pci_type=0x555555f35b65 "i440FX", pi440fx_state=0x7fffffffdda8,
    piix3_devfn=0x7fffffffdd98, isa_bus=0x7fffffffdda0, pic=0x555556c7b5a0, address_space_mem=0x5555569b1a90, address_space_io=0x5555569b2510,
    ram_size=4294967296, below_4g_mem_size=3221225472, above_4g_mem_size=1073741824, pci_address_space=0x555556a60be0, ram_memory=0x555556a612d0)
    at hw/pci-host/piix.c:384
#10 0x0000555555937e59 in pc_init1 (machine=0x5555569ad800, host_type=0x555555f35b6c "i440FX-pcihost", pci_type=0x555555f35b65 "i440FX")
    at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:201
#11 0x00005555559387e3 in pc_init_v4_1 (machine=0x5555569ad800) at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:445
#12 0x0000555555a71a49 in machine_run_board_init (machine=0x5555569ad800) at hw/core/machine.c:1132
#13 0x00005555559fe083 in main (argc=25, argv=0x7fffffffe208, envp=0x7fffffffe2d8) at vl.c:4348

其中需要注意的是相關的realized函數是在xxx_xxx_class_init()函數中設定的。例如,

static void pci_device_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *k = DEVICE_CLASS(klass);

    k->realize = pci_qdev_realize;
    k->unrealize = pci_qdev_unrealize;
    k->bus_type = TYPE_PCI_BUS;
    k->props = pci_props;
}
1. 初始化i440FX
Thread 1 "qemu-system-x86" hit Breakpoint 1, pci_create_simple (bus=0x555556c7f270, devfn=0, name=0x555555f35b65 "i440FX") at hw/pci/pci.c:2142
#0  pci_create_simple (bus=0x555556c7f270, devfn=0, name=0x555555f35b65 "i440FX") at hw/pci/pci.c:2142
#1  0x0000555555b199fe in i440fx_init (host_type=0x555555f35b6c "i440FX-pcihost", pci_type=0x555555f35b65 "i440FX", pi440fx_state=0x7fffffffdda8,
    piix3_devfn=0x7fffffffdd98, isa_bus=0x7fffffffdda0, pic=0x555556c7b5a0, address_space_mem=0x5555569b1a90, address_space_io=0x5555569b2510,
    ram_size=4294967296, below_4g_mem_size=3221225472, above_4g_mem_size=1073741824, pci_address_space=0x555556a60be0, ram_memory=0x555556a612d0)
    at hw/pci-host/piix.c:384
#2  0x0000555555937e59 in pc_init1 (machine=0x5555569ad800, host_type=0x555555f35b6c "i440FX-pcihost", pci_type=0x555555f35b65 "i440FX")
    at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:201
#3  0x00005555559387e3 in pc_init_v4_1 (machine=0x5555569ad800) at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:445
#4  0x0000555555a71a49 in machine_run_board_init (machine=0x5555569ad800) at hw/core/machine.c:1132
#5  0x00005555559fe083 in main (argc=25, argv=0x7fffffffe208, envp=0x7fffffffe2d8) at vl.c:4348

2. 初始化VGA PCI設備
Thread 1 "qemu-system-x86" hit Breakpoint 1, pci_create_simple (bus=0x555556c7f270, devfn=-1, name=0x555555fab6df "VGA") at hw/pci/pci.c:2142
2142        return pci_create_simple_multifunction(bus, devfn, false, name);
(gdb) bt
#0  pci_create_simple (bus=0x555556c7f270, devfn=-1, name=0x555555fab6df "VGA") at hw/pci/pci.c:2142
#1  0x0000555555b21e97 in pci_vga_init (bus=0x555556c7f270) at hw/pci/pci.c:1951
#2  0x0000555555934085 in pc_vga_init (isa_bus=0x555556ffea70, pci_bus=0x555556c7f270) at /root/code/qemu-4.1.0/hw/i386/pc.c:1975
#3  0x000055555593801a in pc_init1 (machine=0x5555569ad800, host_type=0x555555f35b6c "i440FX-pcihost", pci_type=0x555555f35b65 "i440FX")
    at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:236
#4  0x00005555559387e3 in pc_init_v4_1 (machine=0x5555569ad800) at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:445
#5  0x0000555555a71a49 in machine_run_board_init (machine=0x5555569ad800) at hw/core/machine.c:1132
#6  0x00005555559fe083 in main (argc=25, argv=0x7fffffffe208, envp=0x7fffffffe2d8) at vl.c:4348

3. 初始化芯片組PIIX3(控制IO)
Thread 1 "qemu-system-x86" hit Breakpoint 1, pci_create_simple (bus=0x555556c7f270, devfn=9, name=0x555555f7240c "piix3-ide") at hw/pci/pci.c:2142
2142        return pci_create_simple_multifunction(bus, devfn, false, name);
(gdb) bt
#0  pci_create_simple (bus=0x555556c7f270, devfn=9, name=0x555555f7240c "piix3-ide") at hw/pci/pci.c:2142
#1  0x0000555555ab8dc3 in pci_piix3_ide_init (bus=0x555556c7f270, hd_table=0x7fffffffde50, devfn=9) at hw/ide/piix.c:229
#2  0x0000555555938172 in pc_init1 (machine=0x5555569ad800, host_type=0x555555f35b6c "i440FX-pcihost", pci_type=0x555555f35b65 "i440FX")
    at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:256
#3  0x00005555559387e3 in pc_init_v4_1 (machine=0x5555569ad800) at /root/code/qemu-4.1.0/hw/i386/pc_piix.c:445
#4  0x0000555555a71a49 in machine_run_board_init (machine=0x5555569ad800) at hw/core/machine.c:1132
#5  0x00005555559fe083 in main (argc=25, argv=0x7fffffffe208, envp=0x7fffffffe2d8) at vl.c:4348

 命令行參數:
-device virtio-blk-pci,iothread=iothreadxxx1,scsi=off,bus=pci.0,addr=0x6,drive=drive-virtio-disk1,id=virtio-disk0,disable-modern=off,disable-legacy=on \
-drive format=raw,if=none,id=drive-virtio-disk1,cache=directsync,file=/data/rootfs.img,aio=native \

對應的流程如下:

1. 初始化virtio-pci的流程

#0  pci_qdev_realize (qdev=0x55555789a4c0, errp=0x7fffffffdc30) at hw/pci/pci.c:2073
#1  0x0000555555bae9e5 in virtio_pci_dc_realize (qdev=0x55555789a4c0, errp=0x7fffffffdc30) at hw/virtio/virtio-pci.c:1859
#2  0x0000555555a68aae in device_set_realized (obj=0x55555789a4c0, value=true, errp=0x7fffffffde10) at hw/core/qdev.c:834
#3  0x0000555555c4ba4f in property_set_bool (obj=0x55555789a4c0, v=0x5555578a7be0, name=0x555555f500f2 "realized", opaque=0x55555789a030,
    errp=0x7fffffffde10) at qom/object.c:2079
#4  0x0000555555c49cb9 in object_property_set (obj=0x55555789a4c0, v=0x5555578a7be0, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/object.c:1271
#5  0x0000555555c4cdc4 in object_property_set_qobject (obj=0x55555789a4c0, value=0x5555578a7840, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/qom-qobject.c:26
#6  0x0000555555c49f97 in object_property_set_bool (obj=0x55555789a4c0, value=true, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/object.c:1337
#7  0x00005555559f146b in qdev_device_add (opts=0x5555568fae30, errp=0x555556859010 <error_fatal>) at qdev-monitor.c:634
#8  0x00005555559f916b in device_init_func (opaque=0x0, opts=0x5555568fae30, errp=0x555556859010 <error_fatal>) at vl.c:2191
#9  0x0000555555d9b5bb in qemu_opts_foreach (list=0x555556676040 <qemu_device_opts>, func=0x5555559f9144 <device_init_func>, opaque=0x0,
    errp=0x555556859010 <error_fatal>) at util/qemu-option.c:1170
#10 0x00005555559fe128 in main (argc=25, argv=0x7fffffffe208, envp=0x7fffffffe2d8) at vl.c:4372

繼續追蹤到virtio-blk設備的realize,如下:

Thread 1 "qemu-system-x86" hit Breakpoint 1, virtio_blk_pci_realize (vpci_dev=0x55555789a4c0, errp=0x7fffffffdb78)
    at /root/code/qemu-4.1.0/hw/virtio/virtio-blk-pci.c:50
50          VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev);
(gdb) bt
#0  virtio_blk_pci_realize (vpci_dev=0x55555789a4c0, errp=0x7fffffffdb78) at /root/code/qemu-4.1.0/hw/virtio/virtio-blk-pci.c:50
#1  0x0000555555bae634 in virtio_pci_realize (pci_dev=0x55555789a4c0, errp=0x7fffffffdb78) at hw/virtio/virtio-pci.c:1788
#2  0x0000555555b22308 in pci_qdev_realize (qdev=0x55555789a4c0, errp=0x7fffffffdc30) at hw/pci/pci.c:2092
#3  0x0000555555bae9e5 in virtio_pci_dc_realize (qdev=0x55555789a4c0, errp=0x7fffffffdc30) at hw/virtio/virtio-pci.c:1859
#4  0x0000555555a68aae in device_set_realized (obj=0x55555789a4c0, value=true, errp=0x7fffffffde10) at hw/core/qdev.c:834
#5  0x0000555555c4ba4f in property_set_bool (obj=0x55555789a4c0, v=0x5555578a7be0, name=0x555555f500f2 "realized", opaque=0x55555789a030,
    errp=0x7fffffffde10) at qom/object.c:2079
#6  0x0000555555c49cb9 in object_property_set (obj=0x55555789a4c0, v=0x5555578a7be0, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/object.c:1271
#7  0x0000555555c4cdc4 in object_property_set_qobject (obj=0x55555789a4c0, value=0x5555578a7840, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/qom-qobject.c:26
#8  0x0000555555c49f97 in object_property_set_bool (obj=0x55555789a4c0, value=true, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/object.c:1337
#9  0x00005555559f146b in qdev_device_add (opts=0x5555568fae30, errp=0x555556859010 <error_fatal>) at qdev-monitor.c:634
#10 0x00005555559f916b in device_init_func (opaque=0x0, opts=0x5555568fae30, errp=0x555556859010 <error_fatal>) at vl.c:2191
--Type <RET> for more, q to quit, c to continue without paging--
#11 0x0000555555d9b5bb in qemu_opts_foreach (list=0x555556676040 <qemu_device_opts>, func=0x5555559f9144 <device_init_func>, opaque=0x0,
    errp=0x555556859010 <error_fatal>) at util/qemu-option.c:1170
#12 0x00005555559fe128 in main (argc=25, argv=0x7fffffffe208, envp=0x7fffffffe2d8) at vl.c:4372


--------------------------------------------

Thread 1 "qemu-system-x86" hit Breakpoint 1, virtio_blk_device_realize (dev=0x5555578a2630, errp=0x7fffffffd8e0)
    at /root/code/qemu-4.1.0/hw/block/virtio-blk.c:1097
1097    {
(gdb) bt
#0  virtio_blk_device_realize (dev=0x5555578a2630, errp=0x7fffffffd8e0) at /root/code/qemu-4.1.0/hw/block/virtio-blk.c:1097
#1  0x000055555591a452 in virtio_device_realize (dev=0x5555578a2630, errp=0x7fffffffd940) at /root/code/qemu-4.1.0/hw/virtio/virtio.c:2613
#2  0x0000555555a68aae in device_set_realized (obj=0x5555578a2630, value=true, errp=0x7fffffffdb78) at hw/core/qdev.c:834
#3  0x0000555555c4ba4f in property_set_bool (obj=0x5555578a2630, v=0x5555578a5fc0, name=0x555555f32f98 "realized", opaque=0x5555578a3cf0,
    errp=0x7fffffffdb78) at qom/object.c:2079
#4  0x0000555555c49cb9 in object_property_set (obj=0x5555578a2630, v=0x5555578a5fc0, name=0x555555f32f98 "realized", errp=0x7fffffffdb78)
    at qom/object.c:1271
#5  0x0000555555c4cdc4 in object_property_set_qobject (obj=0x5555578a2630, value=0x5555578a5f10, name=0x555555f32f98 "realized", errp=0x7fffffffdb78)
    at qom/qom-qobject.c:26
#6  0x0000555555c49f97 in object_property_set_bool (obj=0x5555578a2630, value=true, name=0x555555f32f98 "realized", errp=0x7fffffffdb78)
    at qom/object.c:1337
#7  0x000055555592dbc4 in virtio_blk_pci_realize (vpci_dev=0x55555789a4c0, errp=0x7fffffffdb78) at /root/code/qemu-4.1.0/hw/virtio/virtio-blk-pci.c:58
#8  0x0000555555bae634 in virtio_pci_realize (pci_dev=0x55555789a4c0, errp=0x7fffffffdb78) at hw/virtio/virtio-pci.c:1788
#9  0x0000555555b22308 in pci_qdev_realize (qdev=0x55555789a4c0, errp=0x7fffffffdc30) at hw/pci/pci.c:2092
#10 0x0000555555bae9e5 in virtio_pci_dc_realize (qdev=0x55555789a4c0, errp=0x7fffffffdc30) at hw/virtio/virtio-pci.c:1859
#11 0x0000555555a68aae in device_set_realized (obj=0x55555789a4c0, value=true, errp=0x7fffffffde10) at hw/core/qdev.c:834
#12 0x0000555555c4ba4f in property_set_bool (obj=0x55555789a4c0, v=0x5555578a7be0, name=0x555555f500f2 "realized", opaque=0x55555789a030,
    errp=0x7fffffffde10) at qom/object.c:2079
--Type <RET> for more, q to quit, c to continue without paging--
#13 0x0000555555c49cb9 in object_property_set (obj=0x55555789a4c0, v=0x5555578a7be0, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/object.c:1271
#14 0x0000555555c4cdc4 in object_property_set_qobject (obj=0x55555789a4c0, value=0x5555578a7840, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/qom-qobject.c:26
#15 0x0000555555c49f97 in object_property_set_bool (obj=0x55555789a4c0, value=true, name=0x555555f500f2 "realized", errp=0x7fffffffde10)
    at qom/object.c:1337
#16 0x00005555559f146b in qdev_device_add (opts=0x5555568fae30, errp=0x555556859010 <error_fatal>) at qdev-monitor.c:634
#17 0x00005555559f916b in device_init_func (opaque=0x0, opts=0x5555568fae30, errp=0x555556859010 <error_fatal>) at vl.c:2191
#18 0x0000555555d9b5bb in qemu_opts_foreach (list=0x555556676040 <qemu_device_opts>, func=0x5555559f9144 <device_init_func>, opaque=0x0,
    errp=0x555556859010 <error_fatal>) at util/qemu-option.c:1170
#19 0x00005555559fe128 in main (argc=25, argv=0x7fffffffe208, envp=0x7fffffffe2d8) at vl.c:4372
(gdb)

參考文獻:
https://github.com/GiantVM/doc/blob/master/pci.md
https://dangokyo.me/2018/03/28/qemu-internal-pci-device/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM