2400 lines
68 KiB
Plaintext
2400 lines
68 KiB
Plaintext
|
Linux 2.4.x Initialization for IA-32 HOWTO
|
|||
|
Randy Dunlap, rddunlap@ieee.org
|
|||
|
v1.0, 2001-05-17
|
|||
|
|
|||
|
This document contains a description of the Linux 2.4 kernel initial<61>
|
|||
|
ization sequence on IA-32 processors.
|
|||
|
______________________________________________________________________
|
|||
|
|
|||
|
Table of Contents
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Introduction
|
|||
|
|
|||
|
1. Overview
|
|||
|
|
|||
|
2. This document
|
|||
|
|
|||
|
3. Contributions
|
|||
|
|
|||
|
4. Trademarks
|
|||
|
|
|||
|
5. License
|
|||
|
|
|||
|
5. Linux init ("ASCII art")
|
|||
|
|
|||
|
5. Linux early setup
|
|||
|
|
|||
|
6. IA-32 Kernel Setup
|
|||
|
|
|||
|
6.1 start_of_setup:
|
|||
|
6.1.1 Read second hard drive DASD type
|
|||
|
6.1.2 Check that LILO loaded us right
|
|||
|
6.1.3 Check old loader trying to load a big kernel
|
|||
|
6.1.4 Determine system memory size
|
|||
|
6.1.5 Video adapter modes
|
|||
|
6.1.6 Get Hard Disk parameters
|
|||
|
6.1.7 Get Micro Channel bus information
|
|||
|
6.1.8 Check for mouse
|
|||
|
6.1.9 Check for APM BIOS support
|
|||
|
6.1.10 Prepare to move to protected mode
|
|||
|
6.1.11 Enable address line A20
|
|||
|
6.1.12 Make sure any possible coprocessor is properly reset
|
|||
|
6.1.13 Mask all interrupts
|
|||
|
6.1.14 Move to Protected Mode
|
|||
|
6.1.15 Jump to startup_32 code
|
|||
|
|
|||
|
7. Video Setup
|
|||
|
|
|||
|
7.1 video:
|
|||
|
7.1.1 basic_detect:
|
|||
|
7.1.2 mode_params:
|
|||
|
7.1.3 mopar_gr:
|
|||
|
7.1.4 mode_menu:
|
|||
|
7.1.5 mode_set:
|
|||
|
7.1.6 store_screen:
|
|||
|
7.1.7 restore_screen:
|
|||
|
7.1.8 mode_table:
|
|||
|
7.1.9 mode_scan:
|
|||
|
7.1.10 svga_modes:
|
|||
|
7.1.10 Linux architecture-specific initialization
|
|||
|
|
|||
|
8. startup_32:
|
|||
|
|
|||
|
9. Set segment registers to known values
|
|||
|
|
|||
|
10. SMP BSP (Bootstrap Processor) check
|
|||
|
|
|||
|
11. Initialize page tables
|
|||
|
|
|||
|
12. Enable paging
|
|||
|
|
|||
|
13. Clear BSS
|
|||
|
|
|||
|
14. 32-bit setup
|
|||
|
|
|||
|
15. Copy boot parameters and command line out of the way
|
|||
|
|
|||
|
16. checkCPUtype
|
|||
|
|
|||
|
17. Count this processor
|
|||
|
|
|||
|
18. Load descriptor table pointer registers
|
|||
|
|
|||
|
19. Start other processors
|
|||
|
|
|||
|
19. Linux architecture-independent initialization
|
|||
|
|
|||
|
20. start_kernel:
|
|||
|
|
|||
|
20.1 More architecture-specific init
|
|||
|
20.2 Continue architecture-independent init
|
|||
|
20.3 Parsing command line options
|
|||
|
20.4 trap_init
|
|||
|
20.5 init_IRQ
|
|||
|
20.6 sched_init
|
|||
|
20.7 time_init
|
|||
|
20.8 softirq_init
|
|||
|
20.9 console_init
|
|||
|
20.10 init_modules
|
|||
|
20.11 Profiling setup
|
|||
|
20.12 kmem_cache_init
|
|||
|
20.13 sti
|
|||
|
20.14 calibrate_delay
|
|||
|
20.15 INITRD setup
|
|||
|
20.16 mem_init
|
|||
|
20.17 kmem_cache_sizes_init
|
|||
|
20.18 proc_root_init
|
|||
|
20.19 mempages = num_physpages;
|
|||
|
20.20 fork_init(mempages)
|
|||
|
20.21 proc_caches_init()
|
|||
|
20.22 vfs_caches_init(mempages)
|
|||
|
20.23 buffer_init(mempages)
|
|||
|
20.24 page_cache_init(mempages)
|
|||
|
20.25 kiobuf_setup()
|
|||
|
20.26 signals_init()
|
|||
|
20.27 bdev_init()
|
|||
|
20.28 inode_init(mempages)
|
|||
|
20.29 ipc_init()
|
|||
|
20.30 dquot_init_hash()
|
|||
|
20.31 check_bugs()
|
|||
|
20.32 Start other SMP processors (as applicable)
|
|||
|
20.33 Start init thread
|
|||
|
20.34 unlock_kernel()
|
|||
|
20.35 current->need_resched = 1;
|
|||
|
20.36 cpu_idle()
|
|||
|
|
|||
|
21. setup_arch
|
|||
|
|
|||
|
21.1 Copy and convert system parameter data
|
|||
|
21.2 For RAMdisk-enabled configs (CONFIG_BLK_DEV_RAM)
|
|||
|
21.3 setup_memory_region
|
|||
|
21.4 Set memory limits
|
|||
|
21.5 parse_mem_cmdline
|
|||
|
21.6 Setup Page Frames
|
|||
|
21.7 Handle SMP and IO APIC Configurations
|
|||
|
21.8 paging_init()
|
|||
|
21.9 Save the boot-time SMP configuration
|
|||
|
21.10 Reserve INITRD memory
|
|||
|
21.11 Scan for option ROMs
|
|||
|
21.12 Reserve system resources
|
|||
|
|
|||
|
22. init thread
|
|||
|
|
|||
|
23. do_basic_setup {part of the init thread}
|
|||
|
|
|||
|
23.1 Be the reaper of orphaned children
|
|||
|
23.2 MTRRs
|
|||
|
23.3 SYSCTLs
|
|||
|
23.4 Init Many Devices
|
|||
|
23.5 PCI
|
|||
|
23.6 Micro Channel
|
|||
|
23.7 ISA PnP
|
|||
|
23.8 Networking Init
|
|||
|
23.9 Initial RamDisk
|
|||
|
23.10 Start the kernel "context" thread (keventd)
|
|||
|
23.11 Initcalls
|
|||
|
23.12 Filesystems
|
|||
|
23.13 IRDA
|
|||
|
23.14 PCMCIA
|
|||
|
23.15 Mount the root filesystem
|
|||
|
23.16 Mount the dev (device) filesystem
|
|||
|
23.17 Switch to the Initial RamDisk
|
|||
|
23.17 Glossary
|
|||
|
23.17 References
|
|||
|
|
|||
|
|
|||
|
______________________________________________________________________
|
|||
|
|
|||
|
|
|||
|
|
|||
|
1. Introduction
|
|||
|
|
|||
|
|
|||
|
Portions of this text come from comments in the kernel source files
|
|||
|
(obviously). I have added annotations in many places. I hope that
|
|||
|
this will be useful to kernel developers -- either new ones or
|
|||
|
experienced ones who need more of this type of information. However,
|
|||
|
if there's not enough detail here for you, "Use the Source."
|
|||
|
|
|||
|
|
|||
|
1.1. Overview
|
|||
|
|
|||
|
|
|||
|
This description is organized as a brief overview which lists the
|
|||
|
sections that are described later in more detail.
|
|||
|
|
|||
|
The description is in three main sections. The first section covers
|
|||
|
early kernel initialization on IA-32 (but only after your boot loader
|
|||
|
of choice and other intermediate loaders have run; i.e., this
|
|||
|
description does not cover loading the kernel). This section is based
|
|||
|
on the code in "linux/arch/i386/boot/setup.S" and
|
|||
|
"linux/arch/i386/boot/video.S".
|
|||
|
|
|||
|
The second major section covers Linux initialization that is x86- (or
|
|||
|
i386- or IA-32-) specific. This section is based on the source files
|
|||
|
"linux/arch/i386/kernel/head.S" and "linux/arch/i386/kernel/setup.c".
|
|||
|
|
|||
|
The third major section covers Linux initialization that is
|
|||
|
architecture-independent. This section is based on the flow in the
|
|||
|
source file "linux/init/main.c".
|
|||
|
|
|||
|
See the References section for other valuable documents about booting,
|
|||
|
loading, and initialization.
|
|||
|
|
|||
|
|
|||
|
1.2. This document
|
|||
|
|
|||
|
|
|||
|
This document describes Linux 2.4.x initialization on IA-32 (or i386
|
|||
|
or x86) processors -- after one or more kernel boot loaders (if any)
|
|||
|
have done their job.
|
|||
|
|
|||
|
You can format it using the commands (for example):
|
|||
|
|
|||
|
|
|||
|
|
|||
|
% sgml2txt ia32_init_240.sgml
|
|||
|
|
|||
|
|
|||
|
|
|||
|
or
|
|||
|
|
|||
|
|
|||
|
% sgml2html ia32_init_240.sgml
|
|||
|
|
|||
|
|
|||
|
|
|||
|
This will produce plain ASCII or HTML files respectively. You can
|
|||
|
also produce LaTeX, GNU, and RTF info by using the proper sgmltool
|
|||
|
(man sgmltools).
|
|||
|
|
|||
|
|
|||
|
|
|||
|
1.3. Contributions
|
|||
|
|
|||
|
|
|||
|
Additions and corrections are welcome. Please send them to me
|
|||
|
(rddunlap@ieee.org). Contributions of section descriptions that are
|
|||
|
used will be credited to their author(s).
|
|||
|
|
|||
|
|
|||
|
1.4. Trademarks
|
|||
|
|
|||
|
|
|||
|
All trademarks are the property of their respective owners.
|
|||
|
|
|||
|
|
|||
|
1.5. License
|
|||
|
|
|||
|
|
|||
|
Copyright (C) 2001 Randy Dunlap.
|
|||
|
|
|||
|
This document may be distributed only subject to the terms and
|
|||
|
conditions set forth in the LDP (Linux Documentation Project) License
|
|||
|
at "http://www.linuxdoc.org/COPYRIGHT.html".
|
|||
|
|
|||
|
|
|||
|
|
|||
|
2. Linux init ("ASCII art")
|
|||
|
|
|||
|
|
|||
|
Pictorially (loosely speaking :), Linux initialization looks like
|
|||
|
this, where "[...]" means optional (depends on the kernel's
|
|||
|
configuration) and "{...}" is a comment.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
+-------------------------------+
|
|||
|
| arch/i386/boot/setup.S:: + |
|
|||
|
| arch/i386/boot/video.S:: |
|
|||
|
|-------------------------------|
|
|||
|
| start_of_setup: |
|
|||
|
| check that loaded OK |
|
|||
|
| get system memory size |
|
|||
|
| get video mode(s) |
|
|||
|
| get hard disk parameters |
|
|||
|
| get MC bus information |
|
|||
|
| get mouse information |
|
|||
|
| get APM BIOS information |
|
|||
|
| enable address line A20 |
|
|||
|
| reset coprocessor |
|
|||
|
| mask all interrupts |
|
|||
|
| move to protected mode |
|
|||
|
| jmp to startup_32 |
|
|||
|
+-------------------------------+
|
|||
|
|
|
|||
|
v
|
|||
|
+-------------------------------+
|
|||
|
| arch/i386/kernel/head.S:: |
|
|||
|
|-------------------------------|
|
|||
|
| startup_32: |
|
|||
|
| set segment registers to |
|
|||
|
| known values |
|
|||
|
| init basic page tables |
|
|||
|
| setup the stack pointer |
|
|||
|
| clear kernel BSS |
|
|||
|
| setup the IDT |
|
|||
|
| checkCPUtype |
|
|||
|
| load GDT, IDT, and LDT |
|
|||
|
| pointer registers |
|
|||
|
| start_kernel |
|
|||
|
| {it does not return} |
|
|||
|
+-------------------------------+
|
|||
|
|
|
|||
|
v
|
|||
|
+-------------------------------+ +-------------------------------+
|
|||
|
| init/main.c:: | +->| arch/i386/kernel/setup.c:: |
|
|||
|
|-------------------------------| | |-------------------------------|
|
|||
|
| start_kernel(): | | | setup_arch(): |
|
|||
|
| lock_kernel | | | copy boot parameters |
|
|||
|
| setup_arch |--+ | init ramdisk |
|
|||
|
| parse_options |<-+ | setup_memory_region |
|
|||
|
| trap_init | | | parse_cmd_line |
|
|||
|
| cpu_init | | | use the BIOS memory map to |
|
|||
|
| init_IRQ | | | setup page frame info. |
|
|||
|
| sched_init | | | reserve physical page 0 |
|
|||
|
| init_timervecs | | | [find_smp_config] |
|
|||
|
| time_init | | | paging_init |
|
|||
|
| softirq_init | | | [get_smp_config] |
|
|||
|
| console_init | | | [init_apic_mappings] |
|
|||
|
| [init_modules] | | | [reserve INITRD memory] |
|
|||
|
| [profiling setup] | | | probe_roms to search |
|
|||
|
| kmem_cache_init | | | for option ROMs |
|
|||
|
| sti | | | request_resource to |
|
|||
|
| calibrate_delay | | | reserve video RAM memory |
|
|||
|
| [INITRD setup] | | | request_resource to |
|
|||
|
| mem_init | | | reserve all standard PC |
|
|||
|
| free_all_bootmem | +--| I/O system board resources|
|
|||
|
| kmem_cache_sizes_init | +-------------------------------+
|
|||
|
| [proc_root_init] |
|
|||
|
| fork_init |
|
|||
|
| proc_caches_init |
|
|||
|
| vfs_caches_init |
|
|||
|
| buffer_init |
|
|||
|
| page_cache_init |
|
|||
|
| kiobuf_setup |
|
|||
|
| signals_init | +-------------------------------+
|
|||
|
| bdev_init | | init/main.c:: |
|
|||
|
| inode_init | | init(): {...init thread...} |
|
|||
|
| [ipc_init] | | do_basic_setup |
|
|||
|
| [dquot_init_hash] | | {bus/dev init & initcalls}|
|
|||
|
| check_bugs | | free_initmem |
|
|||
|
| [smp_init] {*below} | | open /dev/console |
|
|||
|
| start init thread {---->} |.....| exec init script or shell |
|
|||
|
| unlock_kernel | | or panic |
|
|||
|
| cpu_idle | +-------------------------------+
|
|||
|
+-------------------------------+
|
|||
|
|
|||
|
|
|||
|
+-------------------------------+
|
|||
|
| smpboot.c::smp_init |
|
|||
|
|-------------------------------|
|
|||
|
| arch/i386/kernel/smpboot.c:: |
|
|||
|
| smp_boot_cpus(): |
|
|||
|
| [mtrr_init_boot_cpu] |
|
|||
|
| smp_store_cpu_info |
|
|||
|
| print_cpu_info |
|
|||
|
| save CPU ID/APIC ID mappings|
|
|||
|
| verify_local_APIC |
|
|||
|
| connect_bsp_APIC |
|
|||
|
| setup_local_APIC |
|
|||
|
| foreach valid APIC ID |
|
|||
|
| do_boot_cpu(apicid) |
|
|||
|
| setup_IO_APIC |
|
|||
|
| setup_APIC_clocks |
|
|||
|
| synchronize_tsc_bp |
|
|||
|
+-------------------------------+
|
|||
|
|
|||
|
|
|||
|
|
|||
|
3. Linux early setup
|
|||
|
|
|||
|
|
|||
|
(from linux/arch/i386/boot/setup.S and linux/arch/i386/boot/video.S)
|
|||
|
|
|||
|
NOTE: Register notation is %regname and constant notation is a
|
|||
|
number, with or without a leading '$' sign.
|
|||
|
|
|||
|
|
|||
|
3.1. IA-32 Kernel Setup
|
|||
|
|
|||
|
|
|||
|
"setup.S" is responsible for getting the system data from the BIOS and
|
|||
|
putting them into the appropriate places in system memory.
|
|||
|
|
|||
|
Both "setup.S" and the kernel have been loaded by the boot block.
|
|||
|
|
|||
|
"setup.S" is assembled as 16-bit real-mode code. It switches the
|
|||
|
processor to 32-bit protected mode and jumps to the 32-bit kernel
|
|||
|
code.
|
|||
|
|
|||
|
This code asks the BIOS for memory/disk/other parameters, and puts
|
|||
|
them in a "safe" place: 0x90000-0x901FF, that is, where the boot block
|
|||
|
used to be. It is then up to the protected mode system to read them
|
|||
|
from there before the area is overwritten for buffer-blocks.
|
|||
|
|
|||
|
The "setup.S" code begins with a jmp instruction around the "setup
|
|||
|
header", which must begin at location %cs:2.
|
|||
|
|
|||
|
This is the setup header:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
______________________________________________________________________
|
|||
|
.ascii "HdrS" # header signature
|
|||
|
.word 0x0202 # header version number
|
|||
|
realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
|
|||
|
start_sys_seg: .word SYSSEG
|
|||
|
.word kernel_version # pointer to kernel version string
|
|||
|
type_of_loader: .byte 0
|
|||
|
loadflags:
|
|||
|
LOADED_HIGH = 1 # If set, the kernel is loaded high
|
|||
|
#ifndef __BIG_KERNEL__
|
|||
|
.byte 0
|
|||
|
#else
|
|||
|
.byte LOADED_HIGH
|
|||
|
#endif
|
|||
|
setup_move_size: .word 0x8000 # size to move, when setup is not
|
|||
|
# loaded at 0x90000.
|
|||
|
code32_start: # here loaders can put a different
|
|||
|
# start address for 32-bit code.
|
|||
|
#ifndef __BIG_KERNEL__
|
|||
|
.long 0x1000 # default for zImage
|
|||
|
#else
|
|||
|
.long 0x100000# default for big kernel
|
|||
|
#endif
|
|||
|
ramdisk_image: .long 0 # address of loaded ramdisk image
|
|||
|
ramdisk_size: .long 0 # its size in bytes
|
|||
|
bootsect_kludge: .word bootsect_helper, SETUPSEG
|
|||
|
heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later)
|
|||
|
# space from here (exclusive) down to
|
|||
|
# end of setup code can be used by setup
|
|||
|
# for local heap purposes.
|
|||
|
pad1: .word 0
|
|||
|
cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
|
|||
|
# If nonzero, a 32-bit pointer
|
|||
|
# to the kernel command line.
|
|||
|
trampoline: call start_of_setup # no return from start_of_setup
|
|||
|
.space 1024
|
|||
|
# End of setup header #####################################################
|
|||
|
______________________________________________________________________
|
|||
|
|
|||
|
|
|||
|
|
|||
|
3.1.1. start_of_setup:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
3.1.1.1. Read second hard drive DASD type
|
|||
|
|
|||
|
|
|||
|
Read the DASD type of the second hard drive (BIOS int. 0x13,
|
|||
|
%ax=0x1500, %dl=0x81).
|
|||
|
|
|||
|
# Bootlin depends on this being done early. [TBD:why?]
|
|||
|
|
|||
|
|
|||
|
3.1.1.2. Check that LILO loaded us right
|
|||
|
|
|||
|
|
|||
|
Check the signature words at the end of setup. Signature words are
|
|||
|
used to ensure that LILO loaded us right. If the two words are not
|
|||
|
found correctly, copy the setup sectors and check for the signature
|
|||
|
words again. If they still aren't found, panic("No setup signature
|
|||
|
found ...").
|
|||
|
|
|||
|
|
|||
|
3.1.1.3. Check old loader trying to load a big kernel
|
|||
|
|
|||
|
|
|||
|
If the kernel image is "big" (and hence is "loaded high"), then if the
|
|||
|
loader cannot handle "loaded high" images, then panic ("Wrong loader,
|
|||
|
giving up...").
|
|||
|
|
|||
|
|
|||
|
|
|||
|
3.1.1.4. Determine system memory size
|
|||
|
|
|||
|
|
|||
|
Get the extended memory size {above 1 MB} in KB. First clear the
|
|||
|
extended memory size to 0.
|
|||
|
|
|||
|
#ifndef STANDARD_MEMORY_BIOS_CALL
|
|||
|
|
|||
|
Clear the E820 memory area counter.
|
|||
|
|
|||
|
Try three different memory detection schemes.
|
|||
|
First, try E820h, which lets us assemble a memory map, then try E801h,
|
|||
|
which returns a 32-bit memory size, and finally 88h, which returns
|
|||
|
0-64 MB.
|
|||
|
|
|||
|
Method E820H populates a table in the empty_zero_block that contains a
|
|||
|
list of usable address/size/type tuples. In
|
|||
|
"linux/arch/i386/kernel/setup.c", this information is transferred into
|
|||
|
the e820map, and in "linux/arch/i386/mm/init.c", that new information
|
|||
|
is used to mark pages reserved or not.
|
|||
|
|
|||
|
Method E820H:
|
|||
|
Get the BIOS memory map. E820h returns memory classified into
|
|||
|
different types and allows memory holes. We scan through this memory
|
|||
|
map and build a list of the first 32 memory areas {up to 32 entries or
|
|||
|
BIOS says that there are no more entries}, which we return at
|
|||
|
"E820MAP". [See URL:
|
|||
|
http://www.teleport.com/ acpi/acpihtml/topic245.htm]
|
|||
|
|
|||
|
Method E801H:
|
|||
|
We store the 0xe801 memory size in a completely different place,
|
|||
|
because it will most likely be longer than 16 bits.
|
|||
|
|
|||
|
This is the sum of 2 registers, normalized to 1 KB chunk sizes: %ecx =
|
|||
|
memory size from 1 MB to 16 MB range, in 1 KB chunks + %edx = memory
|
|||
|
size above 16 MB, in 64 KB chunks.
|
|||
|
|
|||
|
Ye Olde Traditional Methode:
|
|||
|
BIOS int. 0x15/AH=0x88 returns the memory size (up to 16 MB or 64 MB,
|
|||
|
depending on the BIOS). We always use this method, regardless of the
|
|||
|
results of the other two methods.
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
Set the keyboard repeat rate to the maximum rate using using BIOS int.
|
|||
|
0x16.
|
|||
|
|
|||
|
|
|||
|
3.1.1.5. Video adapter modes
|
|||
|
|
|||
|
|
|||
|
Find the video adapter and its supported modes and allow the user to
|
|||
|
browse video modes.
|
|||
|
|
|||
|
call video # {see Video section below}
|
|||
|
|
|||
|
|
|||
|
3.1.1.6. Get Hard Disk parameters
|
|||
|
|
|||
|
|
|||
|
Get hd0 data: Save the hd0 descriptor (from int. vector 0x41) at
|
|||
|
INITSEG:0x80 length 0x10.
|
|||
|
|
|||
|
Get hd1 data: Save the hd1 descriptor (from int. vector 0x46) at
|
|||
|
INITSEG:0x90 length 0x10.
|
|||
|
|
|||
|
Check that there IS an hd1, using BIOS int. 0x13. If not, clear its
|
|||
|
descriptor.
|
|||
|
|
|||
|
|
|||
|
3.1.1.7. Get Micro Channel bus information
|
|||
|
|
|||
|
|
|||
|
Check for Micro Channel (MCA) bus:
|
|||
|
|
|||
|
<20> Set MCA feature table length to 0 in case not found.
|
|||
|
|
|||
|
<20> Get System Configuration Parameters (BIOS int. 0x15/%ah=0xc0).
|
|||
|
This sets %es:%bx to point to the system feature table.
|
|||
|
|
|||
|
<20> We keep only the first 16 bytes of the system feature table if
|
|||
|
found: Structure size, Model byte, Submodel byte, BIOS revision,
|
|||
|
and Feature information bytes 1-5. Bit 0 or 1 (either one) of
|
|||
|
Feature byte 1 indicates that the system contains a Micro Channel
|
|||
|
bus.
|
|||
|
|
|||
|
|
|||
|
3.1.1.8. Check for mouse
|
|||
|
|
|||
|
|
|||
|
Check for PS/2 pointing device by using BIOS int. 0x11 {get equipment
|
|||
|
list}.
|
|||
|
|
|||
|
<20> Clear the pointing device flag (default).
|
|||
|
|
|||
|
<20> BIOS int. 0x11: get equipment list.
|
|||
|
|
|||
|
<20> If bit 2 (value 0x04) is set, then a mouse is installed and the
|
|||
|
pointing device flag is set to indicate that the device is present.
|
|||
|
|
|||
|
|
|||
|
3.1.1.9. Check for APM BIOS support
|
|||
|
|
|||
|
|
|||
|
Check for an APM BIOS (if kernel is configured for APM support):
|
|||
|
|
|||
|
<20> start: clear version field to 0, which means no APM BIOS present.
|
|||
|
|
|||
|
<20> Check for APM BIOS installation using BIOS int. 0x15.
|
|||
|
|
|||
|
<20> If not present, done.
|
|||
|
|
|||
|
<20> Check for "PM" signature returned in %bx.
|
|||
|
|
|||
|
<20> If no signature, then no APM BIOS: done.
|
|||
|
|
|||
|
<20> Check for 32-bit support in %cx.
|
|||
|
|
|||
|
<20> If no 32-bit support, no (good) APM BIOS: done. Must have 32-bit
|
|||
|
APM BIOS support to be used by Linux.
|
|||
|
|
|||
|
<20> Save the BIOS code segment, BIOS entry point offset, BIOS 16-bit
|
|||
|
code segment, BIOS data segment, BIOS code segment length, and BIOS
|
|||
|
data segment length.
|
|||
|
|
|||
|
<20> Record the APM BIOS version and flags.
|
|||
|
|
|||
|
|
|||
|
3.1.1.10. Prepare to move to protected mode
|
|||
|
|
|||
|
|
|||
|
We build a jump instruction to the kernel's code32_start address.
|
|||
|
(The loader may have changed it.)
|
|||
|
|
|||
|
Move the kernel to its correct place if necessary.
|
|||
|
|
|||
|
Load the segment descriptors (load %ds = %cs).
|
|||
|
|
|||
|
Make sure that we are at the right position in memory, to accommodate
|
|||
|
the command line and boot parameters at their fixed locations.
|
|||
|
|
|||
|
Load the IDT pointer register with 0,0.
|
|||
|
|
|||
|
Calculate the linear base address of the kernel GDT (table) and load
|
|||
|
the GDT pointer register with its base address and limit. This early
|
|||
|
kernel GDT describes kernel code as 4 GB, with base address 0,
|
|||
|
code/readable/executable, with granularity of 4 KB. The kernel data
|
|||
|
segment is described as 4 GB, with base address 0,
|
|||
|
data/readable/writable, with granularity of 4 KB.
|
|||
|
|
|||
|
|
|||
|
3.1.1.11. Enable address line A20
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<20> Empty the 8042 (keyboard controller) of any queued keys.
|
|||
|
|
|||
|
<20> Write 0xd1 (Write Output Port) to Command Register port 0x64.
|
|||
|
|
|||
|
<20> Empty the 8042 (keyboard controller) of any queued keys.
|
|||
|
|
|||
|
<20> Write 0xdf (Gate A20 + more) to Output port 0x60.
|
|||
|
|
|||
|
<20> Empty the 8042 (keyboard controller) of any queued keys.
|
|||
|
|
|||
|
<20> Set bit number 1 (value 0x02: FAST_A20) in the "port 0x92" system
|
|||
|
control register. This enables A20 on some systems, depending on
|
|||
|
the chipset used in them.
|
|||
|
|
|||
|
<20> Wait until A20 really *is* enabled; it can take a fair amount of
|
|||
|
time on certain systems. The memory location used here (0x200) is
|
|||
|
the int 0x80 vector, which should be safe to use. When A20 is
|
|||
|
disabled, the test memory locations are an alias of each other
|
|||
|
(segment 0:offset 0x200 and segment 0xffff:offset 0x210). {0xffff0
|
|||
|
+ 0x210 = 0x100200, but if A20 is disabled, this becomes 0x000200.}
|
|||
|
We just wait (busy wait/loop) until these memory locations are no
|
|||
|
longer aliased.
|
|||
|
|
|||
|
|
|||
|
3.1.1.12. Make sure any possible coprocessor is properly reset
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<20> Write 0 to port 0xf0 to clear the Math Coprocessor '-busy' signal.
|
|||
|
|
|||
|
<20> Write 0 to port 0xf1 to reset the Math Coprocessor.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
3.1.1.13. Mask all interrupts
|
|||
|
|
|||
|
|
|||
|
Now we mask all interrupts; the rest is done in init_IRQ().
|
|||
|
|
|||
|
|
|||
|
<20> Mask off all interrupts on the slave PIC: write 0xff to port 0xa1.
|
|||
|
|
|||
|
<20> Mask off all interrupts on the master PIC except for IRQ2, which is
|
|||
|
the cascaded IRQ input from the slave PIC: write 0xfb to port 0x21.
|
|||
|
|
|||
|
|
|||
|
3.1.1.14. Move to Protected Mode
|
|||
|
|
|||
|
|
|||
|
Now is the time to actually move into protected mode. To make things
|
|||
|
as simple as possible, we do no register setup or anything, we let the
|
|||
|
GNU-compiled 32-bit programs do that. We just jump to absolute
|
|||
|
address 0x1000 (or the loader supplied one), in 32-bit protected mode.
|
|||
|
|
|||
|
Note that the short jump isn't strictly needed, although there are
|
|||
|
reasons why it might be a good idea. It won't hurt in any case.
|
|||
|
|
|||
|
Set the PE (Protected mode Enable) bit in the MSW and jump to the
|
|||
|
following instruction to flush the instruction fetch queue.
|
|||
|
|
|||
|
Clear %bx to indicate that this is the BSP (first CPU only).
|
|||
|
|
|||
|
|
|||
|
3.1.1.15. Jump to startup_32 code
|
|||
|
|
|||
|
|
|||
|
Jump to the 32-bit kernel code (startup_32).
|
|||
|
|
|||
|
NOTE: For high-loaded big kernels we need:
|
|||
|
|
|||
|
|
|||
|
jmpi 0x100000,__KERNEL_CS
|
|||
|
|
|||
|
|
|||
|
|
|||
|
but we yet haven't reloaded the %cs register, so the default size of
|
|||
|
the target offset still is 16 bit. However, using an operand prefix
|
|||
|
(0x66), the CPU will properly take our 48-bit far pointer. (INTeL
|
|||
|
80386 Programmer's Reference Manual, Mixing 16-bit and 32-bit code,
|
|||
|
page 16-6).
|
|||
|
|
|||
|
|
|||
|
|
|||
|
.byte 0x66, 0xea # prefix + jmpi-opcode
|
|||
|
code32: .long 0x1000 # or 0x100000 for big kernels
|
|||
|
.word __KERNEL_CS
|
|||
|
|
|||
|
|
|||
|
|
|||
|
This jumps to "startup_32" in "linux/arch/i386/kernel/head.S".
|
|||
|
|
|||
|
|
|||
|
3.2. Video Setup
|
|||
|
|
|||
|
|
|||
|
"linux/arch/i386/boot/video.S" is included into
|
|||
|
"linux/arch/i386/boot/setup.S", so they are assembled together. The
|
|||
|
file separation is a logical module separation even though the two
|
|||
|
modules aren't built separately.
|
|||
|
|
|||
|
"video.S" handles Linux/i386 display adapter and video mode setup.
|
|||
|
For more information about Linux/i386 video modes, see
|
|||
|
"linux/Documentation/svga.txt" by Martin Mares [mj@ucw.cz].
|
|||
|
|
|||
|
Video mode selection is a kernel build option. When it is enabled,
|
|||
|
You can select a specific (fixed) video mode to be used during kernel
|
|||
|
booting or you can ask to view a selection menu and then choose a
|
|||
|
video mode from that menu.
|
|||
|
|
|||
|
There are a few esoteric (!) "video.S" build options that not covered
|
|||
|
here. See "linux/Documentation/svga.txt" for all of them.
|
|||
|
|
|||
|
CONFIG_VIDEO_SVGA (for automatic detection of SVGA adapters and modes)
|
|||
|
is normally #undefined. The normal method of video adapter detection
|
|||
|
on Linux/i386 is VESA (CONFIG_VIDEO_VESA, for autodetection of VESA
|
|||
|
modes).
|
|||
|
|
|||
|
"video:" is the main entry point called by "setup.S". The %ds
|
|||
|
register *must* be pointing to the bootsector. The "video.S" code
|
|||
|
uses different segments from the main "setup.S" code.
|
|||
|
|
|||
|
This is a simplified description of the code flow in "video.S". It
|
|||
|
does not address the CONFIG_VIDEO_LOCAL, CONFIG_VIDEO_400_HACK, and
|
|||
|
CONFIG_VIDEO_GFX_HACK build options and it does not dive deep into
|
|||
|
video BIOS calls or video register accesses.
|
|||
|
|
|||
|
|
|||
|
3.2.1. video:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<20> %fs is set to the original %ds value
|
|||
|
|
|||
|
<20> %ds and %es are set to %cs
|
|||
|
|
|||
|
<20> %gs is set to zero
|
|||
|
|
|||
|
<20> Detect the video adapter type and supported modes. (call
|
|||
|
basic_detect)
|
|||
|
|
|||
|
<20> #ifdef CONFIG_VIDEO_SELECT
|
|||
|
|
|||
|
<20> If the user wants to see a list of the supported VGA adapter modes,
|
|||
|
list them. (call mode_menu)
|
|||
|
|
|||
|
<20> Set the selected video mode. (call mode_set)
|
|||
|
|
|||
|
<20> #ifdef CONFIG_VIDEO_RETAIN
|
|||
|
|
|||
|
<20> Restore the screen contents. (call restore_screen)
|
|||
|
|
|||
|
<20> #endif /* CONFIG_VIDEO_RETAIN */
|
|||
|
|
|||
|
<20> #endif /* CONFIG_VIDEO_SELECT */
|
|||
|
|
|||
|
<20> Store mode parameters for kernel. (call mode_params)
|
|||
|
|
|||
|
<20> Restore original DS register value.
|
|||
|
|
|||
|
|
|||
|
3.2.1.1. basic_detect:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<20> Detect if we have CGA, MDA, HGA, EGA, or VGA and pass it to the
|
|||
|
kernel.
|
|||
|
|
|||
|
<20> Check for EGA/VGA using BIOS int. 0x10 calls. This also tells
|
|||
|
whether the video adapter is CGA/MDA/HGA.
|
|||
|
|
|||
|
<20> The "adapter" variable is returned as 0 for CGA/MDA/HGA, 1 for EGA,
|
|||
|
and 2 for VGA.
|
|||
|
|
|||
|
|
|||
|
3.2.1.2. mode_params:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<20> Store the video mode parameters for later use by the kernel. This
|
|||
|
is done by asking the BIOS for mode parameters except for the
|
|||
|
rows/columns parameters in the default 80x25 mode -- these are set
|
|||
|
directly, because some very obscure BIOSes supply insane values.
|
|||
|
|
|||
|
<20> #ifdef CONFIG_VIDEO_SELECT
|
|||
|
|
|||
|
<20> For graphics mode with a linear frame buffer, goto mopar_gr.
|
|||
|
|
|||
|
<20> #endif /* CONFIG_VIDEO_SELECT */
|
|||
|
|
|||
|
<20> For MDA/CGA/HGA/EGA/VGA:
|
|||
|
|
|||
|
<20> Read and save cursor position.
|
|||
|
|
|||
|
<20> Read and save video page/mode/width.
|
|||
|
|
|||
|
<20> For MDA/HGA, change the video_segment to $0xb000. (Leave it at its
|
|||
|
initial value of $0xb800 for all other adapters.)
|
|||
|
|
|||
|
<20> Get the Font size (valid only on EGA/VGA).
|
|||
|
|
|||
|
<20> Save the number of video columns and lines.
|
|||
|
|
|||
|
#ifdef CONFIG_VIDEO_SELECT
|
|||
|
|
|||
|
|
|||
|
3.2.1.3. mopar_gr:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<20> Get VESA frame buffer parameters.
|
|||
|
|
|||
|
<20> Get video mem size and protected mode interface information using
|
|||
|
BIOS int. 0x10 calls.
|
|||
|
|
|||
|
|
|||
|
3.2.1.4. mode_menu:
|
|||
|
|
|||
|
|
|||
|
Build the mode list table and display the mode menu.
|
|||
|
|
|||
|
|
|||
|
3.2.1.5. mode_set:
|
|||
|
|
|||
|
|
|||
|
For the selected video mode, use BIOS int. 0x10 calls or register
|
|||
|
writes as needed to set some or all of:
|
|||
|
|
|||
|
<20> Reset the video mode
|
|||
|
|
|||
|
|
|||
|
<20> Number of scan lines
|
|||
|
|
|||
|
<20> Font pixel size
|
|||
|
|
|||
|
<20> Save the screen size in force_size. "force_size" is used to
|
|||
|
override possibly broken video BIOS interfaces and is used instead
|
|||
|
of the BIOS variables.
|
|||
|
|
|||
|
Some video modes require register writes to set:
|
|||
|
|
|||
|
<20> Location of the cursor scan lines
|
|||
|
|
|||
|
<20> Vertical sync start
|
|||
|
|
|||
|
<20> Vertical sync end
|
|||
|
|
|||
|
<20> Vertical display end
|
|||
|
|
|||
|
<20> Vertical blank start
|
|||
|
|
|||
|
<20> Vertical blank end
|
|||
|
|
|||
|
<20> Vertical total
|
|||
|
|
|||
|
<20> (Vertical) overflow
|
|||
|
|
|||
|
<20> Correct sync polarity
|
|||
|
|
|||
|
<20> Preserve clock select bits and color bit
|
|||
|
|
|||
|
{end of mode_set}
|
|||
|
|
|||
|
#ifdef CONFIG_VIDEO_RETAIN /* Normally _IS_ #defined */
|
|||
|
|
|||
|
|
|||
|
3.2.1.6. store_screen:
|
|||
|
|
|||
|
|
|||
|
CONFIG_VIDEO_RETAIN is used to retain screen contents when switching
|
|||
|
modes. This option stores the screen contents to a temporary memory
|
|||
|
buffer (if there is enough memory) so that they can be restored later.
|
|||
|
|
|||
|
|
|||
|
<20> Save the current number of video lines and columns, cursor
|
|||
|
position, and video mode.
|
|||
|
|
|||
|
<20> Calculate the image size.
|
|||
|
|
|||
|
<20> Save the screen image.
|
|||
|
|
|||
|
<20> Set the "do_restore" flag so that the screen contents will be
|
|||
|
restored at the end of video mode detection/selection.
|
|||
|
|
|||
|
|
|||
|
3.2.1.7. restore_screen:
|
|||
|
|
|||
|
|
|||
|
Restores screen contents from temporary buffer (if already saved).
|
|||
|
|
|||
|
|
|||
|
<20> Get parameters of current mode.
|
|||
|
|
|||
|
<20> Set cursor position.
|
|||
|
|
|||
|
<20> Restore the screen contents.
|
|||
|
|
|||
|
#endif /* CONFIG_VIDEO_RETAIN */
|
|||
|
|
|||
|
|
|||
|
3.2.1.8. mode_table:
|
|||
|
|
|||
|
|
|||
|
Build the table of video modes at `modelist'.
|
|||
|
|
|||
|
|
|||
|
<20> Store standard modes.
|
|||
|
|
|||
|
<20> Add modes for standard VGA.
|
|||
|
|
|||
|
<20> #ifdef CONFIG_VIDEO_LOCAL
|
|||
|
|
|||
|
<20> Add locally-defined video modes. (call local_modes)
|
|||
|
|
|||
|
<20> #endif /* CONFIG_VIDEO_LOCAL */
|
|||
|
|
|||
|
<20> #ifdef CONFIG_VIDEO_VESA
|
|||
|
|
|||
|
<20> Auto-detect VESA VGA modes. (call vesa_modes)
|
|||
|
|
|||
|
<20> #endif /* CONFIG_VIDEO_VESA */
|
|||
|
|
|||
|
<20> #ifdef CONFIG_VIDEO_SVGA
|
|||
|
|
|||
|
<20> Detect SVGA cards & modes. (call svga_modes)
|
|||
|
|
|||
|
<20> #endif /* CONFIG_VIDEO_SVGA */
|
|||
|
|
|||
|
<20> #ifdef CONFIG_VIDEO_COMPACT
|
|||
|
|
|||
|
<20> Compact the video modes list, removing duplicate entries.
|
|||
|
|
|||
|
<20> #endif /* CONFIG_VIDEO_COMPACT */
|
|||
|
|
|||
|
|
|||
|
3.2.1.9. mode_scan:
|
|||
|
|
|||
|
|
|||
|
Scans for video modes.
|
|||
|
|
|||
|
|
|||
|
<20> Start with mode 0.
|
|||
|
|
|||
|
<20> Test the mode.
|
|||
|
|
|||
|
<20> Test if it's a text mode.
|
|||
|
|
|||
|
<20> OK, store the mode.
|
|||
|
|
|||
|
<20> Restore back to mode 3.
|
|||
|
|
|||
|
#ifdef CONFIG_VIDEO_SVGA
|
|||
|
|
|||
|
|
|||
|
3.2.1.10. svga_modes:
|
|||
|
|
|||
|
|
|||
|
Try to detect the type of SVGA card and supply (usually approximate)
|
|||
|
video mode table for it.
|
|||
|
|
|||
|
|
|||
|
<20> Test all known SVGA adapters.
|
|||
|
|
|||
|
<20> Call the test routine for each adapter.
|
|||
|
|
|||
|
<20> If adapter is found, copy the video modes.
|
|||
|
|
|||
|
<20> Store pointer to card name.
|
|||
|
|
|||
|
#endif /* CONFIG_VIDEO_SVGA */
|
|||
|
|
|||
|
#endif /* CONFIG_VIDEO_SELECT */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
4. Linux architecture-specific initialization
|
|||
|
|
|||
|
|
|||
|
(from "linux/arch/i386/kernel/head.S")
|
|||
|
|
|||
|
The boot code in "linux/arch/i386/boot/setup.S" transfers execution to
|
|||
|
the beginning code in "linux/arch/i386/kernel/head.S" (labeled
|
|||
|
"startup_32:").
|
|||
|
|
|||
|
To get to this point, a small uncompressed kernel function
|
|||
|
decompresses the remaining compressed kernel image and then it jumps
|
|||
|
to the new kernel code.
|
|||
|
|
|||
|
This is a description of what the "head.S" code does.
|
|||
|
|
|||
|
|
|||
|
4.1. startup_32:
|
|||
|
|
|||
|
|
|||
|
swapper_pg_dir is the top-level page directory, address 0x00101000.
|
|||
|
|
|||
|
On entry, %esi points to the real-mode code as a 32-bit pointer.
|
|||
|
|
|||
|
|
|||
|
4.2. Set segment registers to known values
|
|||
|
|
|||
|
|
|||
|
Set the %ds, %es, %fs, and %gs registers to __KERNEL_DS.
|
|||
|
|
|||
|
|
|||
|
4.3. SMP BSP (Bootstrap Processor) check
|
|||
|
|
|||
|
|
|||
|
#ifdef CONFIG_SMP
|
|||
|
|
|||
|
If %bx is zero, this is a boot on the Bootstrap Processor (BSP), so
|
|||
|
skip this. Otherwise, for an AP (Application Processor):
|
|||
|
|
|||
|
If the desired %cr4 setting is non-zero, turn on the paging options
|
|||
|
(PSE, PAE, ...) and skip "Initialize page tables" (jump to "Enable
|
|||
|
paging").
|
|||
|
|
|||
|
#endif /* CONFIG_SMP */
|
|||
|
|
|||
|
|
|||
|
4.4. Initialize page tables
|
|||
|
|
|||
|
|
|||
|
Begin at pg0 (page 0) and init all pages to 007 (PRESENT + RW + USER).
|
|||
|
|
|||
|
|
|||
|
4.5. Enable paging
|
|||
|
|
|||
|
|
|||
|
Set %cr3 (page table pointer) to swapper_pg_dir.
|
|||
|
|
|||
|
Set the paging ("PG") bit of %cr0 to
|
|||
|
********** enable paging **********.
|
|||
|
|
|||
|
Jump $ to flush the prefetch queue.
|
|||
|
|
|||
|
Jump *[$] to make sure that %eip is relocated.
|
|||
|
|
|||
|
Setup the stack pointer (lss stack_start, %esp).
|
|||
|
|
|||
|
|
|||
|
#ifdef CONFIG_SMP
|
|||
|
|
|||
|
If this is not the BSP (Bootstrap Processor), clear all flags bits and
|
|||
|
jump to checkCPUtype.
|
|||
|
|
|||
|
#endif /* CONFIG_SMP */
|
|||
|
|
|||
|
|
|||
|
4.6. Clear BSS
|
|||
|
|
|||
|
|
|||
|
The BSP clears all of BSS (area between __bss_start and _end) for the
|
|||
|
kernel.
|
|||
|
|
|||
|
|
|||
|
4.7. 32-bit setup
|
|||
|
|
|||
|
|
|||
|
Setup the IDT for 32-bit mode (call setup_idt). setup_idt sets up an
|
|||
|
IDT with 256 entries pointing to the default interrupt handler
|
|||
|
"ignore_int" as interrupt gates. It doesn't actually load the IDT;
|
|||
|
that can be done only after paging has been enabled and the kernel
|
|||
|
moved to PAGE_OFFSET. Interrupts are enabled elsewhere, when we can
|
|||
|
be relatively sure everything is OK.
|
|||
|
|
|||
|
Clear the eflags register (before switching to protected mode).
|
|||
|
|
|||
|
|
|||
|
4.8. Copy boot parameters and command line out of the way
|
|||
|
|
|||
|
|
|||
|
First 2 KB of _empty_zero_page is for boot parameters, second 2 KB is
|
|||
|
for the command line.
|
|||
|
|
|||
|
|
|||
|
4.9. checkCPUtype
|
|||
|
|
|||
|
|
|||
|
Initialize X86_CPUID to -1.
|
|||
|
|
|||
|
Use Flags register, push/pop results, and CPUID instruction(s) to
|
|||
|
determine CPU type and vendor: Sets X86, X86_CPUID, X86_MODEL,
|
|||
|
X86_MASK, and X86_CAPABILITY. Sets bits in %cr0 accordingly.
|
|||
|
|
|||
|
Also checks for presence of an 80287 or 80387 coprocessor. Sets
|
|||
|
X86_HARD_MATH if a math coprocessor or floating point unit is found.
|
|||
|
|
|||
|
|
|||
|
4.10. Count this processor
|
|||
|
|
|||
|
|
|||
|
For CONFIG_SMP builds, increment the "ready" counter to keep a tally
|
|||
|
of the number of CPUs that have been initialized.
|
|||
|
|
|||
|
|
|||
|
4.11. Load descriptor table pointer registers
|
|||
|
|
|||
|
|
|||
|
Load GDT with gdt_descr and IDT with idt_descr. The GDT contains 2
|
|||
|
entries for the kernel (4 GB each for code and data, beginning at 0)
|
|||
|
and 2 userspace entries (4 GB each for code and data, beginning at 0).
|
|||
|
There are 2 null descriptors between the userspace descriptors and the
|
|||
|
APM descriptors.
|
|||
|
|
|||
|
The GDT also contains 4 entries for APM segments. The APM segments
|
|||
|
have byte granularity and their bases and limits are set at runtime.
|
|||
|
The rest of the gdt_table (after the APM segments) is space for TSSes
|
|||
|
and LDTs.
|
|||
|
|
|||
|
Jump to __KERNEL_CS:%eip to cause the GDT to be used. Now in
|
|||
|
********** protected mode **********.
|
|||
|
|
|||
|
Reload all of the segment registers: Set the %ds, %es, %fs, and %gs
|
|||
|
registers to __KERNEL_DS.
|
|||
|
|
|||
|
#ifdef CONFIG_SMP
|
|||
|
|
|||
|
Reload the stack pointer segment only (%ss) with __KERNEL_DS.
|
|||
|
|
|||
|
#else /* not CONFIG_SMP */
|
|||
|
|
|||
|
Reload the stack pointer (%ss:%esp) with stack_start.
|
|||
|
|
|||
|
#endif /* CONFIG_SMP */
|
|||
|
|
|||
|
Clear the LDT pointer to 0.
|
|||
|
|
|||
|
Clear the processor's Direction Flag (DF) to 0 for gcc.
|
|||
|
|
|||
|
|
|||
|
4.12. Start other processors
|
|||
|
|
|||
|
|
|||
|
For CONFIG_SMP builds, if this is not the first (Bootstrap) CPU, call
|
|||
|
initialize_secondary(), which does not return. The secondary (AP)
|
|||
|
processor(s) are initialized and then enter idle state until processes
|
|||
|
are scheduled on them.
|
|||
|
|
|||
|
If this is the first or only CPU, call start_kernel(). (see below)
|
|||
|
|
|||
|
/* the calls above should never return, but in case they do: */
|
|||
|
|
|||
|
L6: jmp L6
|
|||
|
|
|||
|
|
|||
|
|
|||
|
5. Linux architecture-independent initialization
|
|||
|
|
|||
|
|
|||
|
(from "linux/init/main.c")
|
|||
|
|
|||
|
"linux/init/main.c" begins execution with the start_kernel() function,
|
|||
|
which is called from "linux/arch/i386/kernel/head.S". start_kernel()
|
|||
|
never returns to its caller. It ends by calling the cpu_idle()
|
|||
|
function.
|
|||
|
|
|||
|
|
|||
|
5.1. start_kernel:
|
|||
|
|
|||
|
|
|||
|
Interrupts are still disabled. Do necessary setups, then enable them.
|
|||
|
|
|||
|
Lock the kernel (BKL: big kernel lock).
|
|||
|
|
|||
|
Print the linux_banner string (this string resides in
|
|||
|
"linux/init/version.c") using printk(). NOTE: printk() doesn't
|
|||
|
actually print this to the console yet; it just buffers the string
|
|||
|
until a console device registers itself with the kernel, then the
|
|||
|
kernel passes the buffered console log contents to the registered
|
|||
|
console device(s). There can be multiple registered console devices.
|
|||
|
|
|||
|
********** printk() can be called very early because it doesn't
|
|||
|
actually print to anywhere. It just logs the message to "log_buf",
|
|||
|
which is allocated statically in "linux/kernel/printk.c". The
|
|||
|
messages that are saved in "log_buf" are passed to registered console
|
|||
|
devices as they register. **********
|
|||
|
|
|||
|
|
|||
|
5.1.1. More architecture-specific init
|
|||
|
|
|||
|
|
|||
|
Call setup_arch(&command_line):
|
|||
|
|
|||
|
This performs architecture-specific initializations (details below).
|
|||
|
Then back to architecture-independent initialization....
|
|||
|
|
|||
|
The remainder of start_kernel() is done as follows for all processor
|
|||
|
architecures, although several of these function calls are to
|
|||
|
architecture-specific setup/init functions.
|
|||
|
|
|||
|
|
|||
|
5.1.2. Continue architecture-independent init
|
|||
|
|
|||
|
Print the kernel command line.
|
|||
|
|
|||
|
|
|||
|
5.1.3. Parsing command line options
|
|||
|
|
|||
|
|
|||
|
parse_options(command_line): Parse the kernel options on the command
|
|||
|
line. This is a simple kernel command line parsing function. It
|
|||
|
parses the command line and fills in the arguments and environment to
|
|||
|
init (thread) as appropriate. Any command-line option is taken to be
|
|||
|
an environment variable if it contains the character '='. It also
|
|||
|
checks for options meant for the kernel by calling checksetup(), which
|
|||
|
checks the command line for kernel parameters, these being specified
|
|||
|
by declaring them using "__setup", as in:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
______________________________________________________________________
|
|||
|
__setup("debug", debug_kernel);
|
|||
|
______________________________________________________________________
|
|||
|
|
|||
|
|
|||
|
|
|||
|
This declaration causes the debug_kernel() function to be called when
|
|||
|
the string "debug" is scanned. See "linux/Documentation/kernel-
|
|||
|
parameters.txt" for the list of kernel parameters.
|
|||
|
|
|||
|
These options are not given to init -- they are for internal kernel
|
|||
|
use only. The default argument list for the init thread is {"init",
|
|||
|
NULL}, with a maximum of 8 command-line arguments. The default
|
|||
|
environment list for the init thread is {"HOME=/", "TERM=linux",
|
|||
|
NULL}, with a maximum of 8 command-line environment variable settings.
|
|||
|
In case LILO is going to boot us with default command line, it
|
|||
|
prepends "auto" before the whole cmdline which makes the shell think
|
|||
|
it should execute a script with such name. So we ignore all arguments
|
|||
|
entered _before_ init=... [MJ]
|
|||
|
|
|||
|
|
|||
|
5.1.4. trap_init
|
|||
|
|
|||
|
|
|||
|
(in linux/arch/i386/kernel/traps.c)
|
|||
|
|
|||
|
Install exception handlers for basic processor exceptions, i.e., not
|
|||
|
hardware device interrupt handlers.
|
|||
|
|
|||
|
Install the handler for the system call software interrupt.
|
|||
|
|
|||
|
Install handlers for lcall7 (for iBCS) and lcall27 (for Solaris/x86
|
|||
|
binaries).
|
|||
|
|
|||
|
Call cpu_init() to do:
|
|||
|
|
|||
|
<20> initialize per-CPU state
|
|||
|
|
|||
|
<20> reload the GDT and IDT
|
|||
|
|
|||
|
<20> mask off the eflags NT (Nested Task) bit
|
|||
|
|
|||
|
<20> set up and load the per-CPU TSS and LDT
|
|||
|
|
|||
|
<20> clear 6 debug registers (0, 1, 2, 3, 6, and 7)
|
|||
|
|
|||
|
<20> stts(): set the 0x08 bit (TS: Task Switched) in CR0 to enable lazy
|
|||
|
register saves on context switches
|
|||
|
|
|||
|
|
|||
|
5.1.5. init_IRQ
|
|||
|
|
|||
|
|
|||
|
(in linux/arch/i386/kernel/i8259.c)
|
|||
|
|
|||
|
Call init_ISA_irqs() to initialize the two 8259A interrupt controllers
|
|||
|
and install default interrupt handlers for the ISA IRQs.
|
|||
|
|
|||
|
Set an interrupt gate for all unused interrupt vectors.
|
|||
|
|
|||
|
For CONFIG_SMP configurations, set up IRQ 0 early, since it's used
|
|||
|
before the IO APIC is set up.
|
|||
|
|
|||
|
For CONFIG_SMP, install the interrupt handler for CPU-to-CPU IPIs that
|
|||
|
are used for the "reschedule helper."
|
|||
|
For CONFIG_SMP, install the interrupt handler for the IPI that is used
|
|||
|
to invalidate TLBs.
|
|||
|
|
|||
|
For CONFIG_SMP, install the interrupt handler for the IPI that is used
|
|||
|
for generic function calls.
|
|||
|
|
|||
|
For CONFIG_X86_LOCAL_APIC configurations, install the interrupt
|
|||
|
handler for the self-generated local APIC timer IPI.
|
|||
|
|
|||
|
For CONFIG_X86_LOCAL_APIC configurations, install interrupt handlers
|
|||
|
for spurious and error interrupts.
|
|||
|
|
|||
|
Set the system's clock chip to generate a timer tick interrupt every
|
|||
|
HZ Hz.
|
|||
|
|
|||
|
If the system has an external FPU, set up IRQ 13 to handle floating
|
|||
|
point exceptions.
|
|||
|
|
|||
|
|
|||
|
5.1.6. sched_init
|
|||
|
|
|||
|
|
|||
|
(in linux/kernel/sched.c)
|
|||
|
|
|||
|
|
|||
|
<20> Set the init_task's processor ID.
|
|||
|
|
|||
|
<20> Clear the pidhash table. TBD: Why? isn't it in BSS?
|
|||
|
|
|||
|
<20> call init_timervecs()
|
|||
|
|
|||
|
<20> call init_bh() to init "bottom half" queues for timer_bh,
|
|||
|
tqueue_bh, and immediate_bh.
|
|||
|
|
|||
|
|
|||
|
5.1.7. time_init
|
|||
|
|
|||
|
|
|||
|
(in linux/arch/i386/kernel/time.c)
|
|||
|
|
|||
|
Initialize the system's current time of day (xtime) from CMOS.
|
|||
|
|
|||
|
Install the irq0 timer tick interrupt handler.
|
|||
|
|
|||
|
|
|||
|
5.1.8. softirq_init
|
|||
|
|
|||
|
|
|||
|
(in linux/kernel/softirq.c)
|
|||
|
|
|||
|
|
|||
|
5.1.9. console_init
|
|||
|
|
|||
|
|
|||
|
(in linux/drivers/char/tty_io.c)
|
|||
|
|
|||
|
HACK ALERT! This is early. We're enabling the console before we've
|
|||
|
done PCI setups etc., and console_init() must be aware of this. But
|
|||
|
we do want output early, in case something goes wrong.
|
|||
|
|
|||
|
|
|||
|
5.1.10. init_modules
|
|||
|
|
|||
|
|
|||
|
(in linux/kernel/module.c)
|
|||
|
|
|||
|
For CONFIG_MODULES configurations, call init_modules(). This
|
|||
|
initializes the size (or number of symbols) of the kernel symbol
|
|||
|
table.
|
|||
|
|
|||
|
|
|||
|
5.1.11. Profiling setup
|
|||
|
|
|||
|
|
|||
|
if profiling ("profile=#" on the kernel command line): calculate the
|
|||
|
kernel text (code) profile "segment" size; calculate the profile
|
|||
|
buffer size in pages (round up); allocate the profile buffer:
|
|||
|
prof_buffer = alloc_bootmem(size);
|
|||
|
|
|||
|
|
|||
|
5.1.12. kmem_cache_init
|
|||
|
|
|||
|
|
|||
|
(in linux/mm/slab.c)
|
|||
|
|
|||
|
|
|||
|
5.1.13. sti
|
|||
|
|
|||
|
|
|||
|
********** Interrupts are now enabled. **********
|
|||
|
This allows "calibrate_delay()" (below) to work.
|
|||
|
|
|||
|
|
|||
|
5.1.14. calibrate_delay
|
|||
|
|
|||
|
|
|||
|
Calculate the "loops_per_jiffy" delay loop value and print it in
|
|||
|
BogoMIPS.
|
|||
|
|
|||
|
|
|||
|
5.1.15. INITRD setup
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
|||
|
|
|||
|
if (initrd_start && !initrd_below_start_ok &&
|
|||
|
initrd_start < (min_low_pfn << PAGE_SHIFT)) {
|
|||
|
printk("initrd overwritten (initrd_start < (min_low_pfn << PAGE_SHIFT)) - disabling it.\n");
|
|||
|
initrd_start = 0; // mark initrd as disabled
|
|||
|
}
|
|||
|
|
|||
|
#endif /* CONFIG_BLK_DEV_INITRD */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
5.1.16. mem_init
|
|||
|
|
|||
|
|
|||
|
(in linux/arch/i386/mm/init.c)
|
|||
|
|
|||
|
|
|||
|
<20> Clear the empty_zero_page.
|
|||
|
|
|||
|
<20> Call free_all_bootmem() and add that released memory to
|
|||
|
totalram_pages.
|
|||
|
|
|||
|
<20> Count the number of reserved RAM pages.
|
|||
|
|
|||
|
<20> Print the system memory sizes (free/total), kernel code size,
|
|||
|
reserved memory size, kernel data size, kernel "init" size, and the
|
|||
|
highmem size.
|
|||
|
|
|||
|
<20> For CONFIG_SMP, call zap_low_mappings().
|
|||
|
|
|||
|
********** get_free_pages() can be used after mem_init(). **********
|
|||
|
|
|||
|
|
|||
|
5.1.17. kmem_cache_sizes_init
|
|||
|
|
|||
|
|
|||
|
(in linux/mm/slab.c)
|
|||
|
|
|||
|
Set up remaining internal and general caches. Called after the
|
|||
|
"get_free_page()" functions have been enabled and before smp_init().
|
|||
|
|
|||
|
********** kmalloc() can be used after kmem_cache_sizes_init().
|
|||
|
**********
|
|||
|
|
|||
|
|
|||
|
5.1.18. proc_root_init
|
|||
|
|
|||
|
|
|||
|
(in linux/fs/proc/root.c)
|
|||
|
|
|||
|
For CONFIG_PROC_FS configurations:
|
|||
|
|
|||
|
<20> call proc_misc_init()
|
|||
|
|
|||
|
<20> mkdir /proc/net
|
|||
|
|
|||
|
<20> for CONFIG_SYSVIPC, mkdir /proc/sysvipc
|
|||
|
|
|||
|
<20> for CONFIG_SYSCTL, mkdir /proc/sys
|
|||
|
|
|||
|
<20> mkdir /proc/fs
|
|||
|
|
|||
|
<20> mkdir /proc/driver
|
|||
|
|
|||
|
<20> call proc_tty_init()
|
|||
|
|
|||
|
<20> mkdir /proc/bus
|
|||
|
|
|||
|
|
|||
|
5.1.19. mempages = num_physpages;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
5.1.20. fork_init(mempages)
|
|||
|
|
|||
|
|
|||
|
(in linux/kernel/fork.c)
|
|||
|
|
|||
|
The default maximum number of threads is set to a safe value: the
|
|||
|
thread structures can take up at most half of memory.
|
|||
|
|
|||
|
|
|||
|
5.1.21. proc_caches_init()
|
|||
|
|
|||
|
|
|||
|
(in linux/kernel/fork.c)
|
|||
|
|
|||
|
Call kmem_cache_create() to create slab caches for signal_act (signal
|
|||
|
action), files_cache (files_struct), fs_cache (fs_struct),
|
|||
|
vm_area_struct, and mm_struct.
|
|||
|
5.1.22. vfs_caches_init(mempages)
|
|||
|
|
|||
|
|
|||
|
(in linux/fs/dcache.c)
|
|||
|
|
|||
|
Call kmem_cache_create() to create slab caches for buffer_head,
|
|||
|
names_cache, filp, and for CONFIG_QUOTA, dquot.
|
|||
|
|
|||
|
Call dcache_init() to create the dentry_cache and dentry_hashtable.
|
|||
|
|
|||
|
|
|||
|
5.1.23. buffer_init(mempages)
|
|||
|
|
|||
|
|
|||
|
(in linux/fs/buffer.c)
|
|||
|
|
|||
|
Allocate the buffer cache hash table and init the free list.
|
|||
|
Use get_free_pages() for the hash table to decrease TLB misses; use
|
|||
|
SLAB cache for buffer heads.
|
|||
|
Setup the hash chains, free lists, and LRU lists.
|
|||
|
|
|||
|
|
|||
|
5.1.24. page_cache_init(mempages)
|
|||
|
|
|||
|
|
|||
|
(in linux/mm/filemap.c)
|
|||
|
|
|||
|
Allocate and clear the page-cache hash table.
|
|||
|
|
|||
|
|
|||
|
5.1.25. kiobuf_setup()
|
|||
|
|
|||
|
|
|||
|
(in linux/fs/iobuf.c)
|
|||
|
|
|||
|
Call kmem_cache_create() to create the kernel iobuf cache.
|
|||
|
|
|||
|
|
|||
|
5.1.26. signals_init()
|
|||
|
|
|||
|
|
|||
|
(in linux/kernel/signal.c)
|
|||
|
|
|||
|
Call kmem_cache_create() to create the "sigqueue" SLAB cache.
|
|||
|
|
|||
|
|
|||
|
5.1.27. bdev_init()
|
|||
|
|
|||
|
|
|||
|
(in linux/fs/block_dev.c)
|
|||
|
|
|||
|
Initialize the bdev_hashtable list heads.
|
|||
|
|
|||
|
Call kmem_cache_create() to create the "bdev_cache" SLAB cache.
|
|||
|
|
|||
|
|
|||
|
5.1.28. inode_init(mempages)
|
|||
|
|
|||
|
|
|||
|
(in linux/fs/inode.c)
|
|||
|
|
|||
|
|
|||
|
<20> Allocate memory for the inode_hashtable.
|
|||
|
|
|||
|
<20> Intialize the inode_hashtable list heads.
|
|||
|
|
|||
|
<20> Call kmem_cache_create() to create the inode SLAB cache.
|
|||
|
|
|||
|
|
|||
|
5.1.29. ipc_init()
|
|||
|
|
|||
|
|
|||
|
(in linux/ipc/util.c)
|
|||
|
|
|||
|
For CONFIG_SYSVIPC configurations, call ipc_init().
|
|||
|
|
|||
|
The various System V IPC resources (semaphores, messages, and shared
|
|||
|
memory) are initialized.
|
|||
|
|
|||
|
|
|||
|
5.1.30. dquot_init_hash()
|
|||
|
|
|||
|
|
|||
|
(in linux/fs/dquot.c)
|
|||
|
|
|||
|
For CONFIG_QUOTA configurations, call dquot_init_hash().
|
|||
|
|
|||
|
|
|||
|
<20> Clear dquot_hash. TBD: Why? Is it in BSS? Yes.
|
|||
|
|
|||
|
<20> Clear dqstats. TBD: Why? Is it in BSS? Yes.
|
|||
|
|
|||
|
|
|||
|
5.1.31. check_bugs()
|
|||
|
|
|||
|
|
|||
|
(in linux/include/asm-i386/bugs.h)
|
|||
|
|
|||
|
|
|||
|
<20> identify_cpu()
|
|||
|
|
|||
|
<20> For non-CONFIG_SMP configurations, print_cpu_info()
|
|||
|
|
|||
|
<20> check_config()
|
|||
|
|
|||
|
<20> check_fpu()
|
|||
|
|
|||
|
<20> check_hlt()
|
|||
|
|
|||
|
<20> check_popad()
|
|||
|
|
|||
|
<20> Update system_utsname.machine{byte 1} with boot_cpu_data.x86
|
|||
|
|
|||
|
|
|||
|
5.1.32. Start other SMP processors (as applicable)
|
|||
|
|
|||
|
|
|||
|
smp_init() works in one of three ways, depending upon the kernel
|
|||
|
configuration.
|
|||
|
|
|||
|
For a uniprocessor (UP) system without an IO APIC (CONFIG_X86_IO_APIC
|
|||
|
is not defined), smp_init() is empty -- it has nothing to do.
|
|||
|
|
|||
|
For a UP system with (an) IO APIC for interrupt routing, it calls
|
|||
|
IO_APIC_init_uniprocessor().
|
|||
|
|
|||
|
For an SMP system, its main job is to call the architecture-specific
|
|||
|
function "smp_boot_cpus()", which does the following.
|
|||
|
|
|||
|
|
|||
|
<20> For CONFIG_MTRR kernels, calls mtrr_init_boot_cpu(), which must be
|
|||
|
done before the other processors are booted.
|
|||
|
<20> Stores and prints the BSP CPU information.
|
|||
|
|
|||
|
<20> Saves the BSP APIC ID and BSP logical CPU ID (latter is 0).
|
|||
|
|
|||
|
<20> If an MP BIOS interrupt routing table was not found, revert to
|
|||
|
using only one CPU and exit.
|
|||
|
|
|||
|
<20> Verify existence of a local APIC for the BSP.
|
|||
|
|
|||
|
<20> If the "maxcpus" boot option was used to limit the number of CPUs
|
|||
|
actually used to 1 (not SMP), then ignore the MP BIOS interrupt
|
|||
|
routing table.
|
|||
|
|
|||
|
<20> Switch the system from PIC mode to symmetric I/O interrupt mode.
|
|||
|
|
|||
|
<20> Setup the BSP's local APIC.
|
|||
|
|
|||
|
<20> Use the CPU present map to boot the APs serially. Wait for each AP
|
|||
|
to finish booting before starting the next one.
|
|||
|
|
|||
|
<20> If using (an) IO APIC {which is True unless the "noapic" boot
|
|||
|
option was used}, setup the IO APIC(s).
|
|||
|
|
|||
|
|
|||
|
5.1.33. Start init thread
|
|||
|
|
|||
|
|
|||
|
We count on the initial thread going OK.
|
|||
|
|
|||
|
Like idlers, init is an unlocked kernel thread, which will make
|
|||
|
syscalls (and thus be locked).
|
|||
|
|
|||
|
|
|||
|
|
|||
|
kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
{details below}
|
|||
|
|
|||
|
|
|||
|
5.1.34. unlock_kernel()
|
|||
|
|
|||
|
|
|||
|
Release the BKL.
|
|||
|
|
|||
|
|
|||
|
5.1.35. current->need_resched = 1;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
5.1.36. cpu_idle()
|
|||
|
|
|||
|
|
|||
|
This function remains as process number 0. Its purpose is to use up
|
|||
|
idle CPU cycles. If the kernel is configured for APM support or ACPI
|
|||
|
support, cpu_idle() invokes the supported power-saving features of
|
|||
|
these specifications. Otherwise it nominally executes a "hlt"
|
|||
|
instruction.
|
|||
|
|
|||
|
{end of start_kernel()}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
5.2. setup_arch
|
|||
|
|
|||
|
|
|||
|
(in "linux/arch/i386/kernel/setup.c")
|
|||
|
|
|||
|
|
|||
|
5.2.1. Copy and convert system parameter data
|
|||
|
|
|||
|
|
|||
|
Copy and convert parameter data passed from 16-bit real mode to the
|
|||
|
32-bit startup code.
|
|||
|
|
|||
|
|
|||
|
5.2.2. For RAMdisk-enabled configs (CONFIG_BLK_DEV_RAM)
|
|||
|
|
|||
|
|
|||
|
Initialize rd_image_start, rd_prompt, and rd_doload from the real-mode
|
|||
|
parameter data.
|
|||
|
|
|||
|
|
|||
|
5.2.3. setup_memory_region
|
|||
|
|
|||
|
|
|||
|
Use the BIOS-supplied memory map to setup memory regions.
|
|||
|
|
|||
|
|
|||
|
5.2.4. Set memory limits
|
|||
|
|
|||
|
|
|||
|
Set values for the start of kernel code, end of kernel code, end of
|
|||
|
kernel data, and "_end" (end of kernel code = the "brk" address).
|
|||
|
|
|||
|
Set values for code_resource start and end and data_resource start and
|
|||
|
end.
|
|||
|
|
|||
|
|
|||
|
5.2.5. parse_mem_cmdline
|
|||
|
|
|||
|
|
|||
|
Parse any "mem=" parameters on the kernel command line and remember
|
|||
|
them.
|
|||
|
|
|||
|
|
|||
|
5.2.6. Setup Page Frames
|
|||
|
|
|||
|
|
|||
|
Use the BIOS-supplied memory map to setup page frames.
|
|||
|
|
|||
|
Register available low RAM pages with the bootmem allocator.
|
|||
|
|
|||
|
Reserve physical page 0: "it's a special BIOS page on many boxes,
|
|||
|
enabling clean reboots, SMP operation, laptop functions."
|
|||
|
|
|||
|
|
|||
|
5.2.7. Handle SMP and IO APIC Configurations
|
|||
|
|
|||
|
|
|||
|
For CONFIG_SMP, reserve the page immediately above page 0 for stack
|
|||
|
and trampoline usage, then call smp_alloc_memory() to allocate low
|
|||
|
memory for AP processor(s) real mode trampoline code.
|
|||
|
|
|||
|
For CONFIG_X86_IO_APIC configurations, call find_smp_config() to find
|
|||
|
and reserve any boot-time SMP configuration information memory, such
|
|||
|
as MP (Multi Processor) table data from the BIOS.
|
|||
|
|
|||
|
|
|||
|
5.2.8. paging_init()
|
|||
|
|
|||
|
|
|||
|
paging_init() sets up the page tables - note that the first 8 MB are
|
|||
|
already mapped by head.S.
|
|||
|
|
|||
|
This routine also unmaps the page at virtual kernel address 0, so that
|
|||
|
we can trap those pesky NULL-reference errors in the kernel.
|
|||
|
|
|||
|
|
|||
|
5.2.9. Save the boot-time SMP configuration
|
|||
|
|
|||
|
|
|||
|
For CONFIG_X86_IO_APIC configurations, call get_smp_config() to read
|
|||
|
and save the MP table IO APIC interrupt routing configuration data.
|
|||
|
|
|||
|
For CONFIG_X86_LOCAL_APIC configurations, call init_apic_mappings().
|
|||
|
|
|||
|
|
|||
|
5.2.10. Reserve INITRD memory
|
|||
|
|
|||
|
|
|||
|
For CONFIG_BLK_DEV_INITRD configurations, if there is enough memory
|
|||
|
for the initial RamDisk, call reserve_bootmem() to reserve RAM for the
|
|||
|
initial RamDisk.
|
|||
|
|
|||
|
|
|||
|
5.2.11. Scan for option ROMs
|
|||
|
|
|||
|
|
|||
|
Call probe_roms() and reserve their memory space resource(s) if found
|
|||
|
and valid. This is done for the standard video BIOS ROM image, any
|
|||
|
option ROMs found, and for the system board extension ROM (space).
|
|||
|
|
|||
|
|
|||
|
5.2.12. Reserve system resources
|
|||
|
|
|||
|
|
|||
|
Call request_resource() to reserve video RAM memory.
|
|||
|
|
|||
|
Call request_resource() to reserve all standard PC I/O system board
|
|||
|
resources.
|
|||
|
|
|||
|
{end of setup_arch()}
|
|||
|
|
|||
|
|
|||
|
5.3. init thread
|
|||
|
|
|||
|
|
|||
|
The init thread begins at the init() function in "linux/init/main.c".
|
|||
|
This is always expected to be process number 1.
|
|||
|
|
|||
|
init() first locks the kernel and then calls do_basic_setup() to
|
|||
|
perform lots of bus and/or device initialization {more detail below}.
|
|||
|
After do_basic_setup(), most kernel initialization has been completed.
|
|||
|
init() then frees any memory that was specified as being for
|
|||
|
initialization only [marked with "__init", "__initdata",
|
|||
|
"__init_call", or "__initsetup"] and unlocks the kernel (BKL).
|
|||
|
|
|||
|
init() next opens /dev/console and duplicates that file descriptor two
|
|||
|
times to create stdin, stdout, and stderr files for init and all of
|
|||
|
its children.
|
|||
|
|
|||
|
Finally init() tries to execute the command specified on the kernel
|
|||
|
parameters command line if there was one, or an init program or script
|
|||
|
if it can find one in {/sbin/init, /etc/init, /bin/init}, and lastly
|
|||
|
/bin/sh. If init() cannot execute any of these, it panics ("No init
|
|||
|
found. Try passing init= option to kernel.")
|
|||
|
|
|||
|
|
|||
|
5.4. do_basic_setup {part of the init thread}
|
|||
|
|
|||
|
|
|||
|
The machine is now initialized. None of the devices have been touched
|
|||
|
yet, but the CPU subsystem is up and running, and memory and process
|
|||
|
management works.
|
|||
|
|
|||
|
|
|||
|
5.4.1. Be the reaper of orphaned children
|
|||
|
|
|||
|
|
|||
|
The init process handles all orphaned tasks.
|
|||
|
|
|||
|
|
|||
|
5.4.2. MTRRs
|
|||
|
|
|||
|
|
|||
|
// SMP init is completed before this.
|
|||
|
For CONFIG_MTRR, call mtrr_init() [in linux/arch/i386/kernel/mtrr.c].
|
|||
|
|
|||
|
|
|||
|
5.4.3. SYSCTLs
|
|||
|
|
|||
|
|
|||
|
For CONFIG_SYSCTL configurations, call sysctl_init() [in
|
|||
|
linux/kernel/sysctl.c].
|
|||
|
|
|||
|
|
|||
|
5.4.4. Init Many Devices
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Ok, at this point all CPU's should be initialized, so
|
|||
|
* we can start looking into devices..
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
5.4.5. PCI
|
|||
|
|
|||
|
|
|||
|
For CONFIG_PCI configurations, call pci_init() [in
|
|||
|
linux/drivers/pci/pci.c].
|
|||
|
|
|||
|
|
|||
|
5.4.6. Micro Channel
|
|||
|
|
|||
|
|
|||
|
For CONFIG_MCA configurations, call mca_init() [in
|
|||
|
linux/arch/i386/kernel/mca.c].
|
|||
|
|
|||
|
|
|||
|
5.4.7. ISA PnP
|
|||
|
|
|||
|
|
|||
|
For CONFIG_ISAPNP configurations, call isapnp_init() [in
|
|||
|
linux/drivers/pnp/isapnp.c].
|
|||
|
|
|||
|
5.4.8. Networking Init
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* Networking initialization needs a process context */
|
|||
|
sock_init();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
[in linux/net/socket.c]
|
|||
|
|
|||
|
|
|||
|
5.4.9. Initial RamDisk
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
|||
|
|
|||
|
real_root_dev = ROOT_DEV;
|
|||
|
real_root_mountflags = root_mountflags;
|
|||
|
if (initrd_start && mount_initrd)
|
|||
|
root_mountflags &= ~MS_RDONLY; // change to read/write
|
|||
|
else
|
|||
|
mount_initrd =0;
|
|||
|
|
|||
|
#endif /* CONFIG_BLK_DEV_INITRD */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
5.4.10. Start the kernel "context" thread (keventd)
|
|||
|
|
|||
|
|
|||
|
[in linux/kernel/context.c]
|
|||
|
|
|||
|
|
|||
|
5.4.11. Initcalls
|
|||
|
|
|||
|
|
|||
|
Call all functions marked as "__initcall":
|
|||
|
|
|||
|
|
|||
|
do_initcalls();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
[in linux/init/main.c]
|
|||
|
|
|||
|
This initializes many functions and some subsystems --- in no specific
|
|||
|
or guaranteed order unless fixed in their Makefiles --- if they were
|
|||
|
built into the kernel, such as:
|
|||
|
|
|||
|
|
|||
|
<20> APM: apm_init() {in linux/arch/i386/kernel/apm.c}
|
|||
|
|
|||
|
<20> cpuid: cpuid_init() {in linux/arch/i386/kernel/cpuid.c}
|
|||
|
|
|||
|
<20> DMI: dmi_scan_machine() {in linux/arch/i386/kernel/dmi_scan.c}
|
|||
|
|
|||
|
<20> microcode: microcode_init() {in linux/arch/i386/kernel/microcode.c}
|
|||
|
|
|||
|
<20> MSR: msr_init() {in linux/arch/i386/kernel/msr.c}
|
|||
|
|
|||
|
<20> partitions: partition_setup() {in linux/fs/partitions/check.s}
|
|||
|
|
|||
|
<20> file systems, pipes, buffer and cache management, various binary
|
|||
|
format loaders, NLS character sets: too numerous to list {in
|
|||
|
linux/fs/*}
|
|||
|
|
|||
|
<20> user cache (for limits): uid_cache_init() {in linux/kernel/user.c}
|
|||
|
|
|||
|
<20> kmem_cpu_cache: kmem_cpucache_init() {in linux/mm/slab.c}
|
|||
|
|
|||
|
<20> shmem: init_shmem_fs() {in linux/mm/shmem.c}
|
|||
|
|
|||
|
<20> kswapd: kswapd_init() {in linux/mm/vmscan.c}
|
|||
|
|
|||
|
<20> networking, TCP/IP, IPv6, sockets, 802.2, SNAP, LLC, X.25, AX.25,
|
|||
|
IPX, kHTTPd, ATM LAN emulation (LANE), IP chains/forwarding,
|
|||
|
NAT/masquerading, packet matching/filtering/logging, firewalling,
|
|||
|
DECnet, bridging, and other networking protocols too numerous to
|
|||
|
list {in linux/net/*}
|
|||
|
|
|||
|
<20> drivers, some of which are not exactly device drivers, but help out
|
|||
|
with bus/device enumeration and initialization, such as:
|
|||
|
|
|||
|
<20> ACPI: acpi_init() {in linux/drivers/acpi/*}
|
|||
|
|
|||
|
<20> PCI: pci_proc_init() {in linux/drivers/pci/*}
|
|||
|
|
|||
|
<20> PCMCIA controllers {in linux/drivers/pcmcia/*}
|
|||
|
|
|||
|
<20> and...
|
|||
|
|
|||
|
<20> atm drivers {in linux/drivers/atm/*}
|
|||
|
|
|||
|
<20> block drivers {in linux/drivers/block/*}
|
|||
|
|
|||
|
<20> CD-ROM drivers {in linux/drivers/cdrom/*}
|
|||
|
|
|||
|
<20> character drivers {in linux/drivers/char/*}
|
|||
|
|
|||
|
<20> I2O drivers {in linux/drivers/i2o/*}
|
|||
|
|
|||
|
<20> IDE drivers {in linux/drivers/ide/*}
|
|||
|
|
|||
|
<20> input drivers (keyboard/mouse/joystick) {in linux/drivers/input/*}
|
|||
|
|
|||
|
<20> ISDN drivers {in linux/drivers/isdn/*}
|
|||
|
|
|||
|
<20> md, LVM, and RAID drivers {in linux/drivers/md/*}
|
|||
|
|
|||
|
<20> radio drivers {in linux/drivers/media/radio/*}
|
|||
|
|
|||
|
<20> video drivers {in linux/drivers/media/video/*}
|
|||
|
|
|||
|
<20> MTD drivers {in linux/drivers/mtd/*}
|
|||
|
|
|||
|
<20> network drivers, including PLIP, PPP, dummy, Ethernet, bonding,
|
|||
|
Arcnet, hamradio, PCMCIA, Token Ring, and WAN
|
|||
|
|
|||
|
<20> SCSI logical and physical drivers {in linux/drivers/scsi/*}
|
|||
|
|
|||
|
<20> sound drivers {in linux/drivers/sound/*}
|
|||
|
|
|||
|
<20> telephony drivers {in linux/drivers/telephony/*}
|
|||
|
|
|||
|
<20> USB host controllers and device drivers {in linux/drivers/usb/*}
|
|||
|
|
|||
|
<20> video frame buffer drivers {in linux/drivers/video/*}
|
|||
|
|
|||
|
|
|||
|
5.4.12. Filesystems
|
|||
|
|
|||
|
|
|||
|
Call filesystem_setup():
|
|||
|
|
|||
|
<20> init_devfs_fs(); /* Header file may make this empty */
|
|||
|
|
|||
|
<20> For CONFIG_NFS_FS configurations, call init_nfs_fs().
|
|||
|
|
|||
|
<20> For CONFIG_DEVPTS_FS configurations, call init_devpts_fs().
|
|||
|
|
|||
|
[in linux/fs/filesystems.c]
|
|||
|
|
|||
|
|
|||
|
5.4.13. IRDA
|
|||
|
|
|||
|
|
|||
|
For CONFIG_IRDA configurations, call irda_device_init().
|
|||
|
/* Must be done after protocol initialization */
|
|||
|
[in linux/net/irda/irda_device.c]
|
|||
|
|
|||
|
|
|||
|
5.4.14. PCMCIA
|
|||
|
|
|||
|
|
|||
|
/* Do this last */
|
|||
|
For CONFIG_PCMCIA configurations, call init_pcmcia_ds().
|
|||
|
[in linux/drivers/pcmcia/ds.c]
|
|||
|
|
|||
|
|
|||
|
5.4.15. Mount the root filesystem
|
|||
|
|
|||
|
|
|||
|
|
|||
|
mount_root();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
[in linux/fs/super.c]
|
|||
|
|
|||
|
|
|||
|
5.4.16. Mount the dev (device) filesystem
|
|||
|
|
|||
|
|
|||
|
|
|||
|
mount_devfs_fs ();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
[in linux/fs/devfs/base.c]
|
|||
|
|
|||
|
|
|||
|
5.4.17. Switch to the Initial RamDisk
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
|||
|
|
|||
|
if (mount_initrd && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
|
|||
|
// Start the linuxrc thread.
|
|||
|
pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
|
|||
|
if (pid > 0)
|
|||
|
while (pid != wait(&i));
|
|||
|
if (MAJOR(real_root_dev) != RAMDISK_MAJOR
|
|||
|
|| MINOR(real_root_dev) != 0) {
|
|||
|
error = change_root(real_root_dev,"/initrd");
|
|||
|
if (error)
|
|||
|
printk(KERN_ERR "Change root to /initrd: "
|
|||
|
"error %d\n",error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif /* CONFIG_BLK_DEV_INITRD */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
See "linux/Documentation/initrd.txt" for more information on initial
|
|||
|
RAM disks.
|
|||
|
|
|||
|
{end of do_basic_setup()}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
6. Glossary
|
|||
|
|
|||
|
|
|||
|
AP: Application Processor, any x86 processor other than the Bootstrap
|
|||
|
Processor on IA-32 SMP systems
|
|||
|
|
|||
|
ACPI: Advanced Configuration and Power Interface
|
|||
|
|
|||
|
APIC: Advanced Programmable Interrupt Controller
|
|||
|
|
|||
|
APM: Advanced Power Management, a BIOS-managed power management
|
|||
|
specification for personal computers
|
|||
|
|
|||
|
BSP: Bootstrap Processor, the primary booting processor on IA-32 SMP
|
|||
|
systems
|
|||
|
|
|||
|
BSS: Block Started by Symbol: the uninitialized data segment
|
|||
|
|
|||
|
BKL: Big Kernel Lock, the Linux global kernel lock
|
|||
|
|
|||
|
CRn: Control Register n, i386-specific control registers
|
|||
|
|
|||
|
FPU: Floating Point Unit, a separate math coprocessor device
|
|||
|
|
|||
|
GB: gigabyte (1024 * 1024 * 1024 bytes)
|
|||
|
|
|||
|
GDT: Global Descriptor Table, an i386 memory management table
|
|||
|
|
|||
|
IA: Intel Architecture (also i386, x86)
|
|||
|
|
|||
|
IDT: Interrupt Descriptor Table, an i386-specific table that contains
|
|||
|
information used in handling interrupts
|
|||
|
|
|||
|
initrd: initial RAM disk (see "linux/Documentation/initrd.txt")
|
|||
|
|
|||
|
IPC: Inter-Process Communication
|
|||
|
|
|||
|
IPI: Inter-processor Interrupt, a method of signaling interrupts
|
|||
|
between multiple processors on an SMP system
|
|||
|
|
|||
|
IRDA: InfraRed Data Association
|
|||
|
|
|||
|
IRQ: Interrupt ReQuest
|
|||
|
|
|||
|
ISA: Industry Standard Architecture
|
|||
|
|
|||
|
KB: kilobyte (1024 bytes)
|
|||
|
|
|||
|
LDT: Local Descriptor Table, an i386-specific memory management table
|
|||
|
that is used to describe memory for each non-kernel process
|
|||
|
|
|||
|
MB: megabyte (1024 * 1024 bytes)
|
|||
|
|
|||
|
MCA: Micro Channel Architecture, used in IBM PS/2 computers
|
|||
|
|
|||
|
MP: Multi-processor
|
|||
|
|
|||
|
MSW: Machine Status Word
|
|||
|
|
|||
|
MTRR: Memory Type Range Registers
|
|||
|
|
|||
|
PAE: Physical Address Extension: extends the address space to 64 GB
|
|||
|
instead of 4 GB
|
|||
|
|
|||
|
PCI: Peripheral Component Interconnect, an industry standard for
|
|||
|
connecting devices on a local bus in a computer system
|
|||
|
PCMCIA: Personal Computer Memory Card International Association;
|
|||
|
defines standards for PCMCIA cards and CardBus PC Cards
|
|||
|
|
|||
|
PIC: Programmable Interrupt Controller
|
|||
|
|
|||
|
PNP: Plug aNd Play
|
|||
|
|
|||
|
PSE: Page Size Extension: allows 4 MB pages
|
|||
|
|
|||
|
SMP: Symmetric Multi Processor/Processing
|
|||
|
|
|||
|
TLB: Translation Lookaside Buffer, i386-specific processor cache of
|
|||
|
recent page directory and page table entries
|
|||
|
|
|||
|
TSS: Task State Segment, an i386-specific task data structure
|
|||
|
|
|||
|
UP: Uniprocessor (single CPU) system.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
7. References
|
|||
|
|
|||
|
|
|||
|
|
|||
|
1. Tigran Aivazian, "Linux Kernel Internals" (URL:
|
|||
|
http://www.moses.uklinux.net/patches/lki.html)
|
|||
|
|
|||
|
2. Werner Almesberger, x86 Booting. (URL:
|
|||
|
ftp://icaftp.epfl.ch/pub/people/almesber/booting/)
|
|||
|
|
|||
|
3. Werner Almesberger, "LILO Generic boot loader for Linux: Technical
|
|||
|
overview." December 4, 1998. Included in LILO distribution.
|
|||
|
|
|||
|
4. Werner Almesberger and Hans Lermen, Using the initial RAM disk
|
|||
|
(initrd). (file: linux/Documentation/initrd.txt)
|
|||
|
|
|||
|
5. H. Peter Anvin, "The Linux/I386 Boot Protocol (file:
|
|||
|
linux/Documentation/i386/boot.txt)
|
|||
|
|
|||
|
6. Michael Beck et al, "Linux Kernel Internals," second edition.
|
|||
|
Addison-Wesley, 1998.
|
|||
|
|
|||
|
7. Ralf Brown's Interrupt List, URL: http://www.ctyme.com/intr/int.htm
|
|||
|
{browsable}
|
|||
|
|
|||
|
8. Ralf Brown's Interrupt List, URL:
|
|||
|
http://www.delorie.com/djgpp/doc/rbinter/ix/ {browsable}
|
|||
|
|
|||
|
9. Ralf Brown's Interrupt List, URL:
|
|||
|
http://www.cs.cmu.edu/ ralf/files.html {zipped, not browsable}
|
|||
|
|
|||
|
10.
|
|||
|
E820 memory sizing method: URL:
|
|||
|
http://www.teleport.com/ acpi/acpihtml/topic245.htm
|
|||
|
|
|||
|
11.
|
|||
|
IBM Personal Computer AT Technical Reference. 1985.
|
|||
|
|
|||
|
12.
|
|||
|
IBM Personal System/2(r) and Personal Computer BIOS Interface
|
|||
|
Technical Reference, second edition. 1988.
|
|||
|
|
|||
|
13.
|
|||
|
Hans Lermen and Martin Mares, "Summary of empty_zero_page layout."
|
|||
|
(file: linux/Documentation/i386/zero-page.txt)
|
|||
|
|
|||
|
14.
|
|||
|
linux/Documentation directory files
|
|||
|
|
|||
|
15.
|
|||
|
Martin Mares, "Video Mode Selection Support." (file:
|
|||
|
linux/Documentation/svga.txt)
|
|||
|
|
|||
|
16.
|
|||
|
Scott Maxwell, "Linux Core Kernel Commentary." Coriolis Press,
|
|||
|
1999.
|
|||
|
|
|||
|
17.
|
|||
|
Mindshare, Inc., Tom Shanley, "Pentium(r) Pro and Pentium(r) II
|
|||
|
System Architecture," second edition. Addison-Wesley, 1998.
|
|||
|
|
|||
|
18.
|
|||
|
Allesandro Rubini, "Linux Device Drivers." O'Reilly and
|
|||
|
Associates, 1998.
|
|||
|
|
|||
|
|
|||
|
19.
|
|||
|
URL: ftp://linux01.gwdg.de/pub/cLIeNUX/interim/Janet_Reno.tgz
|
|||
|
|
|||
|
20.
|
|||
|
URL: http://www.eecs.wsu.edu/~cs640/ (was dead at last check)
|
|||
|
|
|||
|
21.
|
|||
|
URL: http://www.linuxbios.org + "Papers"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Table of Contents
|
|||
|
|
|||
|
|
|||
|
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 5
|
|||
|
1.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . 5
|
|||
|
1.2. This document . . . . . . . . . . . . . . . . . . . . . . . . 5
|
|||
|
1.3. Contributions . . . . . . . . . . . . . . . . . . . . . . . . 6
|
|||
|
1.4. Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . 6
|
|||
|
1.5. License . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
|
|||
|
2. Linux init ("ASCII art") . . . . . . . . . . . . . . . . . . . 7
|
|||
|
3. Linux early setup . . . . . . . . . . . . . . . . . . . . . . . 10
|
|||
|
3.1. IA-32 Kernel Setup . . . . . . . . . . . . . . . . . . . . . 10
|
|||
|
3.1.1. start_of_setup: . . . . . . . . . . . . . . . . . . . . . . 11
|
|||
|
3.1.1.1. Read second hard drive DASD type . . . . . . . . . . . . 11
|
|||
|
3.1.1.2. Check that LILO loaded us right . . . . . . . . . . . . . 11
|
|||
|
3.1.1.3. Check old loader trying to load a big kernel . . . . . . 12
|
|||
|
3.1.1.4. Determine system memory size . . . . . . . . . . . . . . 12
|
|||
|
3.1.1.5. Video adapter modes . . . . . . . . . . . . . . . . . . . 12
|
|||
|
3.1.1.6. Get Hard Disk parameters . . . . . . . . . . . . . . . . 13
|
|||
|
3.1.1.7. Get Micro Channel bus information . . . . . . . . . . . . 13
|
|||
|
3.1.1.8. Check for mouse . . . . . . . . . . . . . . . . . . . . . 13
|
|||
|
3.1.1.9. Check for APM BIOS support . . . . . . . . . . . . . . . 13
|
|||
|
3.1.1.10. Prepare to move to protected mode . . . . . . . . . . . 14
|
|||
|
3.1.1.11. Enable address line A20 . . . . . . . . . . . . . . . . 14
|
|||
|
3.1.1.12. Make sure any possible coprocessor is properly reset
|
|||
|
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
|
|||
|
3.1.1.13. Mask all interrupts . . . . . . . . . . . . . . . . . . 15
|
|||
|
3.1.1.14. Move to Protected Mode . . . . . . . . . . . . . . . . . 15
|
|||
|
3.1.1.15. Jump to startup_32 code . . . . . . . . . . . . . . . . 15
|
|||
|
3.2. Video Setup . . . . . . . . . . . . . . . . . . . . . . . . . 15
|
|||
|
3.2.1. video: . . . . . . . . . . . . . . . . . . . . . . . . . . 16
|
|||
|
3.2.1.1. basic_detect: . . . . . . . . . . . . . . . . . . . . . . 16
|
|||
|
3.2.1.2. mode_params: . . . . . . . . . . . . . . . . . . . . . . 17
|
|||
|
3.2.1.3. mopar_gr: . . . . . . . . . . . . . . . . . . . . . . . . 17
|
|||
|
3.2.1.4. mode_menu: . . . . . . . . . . . . . . . . . . . . . . . 17
|
|||
|
3.2.1.5. mode_set: . . . . . . . . . . . . . . . . . . . . . . . . 17
|
|||
|
3.2.1.6. store_screen: . . . . . . . . . . . . . . . . . . . . . . 18
|
|||
|
3.2.1.7. restore_screen: . . . . . . . . . . . . . . . . . . . . . 18
|
|||
|
3.2.1.8. mode_table: . . . . . . . . . . . . . . . . . . . . . . . 19
|
|||
|
3.2.1.9. mode_scan: . . . . . . . . . . . . . . . . . . . . . . . 19
|
|||
|
3.2.1.10. svga_modes: . . . . . . . . . . . . . . . . . . . . . . 19
|
|||
|
4. Linux architecture-specific initialization . . . . . . . . . . 21
|
|||
|
4.1. startup_32: . . . . . . . . . . . . . . . . . . . . . . . . . 21
|
|||
|
4.2. Set segment registers to known values . . . . . . . . . . . . 21
|
|||
|
4.3. SMP BSP (Bootstrap Processor) check . . . . . . . . . . . . . 21
|
|||
|
4.4. Initialize page tables . . . . . . . . . . . . . . . . . . . 21
|
|||
|
4.5. Enable paging . . . . . . . . . . . . . . . . . . . . . . . . 21
|
|||
|
4.6. Clear BSS . . . . . . . . . . . . . . . . . . . . . . . . . . 22
|
|||
|
4.7. 32-bit setup . . . . . . . . . . . . . . . . . . . . . . . . 22
|
|||
|
4.8. Copy boot parameters and command line out of the way . . . . 22
|
|||
|
4.9. checkCPUtype . . . . . . . . . . . . . . . . . . . . . . . . 22
|
|||
|
4.10. Count this processor . . . . . . . . . . . . . . . . . . . . 22
|
|||
|
4.11. Load descriptor table pointer registers . . . . . . . . . . 22
|
|||
|
4.12. Start other processors . . . . . . . . . . . . . . . . . . . 23
|
|||
|
5. Linux architecture-independent initialization . . . . . . . . . 24
|
|||
|
5.1. start_kernel: . . . . . . . . . . . . . . . . . . . . . . . . 24
|
|||
|
5.1.1. More architecture-specific init . . . . . . . . . . . . . . 24
|
|||
|
5.1.2. Continue architecture-independent init . . . . . . . . . . 24
|
|||
|
5.1.3. Parsing command line options . . . . . . . . . . . . . . . 24
|
|||
|
5.1.4. trap_init . . . . . . . . . . . . . . . . . . . . . . . . . 25
|
|||
|
5.1.5. init_IRQ . . . . . . . . . . . . . . . . . . . . . . . . . 25
|
|||
|
5.1.6. sched_init . . . . . . . . . . . . . . . . . . . . . . . . 26
|
|||
|
5.1.7. time_init . . . . . . . . . . . . . . . . . . . . . . . . . 26
|
|||
|
5.1.8. softirq_init . . . . . . . . . . . . . . . . . . . . . . . 26
|
|||
|
5.1.9. console_init . . . . . . . . . . . . . . . . . . . . . . . 26
|
|||
|
5.1.10. init_modules . . . . . . . . . . . . . . . . . . . . . . . 26
|
|||
|
5.1.11. Profiling setup . . . . . . . . . . . . . . . . . . . . . 27
|
|||
|
5.1.12. kmem_cache_init . . . . . . . . . . . . . . . . . . . . . 27
|
|||
|
5.1.13. sti . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
|
|||
|
5.1.14. calibrate_delay . . . . . . . . . . . . . . . . . . . . . 27
|
|||
|
5.1.15. INITRD setup . . . . . . . . . . . . . . . . . . . . . . . 27
|
|||
|
5.1.16. mem_init . . . . . . . . . . . . . . . . . . . . . . . . . 27
|
|||
|
5.1.17. kmem_cache_sizes_init . . . . . . . . . . . . . . . . . . 28
|
|||
|
5.1.18. proc_root_init . . . . . . . . . . . . . . . . . . . . . . 28
|
|||
|
5.1.19. mempages = num_physpages; . . . . . . . . . . . . . . . . 28
|
|||
|
5.1.20. fork_init(mempages) . . . . . . . . . . . . . . . . . . . 28
|
|||
|
5.1.21. proc_caches_init() . . . . . . . . . . . . . . . . . . . . 28
|
|||
|
5.1.22. vfs_caches_init(mempages) . . . . . . . . . . . . . . . . 29
|
|||
|
5.1.23. buffer_init(mempages) . . . . . . . . . . . . . . . . . . 29
|
|||
|
5.1.24. page_cache_init(mempages) . . . . . . . . . . . . . . . . 29
|
|||
|
5.1.25. kiobuf_setup() . . . . . . . . . . . . . . . . . . . . . . 29
|
|||
|
5.1.26. signals_init() . . . . . . . . . . . . . . . . . . . . . . 29
|
|||
|
5.1.27. bdev_init() . . . . . . . . . . . . . . . . . . . . . . . 29
|
|||
|
5.1.28. inode_init(mempages) . . . . . . . . . . . . . . . . . . . 29
|
|||
|
5.1.29. ipc_init() . . . . . . . . . . . . . . . . . . . . . . . . 30
|
|||
|
5.1.30. dquot_init_hash() . . . . . . . . . . . . . . . . . . . . 30
|
|||
|
5.1.31. check_bugs() . . . . . . . . . . . . . . . . . . . . . . . 30
|
|||
|
5.1.32. Start other SMP processors (as applicable) . . . . . . . . 30
|
|||
|
5.1.33. Start init thread . . . . . . . . . . . . . . . . . . . . 31
|
|||
|
5.1.34. unlock_kernel() . . . . . . . . . . . . . . . . . . . . . 31
|
|||
|
5.1.35. current->need_resched = 1; . . . . . . . . . . . . . . . . 31
|
|||
|
5.1.36. cpu_idle() . . . . . . . . . . . . . . . . . . . . . . . . 31
|
|||
|
5.2. setup_arch . . . . . . . . . . . . . . . . . . . . . . . . . 32
|
|||
|
5.2.1. Copy and convert system parameter data . . . . . . . . . . 32
|
|||
|
5.2.2. For RAMdisk-enabled configs (CONFIG_BLK_DEV_RAM) . . . . . 32
|
|||
|
5.2.3. setup_memory_region . . . . . . . . . . . . . . . . . . . . 32
|
|||
|
5.2.4. Set memory limits . . . . . . . . . . . . . . . . . . . . . 32
|
|||
|
5.2.5. parse_mem_cmdline . . . . . . . . . . . . . . . . . . . . . 32
|
|||
|
5.2.6. Setup Page Frames . . . . . . . . . . . . . . . . . . . . . 32
|
|||
|
5.2.7. Handle SMP and IO APIC Configurations . . . . . . . . . . . 32
|
|||
|
5.2.8. paging_init() . . . . . . . . . . . . . . . . . . . . . . . 33
|
|||
|
5.2.9. Save the boot-time SMP configuration . . . . . . . . . . . 33
|
|||
|
5.2.10. Reserve INITRD memory . . . . . . . . . . . . . . . . . . 33
|
|||
|
5.2.11. Scan for option ROMs . . . . . . . . . . . . . . . . . . . 33
|
|||
|
5.2.12. Reserve system resources . . . . . . . . . . . . . . . . . 33
|
|||
|
5.3. init thread . . . . . . . . . . . . . . . . . . . . . . . . . 33
|
|||
|
5.4. do_basic_setup {part of the init thread} . . . . . . . . . . 34
|
|||
|
5.4.1. Be the reaper of orphaned children . . . . . . . . . . . . 34
|
|||
|
5.4.2. MTRRs . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
|
|||
|
5.4.3. SYSCTLs . . . . . . . . . . . . . . . . . . . . . . . . . . 34
|
|||
|
5.4.4. Init Many Devices . . . . . . . . . . . . . . . . . . . . . 34
|
|||
|
5.4.5. PCI . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
|
|||
|
5.4.6. Micro Channel . . . . . . . . . . . . . . . . . . . . . . . 34
|
|||
|
5.4.7. ISA PnP . . . . . . . . . . . . . . . . . . . . . . . . . . 34
|
|||
|
5.4.8. Networking Init . . . . . . . . . . . . . . . . . . . . . . 35
|
|||
|
5.4.9. Initial RamDisk . . . . . . . . . . . . . . . . . . . . . . 35
|
|||
|
5.4.10. Start the kernel "context" thread (keventd) . . . . . . . 35
|
|||
|
5.4.11. Initcalls . . . . . . . . . . . . . . . . . . . . . . . . 35
|
|||
|
5.4.12. Filesystems . . . . . . . . . . . . . . . . . . . . . . . 37
|
|||
|
5.4.13. IRDA . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
|
|||
|
5.4.14. PCMCIA . . . . . . . . . . . . . . . . . . . . . . . . . . 37
|
|||
|
5.4.15. Mount the root filesystem . . . . . . . . . . . . . . . . 37
|
|||
|
5.4.16. Mount the dev (device) filesystem . . . . . . . . . . . . 37
|
|||
|
5.4.17. Switch to the Initial RamDisk . . . . . . . . . . . . . . 37
|
|||
|
6. Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
|
|||
|
7. References . . . . . . . . . . . . . . . . . . . . . . . . . . 41
|
|||
|
|
|||
|
|
|||
|
|