[OpenSolaris][kernel]Solaris内核加载设备驱动过程

本文详细介绍了Solaris操作系统在启动过程中,从高级引导序列到设备驱动加载的具体步骤。包括内存布局、初始化进程、设备树创建、PCI总线探测等关键环节。同时,解释了如何通过ddi模块将设备驱动与设备节点绑定,并完成了设备驱动的加载和初始化。文章深入剖析了内核加载设备驱动的过程,对于理解Solaris系统启动和设备管理有重要参考价值。
摘要由CSDN通过智能技术生成
Solaris main():

1. High level boot sequence
===========================

-> lgrp_setup()            // Setup the first lgroup, and home t0

-> startup()            // Machine-dependent startup code
                // In a 32-bit OS, boot loads the kernel text at 0xfe800000 and kernel data
                // at 0xfec00000.  On a 64-bit OS, kernel text and data are loaded at
                // 0xffffffff.fe800000 and 0xffffffff.fec00000 respectively.  Those
                // addresses are fixed in the binary at link time.
--> progressbar_init()        // Initialize a rectangle area for progress bar
--> startup_init()
--> startup_xen_version()
--> startup_memlist()        // Build the memlists and other kernel essential memory system data structures
--> startup_kmem()        // Layout the kernel's part of address space and initialize kmem allocator
--> startup_vm()        // Finish initializing the VM system, now that we are no longer relying on the boot time memory allocators.
--> startup_pci_bios()        // Retrieve information from the bios needed for system configuration early during startup.
--> startup_modules()        // setup_ddi() is called at this point to create a kernel device tree.
                // First, create rootnex and then invoke bus specific code to probe devices.
--> startup_bios_disk()        // ???
--> startup_end()        // configure() is called at this point to set up devices.
                // setx86isalist() is called to set the isa_list string to the defined instruction sets we support.
                // psm_install() is called to call the prober() of each psm module
                // (*picinitf)() is called to enabling interrupt. picinitf is set to mach_picinit() in ./i86pc/os/mp_machdep.c. Reading here, I am thinking about the IOMMU code. The best place to initialization and enable Intel IOMMU is here. We shouldn't put this range of code between the first and second pass of pci_enumerate(), since the pci device tree could be changes during the second pass (phantom, subtractive ppb and so on).
--> progressbar_start()        // process bar related, ignore it.

-> segkmem_gc()            // kernel memory segment driver related

-> callb_init()            // Init all callb tables in the system
-> callout_init()         // Initialize all callout tables.  Called at boot time just before clkstart().
-> timer_init()            // timer_init() allocates the internal data structures used by i_timeout(), i_untimeout() and the timer. Timer must be initialized before cyclic starts
-> cbe_init()            // initialize cyclic back end
-> clock_tick_init_pre()        // Clock tick initialization
-> clock_init()            // initialize clock system
-> init_mstate()
-> init_cpu_mstate()        //On some platforms, clkinitf() changes the timing source that gethrtime_unscaled() uses to generate timestamps.  cbe_init() calls clkinitf(), so re-initialize the microstate counters after the timesource has been chosen.
-> lgrp_plat_probe()

-> (**initptr)()        // Call all system initialization functions. Initialization functions are saved in init_tbl[]. For each initptr, call the function.

-> vm_init()            // vm subsystem related initialization
-> physio_bufs_init()        // initialize buffer pool for raw I/O requests
-> XXX                // Drop the interrupt level and allow interrupts. At this point the DDI guarantees that interrupts are enabled
-> vfs_mountroot()        // Mount the root file system. errorq_init(), cpu_kstat_init(CPU), and ddi_walk_devs(ddi_root_node(), pm_adjust_timestamps, NULL) are called after the root file system is mounted.

-> post_startup()

2. setup_ddi
============

invoking stack:
main()
->startup()
-->startup_modules()
--->setup_ddi()

(1) impl_ddi_init_nodeid()
Keep a sorted free list of available nodeids. Allocating a nodeid won't cause memory allocation. Freeing a nodeid does cause memory allocation. The list node is defined as

struct available {
        uint32_t nodeid;
        uint32_t count;
        struct available *next;
        struct available *prev;
};

Mutex lock, nodeid_lock ,is defined to protect the nodeid list. The list head is pointed by nhead. impl_ddi_init_nodeid() is called to initialize the list and mutex lock.

(2) impl_create_root_class()
Create classes and major number bindings for the name of my root. Called immediately before 'loadrootmodules'. rootname = 'i86pc', platform = 'i86pc'

(3) create_devinfo_tree()
init the dev_info mem cache

alloc a dev_info for root and hold it

add the root dip into devimap list, the list is defined as,
struct devi_nodeid_list {
        kmutex_t dno_lock;              /* Protects other fields */
        struct devi_nodeid *dno_head;  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值