Intel® IA-32 Architecture Learning 3.2 PROCESSOR MANAGEMENT AND INITIALIZATION---Taking Linux As Example

来源:互联网 发布:Java 泛型数组 编辑:程序博客网 时间:2024/05/16 23:35

This chapter is OS dependent. We chose to follow the kernel initialization process in the linear order in which it occurs. We begin with a discussion of what happens on power-on through to the call to the first architecture-independent function, start_kernel(), and follow the process up to the invocation of /sbin/init.  The figure below illustrates the order of events from system power on to power off.
image

We begin with a discussion of BIOS and Open Firmware, which is the first code that runs in the x86 upon power on. This is followed by a discussion of bootloaders commonly used with Linux and how they load the kernel and pass execution control to it. We then discuss in detail the step known as kernel initialization, where all the subsystems are initialized. The end of the kernel initialization is marked by the call to /sbin/init by process 1. The init program continues on with what is known as system initialization by enabling processes that need to be running before users can log in.

1. BIOS

For x86 systems, this is where the system BIOS resides. The Basic Input Output System (BIOS) is a block of hardware-specific system initialization code that boots the system. In x86 systems, the boot loader and, in turn Linux, depend on BIOS to bring the system to a known state. The interface to BIOS is a uniform set of functions known as interrupts. At load time, Linux uses these interrupts to query available system resources. After BIOS completes its initialization, it copies the first 512 bytes from the boot device (which is discussed in the next section) to address 0x7c00 and jumps to it. Although in some installations, BIOS loads the operating system over a network connection, this discussion is confined to the process when loading Linux from the hard drive. When Linux is loaded, BIOS is still in memory and its functions are accessible and called by way of interrupts.

2. Boot Loaders

Boot loaders are programs that reside on the boot device of a computer. The first boot device is usually the first hard disk in the system. A boot loader is called by BIOS (x86) after enough system initialization has occurred to support the memory, interrupts, and I/O required to load the kernel. Once loaded, the kernel initializes and configures the operating system.

Master Boot Record (MBR), which resides in the first sector (sector 0, cylinder 0, head 0) of the boot device. The MBR contains a small program and a four-entry partition table. The end of the boot sector has a hex marker 0xAA55 at location 510. The Table below shows the components of the MBR.
image

The MBR's partition table holds information pertinent to each of the hard disk primary partitions. The following table shows what each 16-byte entry of the MBR's partition table looks like:
image

At the end of BIST and hardware identification, the system initialization code (BIOS) accesses the hard drive controller to read the MBR. After the type of boot drive is identified, one can follow a documented interface (for example, on an IDE drive) to access head 0, cylinder 0, and sector 0.

After the boot device is located, the MBR is copied to memory address 0x7c00 and executed. The small program at the head of the MBR moves itself out of the way and searches its partition table for the location of the active boot partition. The MBR then copies the code from the active boot partition to address 0x7c00 and begins executing it. From this point, DOS is usually booted on an x86 system. However, the active boot partition can have a bootloader that, in turn, loads the operating system. We now discuss some of the most common bootloaders that Linux uses. Here, a Figure shows what memory looks like at bootup time.
 image

2.1 Common Bootloader—GRUB(Grand Unified Bootloader)

GRUB is an x86-based bootloader that's used to load Linux.
GRUB recognizes filesystems on the boot drives, and the kernel can be loaded by specifying the filename, drive, and partition where the kernel resides. GRUB is a two-stage bootloader. Stage 1 is installed in the MBR and is called by BIOS. Stage 2 is partially loaded by Stage 1 and then finishes loading itself from the filesystem. The breakdown of events ocurring in each of the stages is the following:
image
image
image

This configuration specifies that Linux boots and loads the executable image to linear address 0x9000 and jumps to 0x9020. At this point, the uncompressed part of the Linux kernel decompresses the compressed portion to address 0x10000 and kernel initialization begins.

3 Intel x86 based hardware memory management

