The main code of the Linux Startup entry is the kernel_entry function in the arch/MIPS/kernel/head. s file, which appears in Assembly form.
I mainly did the following:
1. Clear BSS segments 0
2. assign values to global variables for parameters passed from boot
3. Clear context register
4. Create a $ GP register based on init_thread_union and set
$ SP register, stack pointer (ptr_la $28, init_thread_union)
5. Make the above preparations and jump
Start_kernel () in/ARCH/MIPS/kernel/Main. c initializes Code related to the hardware platform.
The data structure is mainly involved in arch/MIPS/kernel/init_task.c
Union thread_union init_thread_union
_ Init_task_data
_ Attribute _ (_ aligned _ (thread_size) =
{Init_thread_info (init_task )};
Thread_size is 8 K here, __attribute _ (_ aligned _ (thread_size) indicates that the data structure is 8 K aligned.
Struct task_struct
Init_task = init_task (init_task );
Union thread_union {
Struct thread_info;
Unsigned long stack [thread_size/sizeof (long)];
};
Use a Linux Design and Implementation diagram to show the relationship between thread_info, stack, and task_struct.
The job in head. s of MIPs is
This is the legendary 0 process.
1. process 0 is the ancestor of all other processes, also known as idle process or Swapper process.
2. process 0 is created by the kernel itself from scratch during system initialization. (The process is concentrated in the start_kernel function)
3. Most of the data members of process 0 are statically defined, that is, they are initialized by predefined macros such as init_task and init_mm.
The descriptor init_task of process 0 is defined in arch/ARM/kernel/init_task.c and initialized by the init_task macro. Struct such as init_mm are defined in include/Linux/init_task.h and are the initial values of init_task members. They are initialized by the corresponding initialization macros such as init_mm.
The following is a detailed analysis of the online prawns
After the system starts power-on, the default program entry of the MIPs processor is 0xbfc00000. The address is in the address area of kseg1 without caching, and the corresponding physical address is 0x1fc00000, that is, the CPU starts to get the first command from 0x1fc00000. This address has been determined as the flash location on the hardware. bootloader copies the Linux kernel image to a free address in Ram, there is usually a memory movement operation. The destination address is specified in arch/MIPS/makefile:
Load-$ (config_mips_pb1550) + = 0xffffffff80100000,
In the end, the bootloader will move the kernel to the physical address 0x00100000.
The load address specified in makefile above will be written to arch/MIPS/kernel/vmlinux. LDS by the compilation system:
Output_arch (MIPs)
Entry (kernel_entry)
Jiffies = jiffies_64;
Sections
{
. = 0xffffffff80100000;
/* Read-only */
_ Text =.;/* Text and read-only data */
. Text :{
* (. Text)
...
This file will eventually be passed to GCC in the form of the parameter-xlinker -- script-xlinker vmlinux. LDS, and finally to the linker LD to control its behavior.
LD links the address of the. text section to 0xffffffff80100000.
The entry point of the kernel ELF file, that is, the address that the bootloader directly jumps to after moving the kernel, which is written by the LD into the elf header, it tries to set the entry point in sequence using the following method, and stops when the entry is successful:
A. command line option-e entry
B. Entry (Symbol) in the script)
C. If the start symbol is defined, use the start symbol (Symbol)
D. If the. text section exists, use the address of the first byte.
E. Address 0
Note that in the above LD script, the entry point of the kernel is set to kernel_entry using the entry macro. Therefore, the First Command executed after the kernel obtains control is at kernel_entry.
**************************************** *****
The first phase of Linux kernel startup starts from the/ARCH/MIPS/kernel/head. s file.
The kernel entry function kernel_entry () is defined in the/ARCH/MIPS/kernel/head. s file.
The kernel_entry () function is an architecture-related assembly language. It first initializes the kernel stack segment to prepare the first process in the creation system,
Then, use a loop to clear the uninitialized data segment (BSS segment, between _ edata and _ end) of the kernel image,
Finally, jump to start_kernel () in/init/Main. C to initialize the Code related to the hardware platform.
**************************************** *****
Nested (kernel_entry, 16, SP) # kernelentry point
Declare the kernel_entry function. The stack of the function is 16 bytes. The return address is saved in the $ SP register.
-----------------------------
Declaration function entry
# Define nested (symbol, framesize, RPC )\
. Globl symbol ;\
. Align 2 ;\
. Type symbol, @ function ;\
. Ent symbol, 0 ;\
Symbol:. Frame sp, framesize, RPC
The Assembly pseudo-instruction frame is used to declare the STACK layout.
It has three parameters:
1) The first parameter framereg: Declares the register used to access the local stack, which is generally $ sp.
2) The second parameter framesize indicates the size of the allocated stack of the function, which must conform to $ SP + framesize = the original $ sp.
3) The third parameter, returnreg, is used to save the return address.
----------------------------
Kernel_entry_setup # cpuspecific setup
----------------------------
This macro is empty, defined in the include/ASM-MIPS/Mach-generic/kernel-entry-init.h file.
Some MIPS CPUs require additional settings for sending control
Memory, which is related to a specific platform. Generally, it is a null macro. Some multi-core MIPs are
Some core portals point to kernel_entry together, and then branch in the macro,
Boot core continues, while others do not stop judgment until the boot core wakes up.
----------------------------
Setup_c0_status_pri
Set cp0_status register
----------------------------
. Macro setup_c0_status_pri
# Ifdef config_64bit
Setup_c0_status st0_kx 0
# Else
Setup_c0_status 0 0
# Endif
. Endm
----------------------------
Arc64_twiddle_pc
The operation is null unless config_arc64 is used.
-----------------------------
# Ifdef config_mips_mt_smtc
Mtc0 zero, cp0_tccontext _ bss_start
Mfc0 T0, cp0_status
Ori T0, T0, 0xff1f
Xori T0, T0, 0x001e
Mtc0 T0, cp0_status
# Endif/* config_mips_mt_smtc */
Macro-defined config_mips_mt_smtc is defined when multi-core smtc Linux is used. Generally, this parameter is not considered.
MIPs has developed the ultimate version of SMP Linux, called smtc (thread context Symmetric Multi-processing) Linux.
Smtc Linux can understand the concept of lightweight TC and reduce some overhead related to SMP Linux.
----------------------------
Ptr_la t0 ,__ bss_start # Clear. BSS
Long_s zero, (t0)
Ptr_la T1, _ bss_stop-longsize
1:
Ptr_addiu T0, longsize
Long_s zero, (t0)
BNE T0, T1, 1B
Clear the BSS segment and clear 0.
Variables _ bss_start and _ bss_stop are defined in the connection file ARCH/MIPS/kernel/vmlinux. LDS.
--------------------------------
Long_s A0, fw_arg0 # firmware arguments
Long_s A1, fw_arg1
Long_s A2, fw_arg2
Long_s A3, fw_arg3
The boot parameters passed by bootloader to the kernel are saved in the fw_arg0, fw_arg1, fw_arg2, and fw_arg3 variables.
The variable fw_arg0 is the number of kernel parameters, and the rest are string pointers in *** = XXXX format.
----------------------------------
Mtc0 zero, cp0_context # clear context register
Clear context register of cp0, which is used to save the starting address of the page table.
----------------------------------
Ptr_la $28, init_thread_union
Initialize the $ GP register. The Register address points to a union,
Thread_size. The minimum value is a thread_info structure.
---------------------------------
Ptr_li sp, _ thread_size-32
Ptr_addu sp, $28
Set the $ SP register and stack pointer. $ Sp = (init_thread_union address) + _ thread_size-32
$ SP points to the end address of the union structure-32 byte address.
-----------------------------------
Set_saved_sp sp, T0, T1
Save the stack address $ SP of the CPU core to the array of kernelsp [nr_cpus.
---------------------------------
If the config_smp macro is defined, that is, multiple CPU cores.
. Macro set_saved_sp stackp temptemptemp2
# Ifdef config_mips_mt_smtc
Mfc0 \ Temp, cp0_tcbind
# Else
Mfc0 \ Temp, cp0_context
# Endif
Long_srl \ Temp, ptebase_shift
Long_s \ stackp, kernelsp (\ Temp)
. Endm
If the config_smp macro is not defined, a single CPU core is used.
. Macro set_saved_sp stackptemp temp2
Long_s \ stackp, kernelsp
. Endm
The definition of the variable kernelsp is in the arch/MIPS/kernel/setup. c file.
Unsigned long kernelsp [nr_cpus];
Save the stack address $ SP of the CPU core to the array of kernelsp [nr_cpus.
---------------------------------
Ptr_subu sp, 4 * szreg # init Stack pointer
---------------------------------
J start_kernel
End (kernel_entry)
Finally, jump to start_kernel () in/ARCH/MIPS/kernel/Main. C to initialize the Code related to the hardware platform.
----------------------------------
**************************************** **
The init_thread_union variable is defined in the arch/MIPS/kernel/init_task.c file.
Union thread_union init_thread_union
_ Attribute _ (_ Section _ (". Data. init_task "),
_ Aligned _ (thread_size) =
{Init_thread_info (init_task )};
**************************************** **
Problem:
1) How is the init_thread_union struct pointer initialized?
**************************************** **