您的位置 首页 方案

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

描述armlinux启动的概要过程,以S5PV210(CortexA8)为例,本文描述第一个阶段。一、armlinux的引导uboot在引导armlinux…

描绘arm linux发动的概要进程,以S5PV210(Cortex A8)为例,本文描绘榜首个阶段。

一、arm linux的引导

uboot在引导arm linux(uImage镜像)到SDRAM之后,经过bootm指令对uImage镜像的64个字节头进行解说,获取linux的entry进口地址,并赋值给theKernel函数指针(一般该值是0x38),并将uboot的环境变量参数(如渠道的内存块区域信息、linux发动指令信息bootargs等)按linux要求的tags方式放置在0x30100开端的当地。接着关掉MMU,铲除icache,dcache,最终经过该函数将控制权交给arm linux:

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

其间,machid是渠道的id,其需求与arch/arm/tools/mach_types 中界说的机器ID共同,不然无法发动。bd->bi_boot_params即0x30100,描绘了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 intnr; /* 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传递过来的第三个参数(0x30100)

5)create_page_tables 创立暂时页表,均是以1M为单位进行映射,所以4G空间需求16K,从0x34到0X38。共映射三个部分:

i. linux内核镜像空间的映射(0xc8***开端的内核空间映射到0x38***)

ii. 创立页表到敞开mmu之间还有一段代码需求运转,由于还需求为linux发动的初始1M空间创立一段直接映射,此刻仍是0X38+的地址运转,所以映射是0X38+映射到0X38+

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言语编写。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/277336.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部