linux 3.6 启动源码分析(三) setup_arch

转载地址:http://blog.csdn.net/qing_ping/article/details/17351541

setup_arch()函数是start_kernel阶段最重要的一个函数,每个体系都有自己的setup_arch()函数,是体系结构相关的,具体编译哪个体系的setup_arch()函数,由顶层Makefile中的ARCH变量决定:
它首先通过检测出来的处理器类型进行处理器内核的初始化,然后通过 bootmem_init()函数根据系统定义的 meminfo 结构进行内存结构的初始化,最后调用paging_init()开启 MMU,创建内核页表,映射所有的物理内存和 IO空间。

  1. void __init setup_arch(char **cmdline_p)  
  2. {  
  3.     /*内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。 
  4.     machine_desc结构体通过MACHINE_START宏来初始化,在代码中, 
  5.     通过在start_kernel->setup_arch中调用setup_machine_fdt来获取。*/  
  6.     struct machine_desc *mdesc;  
  7.     /*首先从arm寄存器里面取得cpu ID,然后调用lookup_processor_type来取得proc_info_list这个结构体。 
  8.     取得proc_info_list以后,将里面的内容一个个赋值给相应的全局变量, 
  9.     然后将CPU的信息打印出来。然后它会从arm寄存器里面获得cache的信息, 
  10.     并将cache的信息打印出来(CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c53c7d   
  11.     CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache)。*/  
  12.     setup_processor();  
  13.     /*machine_desc结构体通过MACHINE_START宏来初始化,在代码中,调用setup_machine_fdt来获取。 
  14.     对于samad5,它通过在arch/arm/mach-at91/board_dt.c中的DT_MACHINE_START宏初始化 
  15.     输出CPU型号Machine: Atmel SAMA5 (Device Tree), model: Atmel SAMA5D34-EK*/  
  16.     mdesc = setup_machine_fdt(__atags_pointer);  
  17.     if (!mdesc)  
  18.         mdesc = setup_machine_tags(machine_arch_type);  
  19.     machine_desc = mdesc;  
  20.     machine_name = mdesc->name;  
  21.   
  22.     setup_dma_zone(mdesc);  
  23.   
  24.     //通过struct machine_desc 中的soft_reboot数据来设置重启类型:  
  25.     if (mdesc->restart_mode)  
  26.         reboot_setup(&mdesc->restart_mode);  
  27.       
  28.     /*这里通过连接脚本中得到的Linux代码位置数据来初始化一个mm_struct结构体init_mm中的部分数据 
  29.     ps:每一个任务都有一个mm_struct结构以管理内存空间,init_mm是内核自身的mm_struct 
  30.     */  
  31.     init_mm.start_code = (unsigned long) _text;  
  32.     init_mm.end_code   = (unsigned long) _etext;  
  33.     init_mm.end_data   = (unsigned long) _edata;  
  34.     init_mm.brk    = (unsigned long) _end;  
  35.   
  36.     /* 同时填充cmd_line以备后用, 保护boot_command_line数据 populate cmd_line too for later use, preserving boot_command_line */  
  37.     strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);  
  38.     *cmdline_p = cmd_line;  
  39.     /* 
  40.     处理在 struct obs_kernel_param 中定义为early的启动参数(主要是内存配置部分的参数) 
  41.          
  42.     其中就分析了mem=size@start参数初始化了struct meminfo meminfo; 
  43.     同时如果有vmalloc=size参数也会初始化 vmalloc_min 
  44.     参考:《Linux内核高-低端内存设置代码跟踪(ARM构架)》 
  45.          
  46.     这里需要注意的是内核的cmdline中的参数按照其被需要的先后,分为early和非early的。 
  47.     include/linux/init.h: 
  48.      
  49.     struct obs_kernel_param { 
  50.     const char *str;              //在cmdline中相应参数名。 
  51.     int (*setup_func)(char *);  //对于此参数的专用处理函数 
  52.     int early;                //是否为早期需要处理的参数 
  53.     }; 
  54.      
  55.     两种不同的参数在内核中用了不同的宏来定义: 
  56.     early: #define early_param(str, fn) \ 
  57.            __setup_param(str, fn, fn, 1) 
  58.      
  59.     非early: #define __setup(str, fn) \ 
  60.             __setup_param(str, fn, fn, 0) 
  61.      
  62.     使用这两个宏定义的参数和构架相关,一些构架或者板子可以定义自己特定的参数和处理函数。对于比较重要的“men”参数就是early参数。 
  63.     */    
  64.     parse_early_param();  
  65.   
  66.     sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);  
  67.     sanity_check_meminfo();//在此处设置struct meminfo meminfo中每个bank中的highmem变量2.通过vmalloc_min确定每个bank中的内存是否属于高端内存  
  68.     arm_memblock_init(&meminfo, mdesc);//按地址数据从小到大排序meminfo中的数据,并初始化全局的memblock数据。  
  69.   
  70.     /* 
  71.     设置内核的参考页表。 
  72.     此页表不仅用于物理内存映射,还用于管理vmalloc区。 
  73.     此函数中非常重要的一点就是初始化了bootmem分配器! 
  74.     */  
  75.     paging_init(mdesc);  
  76.     //通过获取设备描述结构体(struct machine_desc)中的数据和编译时产生的地址数据,初始化内存相关的全局结构体变量。  
  77.     request_standard_resources(mdesc);  
  78.   
  79.     if (mdesc->restart)  
  80.         arm_pm_restart = mdesc->restart;  
  81.     //通过启动参数中的“非平坦设备树”信息(如果有),获取内存相关信息  
  82.     unflatten_device_tree();  
  83.   
  84.     /*针对SMP处理器,初始化可能存在的CPU映射 - 这描述了可能存在的CPU*/  
  85. #ifdef CONFIG_SMP  
  86.     if (is_smp())  
  87.         smp_init_cpus();  
  88. #endif  
  89.     /*1.用于内核崩溃时的保留内核此功能通过内核command line参数中的”crashkernel=”保留下内存用于主内核崩溃时获取内核信息的导出*/  
  90.     reserve_crashkernel();  
  91.     /* 
  92.     初始化ARM内部的TCM(紧耦合内存)。 
  93.     参考资料:《对ARM紧致内存TCM的理解》 
  94.     */  tcm_init();  
  95.   
  96. #ifdef CONFIG_MULTI_IRQ_HANDLER  
  97.     handle_arch_irq = mdesc->handle_irq;  
  98. #endif  
  99.   
  100. #ifdef CONFIG_VT  
  101. #if defined(CONFIG_VGA_CONSOLE)  
  102.     conswitchp = &vga_con;  
  103. #elif defined(CONFIG_DUMMY_CONSOLE)  
  104.     conswitchp = &dummy_con;  
  105. #endif  
  106. #endif  
  107.     /* 
  108.     1.如果设备描述结构体定义了init_early函数(应该是早期初始化之意),则在这里调用。 
  109.     */  if (mdesc->init_early)  
  110.         mdesc->init_early();  
  111. }  
主要完成了4个方面的工作,一个就是取得MACHINE和PROCESSOR的信息然或将他们赋值给kernel相应的全局变量,然后呢是对boot_command_line和tags接行解析,再然后呢就是memory、cach的初始化,最后是为kernel的后续运行请求资源。主要完成了4个方面的工作,

1.一个就是取得MACHINE和PROCESSOR的信息然或将他们赋值给kernel相应的全局变量.

2.对boot_command_line和tags接行解析.

3.memory、cach的初始化.

4.为kernel的后续运行请求资源.

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值