<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.jackslab.org/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-cn">
		<id>http://wiki.jackslab.org/index.php?action=history&amp;feed=atom&amp;title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B</id>
		<title>MIPS Linux 最初启动流程 - 版本历史</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.jackslab.org/index.php?action=history&amp;feed=atom&amp;title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B"/>
		<link rel="alternate" type="text/html" href="http://wiki.jackslab.org/index.php?title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B&amp;action=history"/>
		<updated>2026-09-11T07:22:55Z</updated>
		<subtitle>本wiki的该页面的版本历史</subtitle>
		<generator>MediaWiki 1.19.2</generator>

	<entry>
		<id>http://wiki.jackslab.org/index.php?title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B&amp;diff=193&amp;oldid=prev</id>
		<title>2013年1月17日 (四) 10:15 Comcat</title>
		<link rel="alternate" type="text/html" href="http://wiki.jackslab.org/index.php?title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B&amp;diff=193&amp;oldid=prev"/>
				<updated>2013-01-17T10:15:02Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr valign='top'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←上一版本&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;2013年1月17日 (四) 10:15的版本&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第1行：&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第1行：&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;br&amp;gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;1. bootloader 将ELF 格式的Kernel 加载到某个空闲地址处，然后一般有个内存移动操作，目的地址在 arch/mips/Makefile 内指定：&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;1. bootloader 将ELF 格式的Kernel 加载到某个空闲地址处，然后一般有个内存移动操作，目的地址在 arch/mips/Makefile 内指定：&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Comcat</name></author>	</entry>

	<entry>
		<id>http://wiki.jackslab.org/index.php?title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B&amp;diff=192&amp;oldid=prev</id>
		<title>2013年1月17日 (四) 10:13 Comcat</title>
		<link rel="alternate" type="text/html" href="http://wiki.jackslab.org/index.php?title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B&amp;diff=192&amp;oldid=prev"/>
				<updated>2013-01-17T10:13:03Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class='diff diff-contentalign-left'&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
				&lt;col class='diff-marker' /&gt;
				&lt;col class='diff-content' /&gt;
			&lt;tr valign='top'&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;←上一版本&lt;/td&gt;
			&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;2013年1月17日 (四) 10:13的版本&lt;/td&gt;
			&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第1行：&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;第1行：&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;1. bootloader 将ELF 格式的Kernel 加载到某个空闲地址处，然后一般有个内存移动操作，目的地址在 arch/mips/Makefile 内指定： load-$(CONFIG_MIPS_PB1550) += &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;0xFFFFFFFF80100000，则最终bootloader定会将内核移到物理地址 &lt;/del&gt;0x00100000处&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;1. bootloader 将ELF 格式的Kernel 加载到某个空闲地址处，然后一般有个内存移动操作，目的地址在 arch/mips/Makefile 内指定：&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;&amp;#160; &lt;/ins&gt;load-$(CONFIG_MIPS_PB1550) += &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;0xFFFFFFFF80100000&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;&amp;#160;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;则最终bootloader定会将内核移到物理地址 &lt;/ins&gt;0x00100000处&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Comcat</name></author>	</entry>

	<entry>
		<id>http://wiki.jackslab.org/index.php?title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B&amp;diff=191&amp;oldid=prev</id>
		<title>Comcat：以“1. bootloader 将ELF 格式的Kernel 加载到某个空闲地址处，然后一般有个内存移动操作，目的地址在 arch/mips/Makefile 内指定： load-$(C...”为内容创建页面</title>
		<link rel="alternate" type="text/html" href="http://wiki.jackslab.org/index.php?title=MIPS_Linux_%E6%9C%80%E5%88%9D%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B&amp;diff=191&amp;oldid=prev"/>
				<updated>2013-01-17T10:12:18Z</updated>
		
		<summary type="html">&lt;p&gt;以“1. bootloader 将ELF 格式的Kernel 加载到某个空闲地址处，然后一般有个内存移动操作，目的地址在 arch/mips/Makefile 内指定： load-$(C...”为内容创建页面&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;1. bootloader 将ELF 格式的Kernel 加载到某个空闲地址处，然后一般有个内存移动操作，目的地址在 arch/mips/Makefile 内指定： load-$(CONFIG_MIPS_PB1550) += 0xFFFFFFFF80100000，则最终bootloader定会将内核移到物理地址 0x00100000处&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. 上面Makefile 里指定的的 load 地址，最后会被编译系统写入到 arch/mips/kernel/vmlinux.lds 中：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
OUTPUT_ARCH(mips)&lt;br /&gt;
ENTRY(kernel_entry)&lt;br /&gt;
jiffies = jiffies_64;&lt;br /&gt;
SECTIONS&lt;br /&gt;
{&lt;br /&gt;
. = 0xFFFFFFFF80100000;&lt;br /&gt;
/* read-only */&lt;br /&gt;
_text = .; /* Text and read-only data */&lt;br /&gt;
.text : {&lt;br /&gt;
    *(.text)&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
这个文件最终会以参数 -Xlinker --script -Xlinker vmlinux.lds 的形式传给 gcc，并最终传给链接器 ld 来控制其行为。ld 会将 .text 节的地址链接到 0xFFFFFFFF80100000 处。&lt;br /&gt;
&lt;br /&gt;
关于内核 ELF 文件的入口地址(Entry point)，即 bootloader 移动完内核后，直接跳转到的地址，由ld 写入 ELF的头中，其会依次用下面的方法尝试设置入口点，当遇到成功时则停止：&lt;br /&gt;
&lt;br /&gt;
a. 命令行选项 -e entry&lt;br /&gt;
&lt;br /&gt;
b. 脚本中的 ENTRY(symbol)&lt;br /&gt;
&lt;br /&gt;
c. 如果有定义 start 符号，则使用start符号（symbol）&lt;br /&gt;
&lt;br /&gt;
d. 如果存在 .text 节，则使用第一个字节的地址。&lt;br /&gt;
&lt;br /&gt;
e. 地址0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
注意到上面的 ld script 中，用 ENTRY 宏设置了内核的 entry point 是 kernel_entry，因此内核取得控制权后执行的第一条指令是在 kernel_entry 处。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. 这个 kernel_entry 定义于 arch/mips/kernel/head.S 中：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
NESTED(kernel_entry, 16, sp)         # kernel entry point&lt;br /&gt;
&lt;br /&gt;
    kernel_entry_setup                          # cpu specific setup，某些MIPS CPU需要额外的设置一些控制寄&lt;br /&gt;
                                                           存器，和具体的平台相关，一般为空宏；某些多核MIPS，启动时所&lt;br /&gt;
                                                           有的core的入口一起指向kernel_entry，然后在该宏里分叉，boot&lt;br /&gt;
                                                           core 继续往下，其它的则不停的判断循环，直到boot core 唤醒之&lt;br /&gt;
&lt;br /&gt;
    setup_c0_status_pri                         # 设置cp0_status 寄存器&lt;br /&gt;
&lt;br /&gt;
    ARC64_TWIDDLE_PC                        # 除非 CONFIG_ARC64，否则为空操作&lt;br /&gt;
&lt;br /&gt;
#ifdef CONFIG_MIPS_MT_SMTC&lt;br /&gt;
    /*&lt;br /&gt;
     * In SMTC kernel, &amp;quot;CLI&amp;quot; is thread-specific, in TCStatus.&lt;br /&gt;
     * We still need to enable interrupts globally in Status,&lt;br /&gt;
     * and clear EXL/ERL.&lt;br /&gt;
     *&lt;br /&gt;
     * TCContext is used to track interrupt levels under&lt;br /&gt;
     * service in SMTC kernel. Clear for boot TC before&lt;br /&gt;
     * allowing any interrupts.&lt;br /&gt;
     */&lt;br /&gt;
    mtc0    zero, CP0_TCCONTEXT&lt;br /&gt;
&lt;br /&gt;
    mfc0    t0, CP0_STATUS&lt;br /&gt;
    ori t0, t0, 0xff1f&lt;br /&gt;
    xori    t0, t0, 0x001e&lt;br /&gt;
    mtc0    t0, CP0_STATUS&lt;br /&gt;
#endif /* CONFIG_MIPS_MT_SMTC */&lt;br /&gt;
&lt;br /&gt;
    PTR_LA      t0, __bss_start                      # clear .bss&lt;br /&gt;
    LONG_S      zero, (t0)&lt;br /&gt;
    PTR_LA      t1, __bss_stop - LONGSIZE&lt;br /&gt;
1:&lt;br /&gt;
    PTR_ADDIU   t0, LONGSIZE&lt;br /&gt;
    LONG_S      zero, (t0)&lt;br /&gt;
    bne     t0, t1, 1b&lt;br /&gt;
&lt;br /&gt;
    LONG_S      a0, fw_arg0                 # firmware arguments&lt;br /&gt;
    LONG_S      a1, fw_arg1               # bootloader 会将要传给内核的参数&lt;br /&gt;
    LONG_S      a2, fw_arg2                  写在 a0 ~ a4 里。此处为将参数保存&lt;br /&gt;
    LONG_S      a3, fw_arg3                    在 fw_arg0 ~ fw_arg3 四个变量里&lt;br /&gt;
&lt;br /&gt;
    MTC0        zero, CP0_CONTEXT        # clear context register&lt;br /&gt;
    PTR_LA      $28, init_thread_union     # 初始化 gp，指向一个union，THREAD_SIZE&lt;br /&gt;
                                                                大小，最低处是一个thread_info 结构&lt;br /&gt;
    PTR_LI      sp, _THREAD_SIZE - 32      # _THREAD_SIZE = THREAD_SIZE&lt;br /&gt;
    PTR_ADDU    sp, $28                           # sp 指向这个union结构的最高低32B处&lt;br /&gt;
    set_saved_sp    sp, t0, t1&lt;br /&gt;
    PTR_SUBU    sp, 4 * SZREG       # init stack pointer&lt;br /&gt;
&lt;br /&gt;
    j       start_kernel                   # gp, sp设好，可以进入 C 语言环境了 :)&lt;br /&gt;
    END(kernel_entry)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[include/asm-mips/thread_info.h]:&lt;br /&gt;
&lt;br /&gt;
  #define   THREAD_SIZE   (PAGE_SIZE &amp;lt;&amp;lt; THREAD_SIZE_ORDER)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
_THREAD_SIZE 是为预处理生成，与THREAD_SIZE 一致。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
来看看 setup_c0_status_pri:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    .macro setup_c0_status_pri&lt;br /&gt;
#ifdef CONFIG_64BIT&lt;br /&gt;
    setup_c0_status ST0_KX 0&lt;br /&gt;
#else&lt;br /&gt;
    setup_c0_status 0 0               # CP0_Status[4:0] 置0，CU0 置1，其他位不变&lt;br /&gt;
#endif                                         &lt;br /&gt;
    .endm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
特别注意一直到 trap_init() 中的 per_cpu_trap_init()，CP0_Status[BEV] 一直为1。因此这个阶段异常的入口一直在0xFFFFFFFFBFC000200&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    .macro setup_c0_status set clr&lt;br /&gt;
    .set    push&lt;br /&gt;
#ifdef CONFIG_MIPS_MT_SMTC&lt;br /&gt;
    /*&lt;br /&gt;
     * For SMTC, we need to set privilege and disable interrupts only for&lt;br /&gt;
     * the current TC, using the TCStatus register.&lt;br /&gt;
     */&lt;br /&gt;
    mfc0    t0, CP0_TCSTATUS&lt;br /&gt;
    /* Fortunately CU 0 is in the same place in both registers */&lt;br /&gt;
    /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */&lt;br /&gt;
    li t1, ST0_CU0 | 0x08001c00&lt;br /&gt;
    or t0, t1&lt;br /&gt;
    /* Clear TKSU, leave IXMT */&lt;br /&gt;
    xori    t0, 0x00001800&lt;br /&gt;
    mtc0    t0, CP0_TCSTATUS&lt;br /&gt;
    _ehb&lt;br /&gt;
    /* We need to leave the global IE bit set, but clear EXL...*/&lt;br /&gt;
    mfc0    t0, CP0_STATUS&lt;br /&gt;
    or t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr&lt;br /&gt;
    xor t0, ST0_EXL | ST0_ERL | \clr&lt;br /&gt;
    mtc0    t0, CP0_STATUS&lt;br /&gt;
#else&lt;br /&gt;
    mfc0    t0, CP0_STATUS&lt;br /&gt;
    or t0, ST0_CU0|\set|0x1f|\clr&lt;br /&gt;
    xor t0, 0x1f|\clr&lt;br /&gt;
    mtc0    t0, CP0_STATUS&lt;br /&gt;
    .set    noreorder&lt;br /&gt;
    sll zero,3              # ehb&lt;br /&gt;
#endif&lt;br /&gt;
    .set    pop&lt;br /&gt;
    .endm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
在完成 status, gp, fp 的设置后，直接跳转到 init/main.c 中的 start_kernel() ，开始了一个新的时代 ;) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Comcat</name></author>	</entry>

	</feed>