天天看點

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

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.

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

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.

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

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:

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

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.

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

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:

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

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

繼續閱讀