计算机系统启动过程分析

本文基于MIPS架构龙芯3号处理器为例,介绍启动过程。

启动过程分析

无论采用何种指令系统的处理器,复位后的第一条指令都会从一个预先定义好的特定地址去取指。处理器的执行就从这条指令开始。处理器的启动过程实际上就是一个特定程序的执行过程,这个程序被成为固件,也就是BIOS,现在主流的BIOS都是采用UEFI软件架构。龙芯也自己研制了在MIPS架构上的UEFI版本。龙芯3号处理器的上电执行的第一条指令的地址位于0xBFC00000这个地址上,(32位虚拟地址,实际的物理地址为0x1fc00000)。从此之后系统的启动过程就开始了,为了使计算机达到一个可控制的状态,在启动过程中需要对处理器核,内存,外设等各个部分进行初始化,再对必要的外设进行驱动管理。下面将详细的讲讲这个启动过程中都做的工作。(注意这里只是介绍的单核启动的过程)

  1. 处理器核初始化
    这部分主要是对处理器的模式和一些功能的的初始化,是处理器工作在一个稳定的模式下,如果处理器的状态并没有完全可控,或许在执行过程中会出现一些猜测不到的错误,导致死机等问题。处理器的第一条指令,实际上是由复位信号控制的,但受限于各种因素,复位信号并没有对处理器内部的所有寄存器进行复位,例如TLB和Cache等复杂结构。就需要软件对这部分结构进行初始化,但是从龙芯的3A2000以后的处理器,其初始化都是由硬件完成的,软件就不需要对TLB和Cache等结构进行初始化操作了。然后对处理器核的状态寄存器和原因寄存器进行初始化,并将后续软件使用的一些功能的初始化。

  2. 调试接口初始化
    这里的调试接口主要是指串口,在龙芯平台上,CPU内部是集成了串口寄存器的,一般在处理器和初始化之后就会对串口寄存器进行初始化,这样就可以利用一些打印信息来判断后面个过程的执行状态。

  3. TLB初始化
    这部分代码在3A2000的处理器之前是需要的,但是在这之后的处理器上是不需要的。因为上电后,硬件已经将这部分结构初始化好,软件只需要内核下初始化一下TLB映射的也表即可,在BIOS下面是不需要再做其他的操作了。

  4. Cache初始化
    同上一样,这部分也是硬件初始化好了,以前在硬件没初始化之前,上电后Cache是不能使用的,也就是为什么上电后的第一条指令要通过uncache的地址端来映射,就是因为cache还不能使用,你现在是没有这个限制的。也就是说上电后的第一条指令的虚拟地址是0x9fc00000也是可以的。

  5. 内存初始化
    内存是重要的计算机组成部分。BIOS(UEFI)在运行过程中,后期的代码都是在内存中运行的。内存相对于传统的Rom或者Flash来说,速度快乐不止上千倍。越来越多的处理器已经内部集成了内存控制器,因为内存的使用和设置和外接内存芯片的种类配置等都相关。所以在启动过程中需要先获取内存的配置信息,根据这些配置信息来对内存进行初始化。其实对内存的初始化就是对内存控制器的初始化。在初始化完成后,程序可以使用内存中的已有的数据来实现系统的休眠和唤醒等功能。内存控制器的初始化主要包含两部分:一是根据内存的行地址和列地址等对内存地址映射进行配置。二是根据协议对内存信号调整的支持方式对内存读写信号相关的寄存器进行行训练,以保证传输时的数据完整性。内存初始化完成后,还需要根据内存的大小对系统可用的物理地址空间进行相应的调整。

  6. IO 总线初始化
    受外围桥片的影响,不同系需要对IO 总线进行针对性的初始化操作。对于龙芯3A3000处理器来说,对应的IO总线主要为HT总线,在IO总线初始化的时候主要做了一下操作:
    一是对IO总线操作的地址空间进行设置,划定设备的配置访问空间,IO访问空间和Memory空间。二是IO设备的DMA访问空间的设置,对处理器能接收的DMA内存地址进行了设置。三是对HT总线进行升频,从1.0模式的200M升频到3.0模式的2G,并将总线的带宽由8位升到16位。这样对IO总线的初始化操作就基本上完成了,还需要进行一些和桥片特性相关的配置才能使桥片正常工作。
    完成内存与IO总线初始化操作后,整个计算机系统就已经进入了一个可控制的状态。但是为了加载操作系统,还需要对系统中的一些设备进行初始化并加载相应的驱动。

  7. 设备的探测及驱动的加载
    设备有LPC设备和PCI/PCIE设备等,这里主要介绍PCIE设备。
    在PCI软件架构下,系统可以灵活的支持设备的自动识别和驱动的自动加载的过程。下面对PCI阮家架构进行简要的说明。
    PCI协议下,IO系统空间分为三个部分:配置空间,IO空间和Memory空间。配置空间存储设备的基本信息,主要用于设备的探测和发现。IO空间比较小,用于少量的设备寄存器访问;Memory空间可映射的区域较大,可以方便的映射设备所需要的大块物理地址空间。对于软件来说IO空间和Memory空间并没有很大的区别。特别是MIPS这种IO空间和Memory空间同一编址的指令系统。他们的区别仅在于所在的地址段不同,而对于某些设备的Memory访问,可以采用更长的单次访问请求。例如对于IO空间,可以限制为仅能使用字访问,而对于Memory空间则可以随意字长的访问。配置空间的地址偏移由总线号,设备号,功能号和寄存器号组合得到。通过对这个组合的全部枚举,可以检测到系统中存在的所有设备。
    对PCI设备的探测和加载驱动的过程是一个递归的过程,大致算法如下:
    1)将初始总线号,设备号,功能号,设为0
    2)使用当前的总线号,设备号,功能号组成一个配置空间的地址,使用该地址访问其0号寄存器,检查其设备号。
    3)如果读出全1或者全0表示没有设备
    4)如果该设备为有效设备,检查每个BAR所需要的地址空间大小,并收集信息。
    5)检测其是否为一个多功能设备,如果是将功能号加1再继续扫描,执行第2步。
    6)如果该设备为桥设备,则给该设备配置一个新的总线号,再使用该总线号,从设备号为0,功能号为0开始递归调用第二步。
    7)如果设备号非31,则设备号加1继续执行第二步,如果设备号为31,并且总线号为0,表示扫描结束,如果总线号非0,则退回上一层递归调用。
    通过这个递归调用过程,就可以得到总线上的所有的PCI设备以及其所需要的所有空间信息。有了这些信息,就可以使用排序的方法对所有的设备从大到小进行分配,最后利用分配的基地址和设备的ID信息,加载相应的驱动之后,就可以正常的使用该设备了。

这样设备驱动也都加载之后,设备如USB,硬盘等设备就可以使用。这样就可以加载里面操作系统启动的内核和initrd等内容来加载操作系统了。

猜你喜欢

转载自blog.csdn.net/Lq19880521/article/details/88075540