總攬
https://myfamily12345.pixnet.net/blog/post/404540683
在 System.map中,可以看到相當多相關於PCI的初始化動作,
ffffffff81eab7e0 T __initcall_start
............................................................
ffffffff81eaba20 t __initcall_pcibus_class_init2
ffffffff81eaba28 t __initcall_pci_driver_init2
ffffffff81eaba30 t __initcall_backlight_class_init2
............................................................
ffffffff81eabb28 t __initcall_pci_arch_init3
.....................................................................................................................................
ffffffff81eabae0 t __initcall_gigantic_pages_init3
ffffffff81eabae8 t __initcall_kcmp_cookies_init3
ffffffff81eabaf0 t __initcall_acpi_pci_init3
ffffffff81eabaf8 t __initcall_dma_bus_init3
......................................................................................................................................
ffffffff81eabb08 t __initcall_setup_vcpu_hotplug_event3
ffffffff81eabb10 t __initcall_register_xen_pci_notifier3
ffffffff81eabb18 t __initcall_xen_pcpu_init3
ffffffff81eabb20 t __initcall_dmi_id_init3
ffffffff81eabb28 t __initcall_pci_arch_init3
ffffffff81eabb30 T __initcall4_start
.....................................................
ffffffff81eabc70 t __initcall_pci_slot_init4
.........................................................
ffffffff81eabc80 t __initcall_acpi_init4
.....................................................................................
ffffffff81eabd60 t __initcall_pci_subsys_init4
...........................................................
ffffffff81eabf58 t __initcall_init_acpi_pm_clocksource5
ffffffff81eabf60 t __initcall_pcibios_assign_resources5
............................................................
ffffffff81eabf98 t __initcall_pci_apply_final_quirks5s
ffffffff81eabfa0 t __initcall_acpi_reserve_resources5s
ffffffff81eabfa8 t __initcall_populate_rootfsrootfs
ffffffff81eabfa8 T __initcallrootfs_start
ffffffff81eabfb0 t __initcall_pci_iommu_initrootfs
............................................................
ffffffff81eac360 t __initcall_phy_core_init6
ffffffff81eac368 t __initcall_pci_proc_init6
ffffffff81eac370 t __initcall_pcie_portdrv_init6
ffffffff81eac378 t __initcall_aer_service_init6
ffffffff81eac380 t __initcall_pcie_pme_service_init6
ffffffff81eac388 t __initcall_pci_hotplug_init6
ffffffff81eac390 t __initcall_pcied_init6
ffffffff81eac398 t __initcall_xenfb_init6
..........................................................
ffffffff81eac3f0 t __initcall_dw_pci_driver_init6
...........................................................
ffffffff81eac420 t __initcall_platform_pci_init6
..........................................................
ffffffff81eac448 t __initcall_serial8250_init6
ffffffff81eac450 t __initcall_serial_pci_driver_init6
ffffffff81eac458 t __initcall_lpss8250_pci_driver_init6
ffffffff81eac460 t __initcall_mid8250_pci_driver_init6
ffffffff81eac468 t __initcall_hpet_init6
................................................................
ffffffff81eac4e0 t __initcall_nvme_core_init6
ffffffff81eac4e8 t __initcall_nvme_init6
ffffffff81eac4f0 t __initcall_ahci_pci_driver_init6
ffffffff81eac4f8 t __initcall_net_olddevs_init6
ffffffff81eac500 t __initcall_ehci_hcd_init6
ffffffff81eac508 t __initcall_ehci_pci_init6
ffffffff81eac510 t __initcall_ohci_hcd_mod_init6
ffffffff81eac518 t __initcall_xhci_hcd_init6
ffffffff81eac520 t __initcall_xhci_pci_init6
ffffffff81eac528 t __initcall_i8042_init6
..............................................................
ffffffff81eac710 t __initcall_prandom_reseed7
ffffffff81eac718 t __initcall_pci_resource_alignment_sysfs_init7
ffffffff81eac720 t __initcall_pci_sysfs_init7
ffffffff81eac728 t __initcall_bert_init7
...................................................................
ffffffff81eac760 t __initcall_efi_shutdown_init7
ffffffff81eac768 t __initcall_pci_mmcfg_late_insert_resources7
ffffffff81eac770 t __initcall_register_sk_filter_ops7
(1) 在/sys/class目錄下,產生 pci_bus 的目錄:
/
is exported by the kernel at run time, exposing the hierarchy of the hardware through
.
'/
路徑 /drivers/pci/probe
.dev_release = &release_pcibus_dev,
.dev_groups = pcibus_groups,
};
static int __init pcibus_class_init(void)
{
return class_register(&pcibus_class);
}
(2) 在/sys/bus下,建立 pci目錄,如果,有偵測到PCI devcie 將會在將會在 /sys/bus/pci/drivers 建立device使用的目錄
路徑 /drivers/pci/pci-driver.c
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
.uevent = pci_uevent,
.probe = pci_device_probe,
.remove = pci_device_remove,
.shutdown = pci_device_shutdown,
.dev_groups = pci_dev_groups,
.bus_groups = pci_bus_groups,
.drv_groups = pci_drv_groups,
.pm = PCI_PM_OPS_PTR,
};
static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
(3)ACPI(Advanced Configuration and Power Interface)負責x86處理器系統的資源,電源,熱插拔和中斷向量管理
在程式中設定相關ACPI2的相關函式,同時顯示ACPI Hot Plug PCI Controller Driver 版本
路徑 /drivers/pci/pci-acpi.c
static int __init acpi_pci_init(void)
{
int ret;
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) {
pr_info("ACPI FADT declares the system doesn't support MSI, so disable it\n");
pci_no_msi();
}
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
pr_info("ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
pcie_no_aspm();
}
ret = register_acpi_bus_type(&acpi_pci_bus);
if (ret)
return 0;
pci_set_platform_pm(&acpi_pci_platform_pm);
acpi_pci_slot_init();
acpiphp_init();
return 0;
}
(4) 對PCI總線進行初始化,指定raw_pci_ops透過 0xCF8 0xCFC 兩個端口進行讀寫,指定pci_mmcfg到raw_pci_ext_ops,
CONFIG_PCI_BIOS => 透過BIOS對PCI總線init
CONFIG_PCI_DIRECT=> 透過BIOS對linux總線init
路徑 /arch/x86/pci/init.c
static __init int pci_arch_init(void)
{
#ifdef CONFIG_PCI_DIRECT
int type = 0;
type = pci_direct_probe();
#endif
if (!(pci_probe & PCI_PROBE_NOEARLY))
pci_mmcfg_early_init();
if (x86_init.pci.arch_init && !x86_init.pci.arch_init())
return 0;
#ifdef CONFIG_PCI_BIOS
pci_pcbios_init();
#endif
/*
* don't check for raw_pci_ops here because we want pcbios as last
* fallback, yet it's needed to run first to set pcibios_last_bus
* in case legacy PCI probing is used. otherwise detecting peer busses
* fails.
*/
#ifdef CONFIG_PCI_DIRECT
pci_direct_init(type);
#endif
if (!raw_pci_ops && !raw_pci_ext_ops)
printk(KERN_ERR
"PCI: Fatal: No config space access function found\n");
dmi_check_pciprobe();
dmi_check_skip_isa_align();
return 0;
}
pci_arch_init
|--> pci_mmcfg_early_init
|--> pci_mmcfg_check_hostbridge
|--> pci_parse_mcfg
|--> free_all_mmcfg
|--> acpi_mcfg_check_entry
|-->pci_mmconfig_add
|--> pci_mmconfig_alloc
|--> list_add_sorted
|--> __pci_mmcfg_init
|--> pci_mmcfg_arch_init
|--> pci_mmcfg_arch_map
|--> mcfg_ioremap
(5) 在/sys/bus/pci/下建立一個slots目錄跟 kobject結構
static int pci_slot_init(void)
{
struct kset *pci_bus_kset;
pci_bus_kset = bus_get_kset(&pci_bus_type);
pci_slots_kset = kset_create_and_add("slots", NULL,
&pci_bus_kset->kobj);
if (!pci_slots_kset) {
printk(KERN_ERR "PCI: Slot initialization failure\n");
return -ENOMEM;
}
return 0;
}
(6) acpi 相關的init 動作
static int __init acpi_init(void)
{
int result;
if (acpi_disabled) {
printk(KERN_INFO PREFIX "Interpreter disabled.\n");
return -ENODEV;
}
acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
if (!acpi_kobj) {
printk(KERN_WARNING "%s: kset create error\n", __func__);
acpi_kobj = NULL;
}
init_acpi_device_notify();
result = acpi_bus_init();
if (result) {
disable_acpi();
return result;
}
pci_mmcfg_late_init();
acpi_iort_init();
acpi_scan_init();
acpi_ec_init();
acpi_debugfs_init();
acpi_sleep_proc_init();
acpi_wakeup_device_init();
acpi_debugger_init();
acpi_setup_sb_notify_handler();
acpi_set_processor_mapping();
return 0;
}
acpi_init
|--> acpi_scan_init
|--> acpi_pci_root_init
|--> acpi_pci_link_init
(7) 建立 PCI Root Bridge,並配置相關 io mem resource
static struct acpi_scan_handler pci_root_handler = {
.ids = root_device_ids,
.attach = acpi_pci_root_add,
.detach = acpi_pci_root_remove,
.hotplug = {
.enabled = true,
.scan_dependent = acpi_pci_root_scan_dependent,
},
};
void __init acpi_pci_root_init(void)
{
acpi_hest_init();
if (acpi_pci_disabled)
return;
pci_acpi_crs_quirks();
acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root");
}
acpi_pci_root_init
|--> pci_root_handler(acpi_pci_root_add)
ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
|--> negotiate_os_control
|--> pci_acpi_scan_root
kzalloc_node(sizeof(*info), GFP_KERNEL, node);
|--> acpi_pci_root_create
|--> pci_acpi_root_init_info
|--> setup_mcfg_map
|--> pci_mmconfig_insert
|--> pci_mmconfig_lookup
|--> acpi_pci_probe_root_resources
|--> pci_acpi_root_add_resources
|--> pci_add_resource
|--> pci_create_root_bus
||--> pci_alloc_bus
||--> pci_find_bus(pci_domain_nr(b), bus)
||--> pcibios_root_bridge_prepare(bridge)
kzalloc
pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window]
pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window]
pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window]
pci_bus 0000:00: root bus resource [mem 0x000c0000-0x000dffff window]
pci_bus 0000:00: root bus resource [mem 0x80000000-0xdfffffff window]
pci_bus 0000:00: root bus resource [mem 0x480000000-0x7fffffffff window]
pci_bus 0000:00: root bus resource [mem 0xfe010000-0xfe010fff window]
pci_bus 0000:00: root bus resource [mem 0xfa000000-0xfa0fffff window]
pci_bus 0000:00: root bus resource [mem 0xfb000000-0xfb7fffff window]
pci_bus 0000:00: root bus resource [mem 0xfa100000-0xfa1007ff window]
||--> pci_bus_insert_busn_res
pci_bus 0000:00: root bus resource [bus 00-ff]
||--> pci_scan_child_bus
|--> for (devfn = 0; devfn < 0x100; devfn += 8)
pci_scan_slot
|-->pci_scan_single_device
|--> pci_get_slot
|--> pci_scan_device
|--> pci_bus_read_dev_vendor_id
|--> pci_alloc_dev
|--> pci_set_of_node
|--> pci_setup_device
0000:00:00.0 [domain:busnum:PCIslot.func]
|--> pci_device_add
|--> pci_configure_device
|--> set_dev_node
|--> pci_dma_configure
|--> pci_fixup_device
|--> pci_reassigndev_resource_alignment
|--> pci_init_capabilities
|--> pcibios_add_device
|--> pci_set_msi_domain
|-->device_add
|--> pci_iov_bus_range
|--> pcibios_fixup_bus
|-->pci_read_bridge_bases
pci 0000:00:17.0: PCI bridge to [bus 06-07]
|-->pci_bus_add_resource
|-->pcibios_fixup_device_resources
|--> list_for_each_entry(dev, &bus->devices, bus_list)
pci_scan_bridge
|--> pci_read_config_dword
|--> pci_read_config_word
|--> pci_write_config_word
|--> pci_enable_crs
|--> pci_find_bus
|--> pci_add_new_bus
|--> pci_scan_child_bus
||--> pci_set_host_bridge_release
留言列表