Memory management is one of the first subsystems to be initialized and begins prior to the execution of start_kernel() because of its highly architecture-dependent nature.
In real address mode, the processor can execute a program written for the 8086 and 8088 processors using the same instructions and, more importantly, the same method of addressing or address translation. The end result of address translation is how the processor accesses the system memory. The early Intel processors had a 20-bit address bus, which accessed approximately 64K bytes of memory

The code in setup.S performs several important functions with respect to memory initialization:

/*********************************/
# method E820H:
# the memory map from hell.  e820h returns memory classified into
# a whole bunch of different types, and allows memory holes and
# everything.  We scan through this memory map and build a list
# of the first 32 memory areas, which we return at [E820MAP].
# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.

#define SMAP  0x534d4150

meme820:
    xorl    %ebx, %ebx            # continuation counter
    movw    $E820MAP, %di            # point into the whitelist
                        # so we can have the bios
                        # directly write into it.

jmpe820:
    movl    $0x0000e820, %eax        # e820, upper word zeroed
    movl    $SMAP, %edx            # ascii 'SMAP'
    movl    $20, %ecx            # size of the e820rec
    pushw    %ds                # data record.
    popw    %es
    int    $0x15                # make the call
    jc    bail820                # fall to e801 if it fails

    cmpl    $SMAP, %eax            # check the return is `SMAP'
    jne    bail820                # fall to e801 if it fails

#    cmpl    $1, 16(%di)            # is this usable memory?
#    jne    again820

    # If this is usable memory, we save it by simply advancing %di by
    # sizeof(e820rec).
    #
good820:
    movb    (E820NR), %al            # up to 128 entries
    cmpb    $E820MAX, %al
    jae    bail820

    incb    (E820NR)
    movw    %di, %ax
    addw    $20, %ax
    movw    %ax, %di
again820:
    cmpl    $0, %ebx            # check to see if
    jne    jmpe820                # %ebx is set to EOF
bail820:
/*********************************/

the memory map can be obtained by three methods: 0xe820, 0xe801, and 0x88. All three methods have to do with compatibility with existing BIOS distributions and their platforms.

/*********************************/
# Now we move the system to its rightful place ... but we check if we have a
# big-kernel. In that case we *must* not move it ...
    testb    $LOADED_HIGH, %cs:loadflags
    jz    do_move0            # .. then we have a normal low
                        # loaded zImage
                        # .. or else we have a high
                        # loaded bzImage
    jmp    end_move            # ... and we skip moving

do_move0:
    movw    $0x100, %ax            # start of destination segment
    movw    %cs, %bp            # aka SETUPSEG
    subw    $DELTA_INITSEG, %bp        # aka INITSEG
    movw    %cs:start_sys_seg, %bx        # start of source segment
    cld
do_move:
    movw    %ax, %es            # destination segment
    incb    %ah                # instead of add ax,#0x100
    movw    %bx, %ds            # source segment
    addw    $0x100, %bx
    subw    %di, %di
    subw    %si, %si
    movw     $0x800, %cx
    rep
    movsw
    cmpw    %bp, %bx            # assume start_sys_seg > 0x200,
                        # so we will perhaps read one
                        # page more than needed, but
                        # never overwrite INITSEG
                        # because destination is a
                        # minimum one page below source
    jb    do_move

end_move:
/*********************************/

 

 

 

 

 

对CPU、定时器、DMA控制器、中断控制器、内存中的RAM和ROM、键盘、磁盘驱动器、异步通信接口、打印机配置等内容进行测试,这个过程叫做POST(上电自检),Intel称为BIST过程。

加电:
初始化寄存器;CS:EIP=0xfffffff0,in ROM(CPU要执行的第一条指令) 在0x0000位置设置中断向量表,这样后面还可以接着使用BIOS功能该地址中有一条JMP指令,跳转地址通常是BIOS的入口地址
BIOS:
--POST
--初始化硬件设备
--搜索启动操作系统的设备(U盘、硬盘、CD-ROM)
--并把MBR读到内存绝对地址0x7c00处同时将控制权交出。

 

 

 

Main Ref:

Kernel Primer- A Top Down Approach for x86 and PowerPC architectures