20.PCI代码导读-2.驱动初始化流程-流程总览-《计算机知识》

admin 2025-11-02 22:25:01 系统网络 来源:ZONE.CI 全球网 0 阅读模式
  • 基础知识(复习)
    • 如何查看当前系统配置CONFIG
    • 如何查看当前系统System.map
    • 模块加载过程
  • 初始化代码流程
    • 代码初始化总览
    • 代码目录
    • 流程总览
    • 初始化的两个阶段
  • Ubuntu 18.04下的一些配置

    基础知识(复习)

    如何查看当前系统配置CONFIG

    1. # 方法1:需要内核使能 CONFIG_IKCONFIG_PROC
    2. sudo modprobe configs
    3. zcat /proc/config.gz
    4. # 方法2:直接看
    5. cat /boot/config-$(uname -r)

    如何查看当前系统System.map

    Ubuntu会把System.map文件放到/boot目录下,有的可能在源码目录:

    1. inno@DEV-005:~$ ls /usr/src/linux-headers-$(uname -r)
    2. arch block .....
    3. inno@DEV-005:~$ ls /boot/System.map-$(uname -r)
    4. /boot/System.map-5.4.0-47-generic

    模块加载过程

    复习-initcall全过程

    1. 调用过程
    2. rest_init
    3. kernel_init # 进程1加载的驱动模块
    4. kernel_init_freeable
    5. do_basic_setup
    6. driver_init(); // 驱动架构初始化
    7. do_initcalls(); // initcalls初始化
    8. 调用级别
    9. #define pure_initcall(fn) __define_initcall("0",fn,0)
    10. #define core_initcall(fn) __define_initcall("1",fn,1)
    11. #define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
    12. #define postcore_initcall(fn) __define_initcall("2",fn,2)
    13. #define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
    14. #define arch_initcall(fn) __define_initcall("3",fn,3)
    15. #define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)
    16. #define subsys_initcall(fn) __define_initcall("4",fn,4)
    17. #define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
    18. #define fs_initcall(fn) __define_initcall("5",fn,5)
    19. #define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
    20. #define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
    21. #define device_initcall(fn) __define_initcall("6",fn,6)
    22. #define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
    23. #define late_initcall(fn) __define_initcall("7",fn,7)
    24. #define late_initcall_sync(fn) __define_initcall("7s",fn,7s)

    初始化代码流程

    参考好文:

    • PCI总线的初始化
    • PCI驱动框架简单分析

    注:这部分代码暂时绕过ACPI的枚举过程,下一章节详解

    代码初始化总览

    1. [baiy@test pci]$ pwd
    2. /home/public/baiy/linux/x86/linux-5.7.14/drivers/pci
    3. [baiy@test pci]$ grep -nr "_initcall"
    4. pci-acpi.c:1360:arch_initcall(acpi_pci_init);
    5. pci-driver.c:1681:postcore_initcall(pci_driver_init);
    6. pci-mid.c:77:arch_initcall(mid_pci_init);
    7. pci-sysfs.c:1453:late_initcall(pci_sysfs_init);
    8. pci.c:6389:late_initcall(pci_resource_alignment_sysfs_init);
    9. pci.c:6564:pure_initcall(pci_realloc_setup_params);
    10. pcie/portdrv_pci.c:264:device_initcall(pcie_portdrv_init);
    11. probe.c:108:postcore_initcall(pcibus_class_init);
    12. proc.c:462:device_initcall(pci_proc_init);
    13. quirks.c:193:fs_initcall_sync(pci_apply_final_quirks);
    14. slot.c:377:subsys_initcall(pci_slot_init);
    15. [baiy@test pci]$ pwd
    16. /home/public/baiy/linux/x86/linux-5.7.14/arch/x86/pci
    17. [baiy@test pci]$ grep -nr "_initcall"
    18. i386.c:373:fs_initcall(pcibios_assign_resources);
    19. init.c:45:arch_initcall(pci_arch_init);
    20. legacy.c:77:subsys_initcall(pci_subsys_init);
    21. mmconfig-shared.c:718:late_initcall(pci_mmcfg_late_insert_resources);
    22. # 或者执行 cat /proc/kallsyms | grep pci | grep initcall
    23. # 或者执行 cat /proc/System.map | grep pci | grep initcall
    24. [baiy@test pci]$ cat /proc/kallsyms | grep pci | grep initcall # 忘了加sudo,所以地址都是0
    25. 0000000000000000 t __initcall_pci_realloc_setup_params0
    26. 0000000000000000 t __initcall_pcibus_class_init2
    27. 0000000000000000 t __initcall_pci_driver_init2
    28. 0000000000000000 t __initcall_acpi_pci_init3
    29. 0000000000000000 t __initcall_register_xen_pci_notifier3
    30. 0000000000000000 t __initcall_pci_arch_init3
    31. 0000000000000000 t __initcall_pci_slot_init4
    32. 0000000000000000 t __initcall_pci_subsys_init4
    33. 0000000000000000 t __initcall_pci_eisa_init_early4s
    34. 0000000000000000 t __initcall_pcibios_assign_resources5
    35. 0000000000000000 t __initcall_pci_apply_final_quirks5s
    36. 0000000000000000 t __initcall_pci_iommu_initrootfs
    37. 0000000000000000 t __initcall_pwm_lpss_driver_pci_init6
    38. 0000000000000000 t __initcall_pci_proc_init6
    39. 0000000000000000 t __initcall_pcie_portdrv_init6
    40. 0000000000000000 t __initcall_pci_hotplug_init6
    41. 0000000000000000 t __initcall_pci_ep_cfs_init6
    42. 0000000000000000 t __initcall_pci_epc_init6
    43. 0000000000000000 t __initcall_pci_epf_init6
    44. 0000000000000000 t __initcall_dw_plat_pcie_driver_init6
    45. 0000000000000000 t __initcall_virtio_pci_driver_init6
    46. 0000000000000000 t __initcall_serial_pci_driver_init6
    47. 0000000000000000 t __initcall_sis_pci_driver_init6
    48. 0000000000000000 t __initcall_ata_generic_pci_driver_init6
    49. 0000000000000000 t __initcall_vfio_pci_init6
    50. 0000000000000000 t __initcall_ehci_pci_init6
    51. 0000000000000000 t __initcall_ohci_pci_init6
    52. 0000000000000000 t __initcall_xhci_pci_init6
    53. 0000000000000000 t __initcall_pci_resource_alignment_sysfs_init7
    54. 0000000000000000 t __initcall_pci_sysfs_init7
    55. 0000000000000000 t __initcall_pci_mmcfg_late_insert_resources7

    然后我们根据加载顺序配合System.map开始看就好,ACPI牵扯到上电过程,后边详解。

    代码目录

    x86的PCI代码集中在两个目录

    arch/x86/pci driver/x86/pci

    流程总览

    这里为了以后复习,总览下代码

    2.驱动初始化流程-流程总览 - 图12.驱动初始化流程-流程总览 - 图2

    初始化的两个阶段

    第一阶段(PCI基础环境搭建):

    • MMC config基础地址初始化 pci_mmconfig_add
    • 获取系统启动的pci命令行参数 pci_setup
    • 注册/sys/class/pci_bus接口 pcibus_class_init
    • 注册/sys/bus/pci和/sys/bus/pci_express设备总线 pci_driver_init (重点,sysfs下的信息)
    • 检测PCI 总线0,校验主桥,并占用X86对PCI访问IO端口,设置访问函数 pci_arch_init (重点)

    第二阶段(ACPI初始化,重点):

    • 初始化PCI的入口地址,初始化acpi_pci_root 结构 acpi_pci_root_add
    • 初始化主桥设备 pci_create_root_bus
    • 扫描并添加主桥下所有pci设备 pci_scan_child_bus
    • 给每个pci设备分配资源,并初始化所有cap
    • 如何是桥设备,递归初始化

    Ubuntu 18.04下的一些配置

    config.txtscreen.log

    weinxin
    版权声明
    本站原创文章转载请注明文章出处及链接,谢谢合作!
    评论:0   参与:  0