arm linux 启动之一:汇编启动到start_kernel

描述arm linux启动的概要过程,以S5PV210(Cortex A8)为例,本文描述第一个阶段。

一、arm linux的引导

uboot在引导arm linux(uImage镜像)到SDRAM之后,通过bootm命令对uImage镜像的64个字节头进行解释,获取linux的entry入口地址,并赋值给theKernel函数指针(一般该值是0x30008000),并将uboot的环境变量参数(如平台的内存块区域信息、linux启动命令信息bootargs等)按linux要求的tags形式放置在0x30000100起始的地方。接着关掉MMU,清除icache,dcache,最后通过该函数将控制权交给arm linux:

theKernel (0, machid, bd->bi_boot_params);

其中,machid是平台的id,其需要与arch/arm/tools/mach_types 中定义的机器ID一致,否则无法启动。 bd->bi_boot_params即0x30000100,描述了linux启动所需要的信息。

二、arm linux启动的第一部分

该部分是体系相关的汇编部分,代码位于arch\arm\kernel\head.S,入口是ENTRY(stext),其主要完成的工作包括:

1) 设置当前arm工作模式是svc mode,关中断

2)__lookup_processor_type 获取对应的CPU信息数据结构地址,主要是arm v7架构相关的信息,如MMU,cache标志值等,数据结构如下:

struct proc_info_list {

   unsigned int    cpu_val;

   unsigned int    cpu_mask;

   unsigned long     __cpu_mm_mmu_flags;   /* used by head.S */

   unsigned long     __cpu_io_mmu_flags;   /* used by head.S */

   unsigned long     __cpu_flush;    /* used by head.S */

   const char      *arch_name;

   const char      *elf_name;

   unsigned int    elf_hwcap;

   const char      *cpu_name;

   struct processor   *proc;

   struct cpu_tlb_fns *tlb;

   struct cpu_user_fns   *user;

   struct cpu_cache_fns  *cache;

};

arm linux支持各种CPU体系架构,其描述在.proc.info.init 段,对应S5PV210即arch\arm\mm\proc-v7.S, lookup_processor_type先通过协处理器CP15读出CPU ID并跟cpu_val比较,匹配即可得到数据结构地址。该地址是链接到虚拟地址,而此时MMU是关闭的,需要将该地址转为物理地址访问。

         3)__lookup_machine_type获取对应平台机器的数据结构地址,主要是平台板子相关的数据信息,如内存起始地址和大小,中断和timer初始化函数等,如下:          

struct machine_desc {

   unsigned int   nr;      /* architecture number   */

   unsigned int    phys_io; /* start of physicalio  */

   unsigned int    io_pg_offst; /* byte offsetfor io   * page tabe entry */

const char      *name;  /* architecture name  */

   unsigned long      boot_params; /*tagged list     */

   unsigned int    video_start; /* start of videoRAM */

   unsigned int    video_end;  /* end ofvideo RAM   */

   unsigned int    reserve_lp0 :1; /* never haslp0   */

   unsigned int    reserve_lp1 :1; /* never haslp1   */

   unsigned int    reserve_lp2 :1; /* never haslp2   */

   unsigned int    soft_reboot :1; /* softreboot     */

   void       (*fixup)(struct machine_desc *,   struct tag *, char **,    struct meminfo *);

void       (*map_io)(void);/* IO mapping function  */

   void       (*init_irq)(void);

   struct sys_timer   *timer;    /* system tick timer  */

   void       (*init_machine)(void);

};

arm linux支持各种平台板子,其描述在.arch.info.init 段,对应S5PV210即\arch\arm\mach-s5pv210\mach-smdkv210.c。UBOOT的machid即用于搜索匹配nr,以取到机器信息。

        4)检查uboot传递过来的tags是否符合标准,并检测machine数据结构的boot_params的值是否等于theKernel传递过来的第三个参数(0x30000100)

        5)create_page_tables 创建临时页表,均是以1M为单位进行映射,所以4G空间需要16K,从0x30004000到0X30008000。共映射三个部分:

               i. linux内核镜像空间的映射(0xc0008***开始的内核空间映射到0x30008***)

ii. 创建页表到开启mmu之间还有一段代码需要运行,因为还需要为linux启动的初始1M空间创建一段直接映射,此时还是0X30008000+的地址运行,所以映射是0X30008000+映射到0X30008000+

               iii. uboot传递过来的tags参数也需要进行映射(虚拟0XC**映射到0X3**),以进行访问。

6)ldr r13, __switch_data,将 __switch_data数据结构的地址入栈。

7)add   pc,r10, #PROCINFO_INITFUNC,即将PC改到arch\arm\mm\proc-v7.S的 __v7_setup去执行,跳转前将__enable_mmu放到lr,即 __v7_setup执行完就返回到__enable_mmu。 __v7_setup主要是CPU体系相关的初始化,如icache,dcache等。

8)__enable_mmu打开MMU,cache等,最后将r13出栈,取出arch/arm/kernel/head-common.S的__switch_data的第一个内容__mmap_switched函数,并赋给PC

__switch_data:

   .long __mmap_switched

   .long__data_loc         @ r4

   .long_data           @ r5

   .long __bss_start        @r6

   .long_end            @ r7

   .long processor_id       @ r4

   .long __machine_arch_type      @ r5

   .long __atags_pointer       @r6

   .long cr_alignment       @ r7

   .long init_thread_union + THREAD_START_SP @ sp

         9)__mmap_switched初始化data,bss等相关段,保存相关的数据结构地址到相关变量。设置以后系统启动init进程的栈空间。

        10)b  start_kernel 跳转到linux启动的第二部分,为C语言编写。

时间: 2024-10-11 13:42:27

arm linux 启动之一:汇编启动到start_kernel的相关文章

arm linux 启动之二:start_kernel到创建1号进程

本文介绍arm linux启动的第二部分,C语言编写,主要讲述start_kernel到1号进程的创建.主要讲述大概过程,以后再对子函数进行讲解. 一.start_kernel start_kernel位于init/main.c,主要完成linux一些子系统的初始化. 1)smp_setup_processor_id() 单CPU位为空. 2)lock_kernel() 锁CPU,linux是支持抢占的,多CPU时调用这个函数防止其他CPU抢占.3)tick_init() 时间相关初始化4)bo

ARM Linux从Bootloader、kernel到filesystem启动流程

转自:http://www.veryarm.com/1491.html ARM Linux启动流程大致为:bootloader ---->kernel---->root filesystem.bootloader 是一上电就拿到cpu 的控制权的,而bootloader实现了硬件的初始化.bootloader俨然就成了Power on 之后”第一个吃螃蟹”的代码. 谈到这就得想到硬件机制是如何满足这个功能的了.CPU内部一般都集成小容量的SRAM (又叫stapping stone,垫脚石),

ARM linux内核启动时几个关键地址【转】

转自:http://www.cnblogs.com/armlinux/archive/2011/11/06/2396787.html 1.       内核启动地址1.1.   名词解释ZTEXTADDR 解压代码运行的开始地址.没有物理地址和虚拟地址之分,因为此时MMU处于关闭状态.这个地址不一定时RAM的地址,可以是支持读写寻址的flash等存储中介. Start address of decompressor. here's no point in talking about virtua

arm linux下启动ftp服务

1.环境: /home/jello # uname -aLinux  3.10.0 #2 SMP Mon Mar 6 17:52:09 CST 2017 armv7l GNU/Linux 2.使用tcpsvd启动ftp服务 tcpsvd -vE 0.0.0.0 21 ftpd ftpdir & (&表示使当前程序后台运行,以免影响交互)

2.16.3.内核启动的汇编阶段

参考https://blog.csdn.net/skyflying2012/article/details/41344377 本节是内核启动的汇编阶段剩余内容,主要是cpu的校验.机器码的校验.传参tag的校验.页表的创建.各种段的处理等. 2.16.3.1.__lookup_processor_type (1)我们从cp15协处理器的c0寄存器中读取出硬件的CPU ID号,然后调用这个函数来进行合法性检验.如果合法则继续启动,如果不合法则停止启动,转向__error_p启动失败. (2)该函数

ARM linux电源管理——Cortex A系列CPU(32位)睡眠和唤醒的底层汇编实现

ARM linux电源管理——Cortex A系列CPU(32位)睡眠和唤醒的底层汇编实现 承接 http://www.wowotech.net/pm_subsystem/suspend_and_resume.html Linux电源管理(6)_Generic PM之Suspend功能一文中的下图. 本文主要分析平台相关的CPU睡眠和唤醒,即下电和上电流程,以及ARM底层汇编代码实现. 内核版本:3.1.0               CPU:ARM Cortex-A7 1 平台相关函数执行流程

ARM Cortex-M底层技术(2)—启动代码详解

杂谈 工作了一天,脑袋比较乱.一直想把底层的知识写成一个系列,希望可以坚持下去.为什么要写底层的东西呢?首先,工作用到了这部分内容,最近和内部Flash打交道比较多,自然而然会接触到一些底层的东西:第二,近些年来Cortex-M阵营各厂商(ST.Nordic.ATMEL……)对新产品的迭代速度越来越快,以及微控制器应用普及程度的加深,越来越多的开发者把更多精力投注在应用层开发上,花在对底层技术上的时间越来越少,更深层次的原因是走嵌入式底层没有做互联网上层赚钱.希望自己可以把嵌入式ARM Cort

转:linux守护进程的启动方法

Linux 守护进程的启动方法 作者: 阮一峰 日期: 2016年2月28日 "守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问题的由来 Web应用写好后,下一件事就是启动,让它一直在后台运行. 这并不容易.举例来说,下面是一个最简单的Node应用server.js,只有6行. var http = require('http'); http.createServer(function(req, res)

Linux中tomcat开机启动配置脚本【参考其他文章的总结备忘录】

参考文章http://blog.sina.com.cn/s/blog_a57562c80101ic47.html http://blog.csdn.net/cheng168520/article/details/4312828 http://blog.sina.com.cn/s/blog_7f395ece0100ti5y.html 以前在自己本机上安装过一个Linux,后台应为系统崩溃,以前配置的开机启动脚本.数据库主从双备份.负载均衡等都没了,所以现在在重新配置一次,赶紧做个笔记防止自己以后又