armlinux从入口到startkernel代码详细分析2.docx

上传人:b****2 文档编号:18566956 上传时间:2023-08-19 格式:DOCX 页数:17 大小:54.12KB
下载 相关 举报
armlinux从入口到startkernel代码详细分析2.docx_第1页
第1页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第2页
第2页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第3页
第3页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第4页
第4页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第5页
第5页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第6页
第6页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第7页
第7页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第8页
第8页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第9页
第9页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第10页
第10页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第11页
第11页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第12页
第12页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第13页
第13页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第14页
第14页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第15页
第15页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第16页
第16页 / 共17页
armlinux从入口到startkernel代码详细分析2.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

armlinux从入口到startkernel代码详细分析2.docx

《armlinux从入口到startkernel代码详细分析2.docx》由会员分享,可在线阅读,更多相关《armlinux从入口到startkernel代码详细分析2.docx(17页珍藏版)》请在冰点文库上搜索。

armlinux从入口到startkernel代码详细分析2.docx

armlinux从入口到startkernel代码详细分析2

1.确定processortype

   arch/arm/kernel/head.S中:

00075:

 mrcp15,0,r9,c0,c0 @getprocessorid       

00076:

 bl__lookup_processor_type @r5=procinfor9=cpuid   

00077:

 movsr10,r5   @invalidprocessor(r5=0)?

00078:

 beq__error_p  @yes,error'p'         

75行:

通过cp15协处理器的c0寄存器来获得processorid的指令.关于cp15的详细内容可参考相关的arm手册

76行:

跳转到__lookup_processor_type.在__lookup_processor_type中,会把processortype存储在r5中

77,78行:

判断r5中的processortype是否是0,如果是0,说明是无效的processortype,跳转到__error_p(出错)

__lookup_processor_type函数主要是根据从cpu中获得的processorid和系统中的proc_info进行匹配,将匹配到的proc_info_list的基地址存到r5中,0表示没有找到对应的processortype.

下面我们分析__lookup_processor_type函数

arch/arm/kernel/head-common.S中:

00145:

 .type__lookup_processor_type,%function

00146:

__lookup_processor_type:

00147:

 adrr3,3f

00148:

 ldmdar3,{r5-r7}

00149:

 subr3,r3,r7  @getoffsetbetweenvirt&phys

00150:

 addr5,r5,r3  @convertvirtaddressesto

00151:

 addr6,r6,r3  @physicaladdressspace

00152:

1:

ldmiar5,{r3,r4}  @value,mask

00153:

 andr4,r4,r9  @maskwantedbits

00154:

 teqr3,r4

00155:

 beq2f

00156:

 addr5,r5,#PROC_INFO_SZ @sizeof(proc_info_list)

00157:

 cmpr5,r6

00158:

 blo1b

00159:

 movr5,#0   @unknownprocessor

00160:

2:

movpc,lr

00161:

00162:

00165:

ENTRY(lookup_processor_type)

00166:

 stmfdsp!

{r4-r7,r9,lr}

00167:

 movr9,r0

00168:

 bl__lookup_processor_type

00169:

 movr0,r5

00170:

 ldmfdsp!

{r4-r7,r9,pc}

00171:

00172:

00176:

 .long__proc_info_begin

00177:

 .long__proc_info_end

00178:

3:

.long.

00179:

 .long__arch_info_begin

00180:

 .long__arch_info_end

  

145,146行是函数定义

147行:

取地址指令,这里的3f是向前symbol名称是3的位置,即第178行,将该地址存入r3.

       这里需要注意的是,adr指令取址,获得的是基于pc的一个地址,要格外注意,这个地址是3f处的"运行时地址",由于此时MMU还没有打开,也可以理解成物理地址(实地址).(详细内容可参考arm指令手册)

      

148行:

因为r3中的地址是178行的位置的地址,因而执行完后:

       r5存的是176行符号__proc_info_begin的地址;

       r6存的是177行符号__proc_info_end的地址;

       r7存的是3f处的地址.

       这里需要注意链接地址和运行时地址的区别.r3存储的是运行时地址(物理地址),而r7中存储的是链接地址(虚拟地址).

      

        __proc_info_begin和__proc_info_end是在arch/arm/kernel/vmlinux.lds.S中:

       00031:

 __proc_info_begin=.;

       00032:

  *(.proc.info.init)

       00033:

 __proc_info_end=.;

       这里是声明了两个变量:

__proc_info_begin和__proc_info_end,其中等号后面的"."是locationcounter(详细内容请参考ld.info)

       这三行的意思是:

__proc_info_begin的位置上,放置所有文件中的".proc.info.init"段的内容,然后紧接着是__proc_info_end的位置.

       kernel使用structproc_info_list来描述processortype.

        在include/asm-arm/procinfo.h中:

       00029:

structproc_info_list{

       00030:

 unsignedint cpu_val;

       00031:

 unsignedint cpu_mask;

       00032:

 unsignedlong __cpu_mm_mmu_flags;

       00033:

 unsignedlong __cpu_io_mmu_flags;

       00034:

 unsignedlong __cpu_flush; 

       00035:

 constchar *arch_name;

       00036:

 constchar *elf_name;

       00037:

 unsignedint elf_hwcap;

       00038:

 constchar *cpu_name;

       00039:

 structprocessor*proc;

       00040:

 structcpu_tlb_fns*tlb;

       00041:

 structcpu_user_fns*user;

       00042:

 structcpu_cache_fns*cache;

       00043:

};

      

       我们当前以at91为例,其processor是926的.

               在arch/arm/mm/proc-arm926.S中:

       00464:

 .section".proc.info.init",#alloc,#execinstr

       00465:

       00466:

 .type__arm926_proc_info,#object

       00467:

__arm926_proc_info:

       00468:

 .long0x41069260  @ARM926EJ-S(v5TEJ)

       00469:

 .long0xff0ffff0

       00470:

 .long  PMD_TYPE_SECT|\

       00471:

  PMD_SECT_BUFFERABLE|\

       00472:

  PMD_SECT_CACHEABLE|\

       00473:

  PMD_BIT4|\

       00474:

  PMD_SECT_AP_WRITE|\

       00475:

  PMD_SECT_AP_READ

       00476:

 .long  PMD_TYPE_SECT|\

       00477:

  PMD_BIT4|\

       00478:

  PMD_SECT_AP_WRITE|\

       00479:

  PMD_SECT_AP_READ

       00480:

 b__arm926_setup

       00481:

 .longcpu_arch_name

       00482:

 .longcpu_elf_name

       00483:

 .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA

       00484:

 .longcpu_arm926_name

       00485:

 .longarm926_processor_functions

       00486:

 .longv4wbi_tlb_fns

       00487:

 .longv4wb_user_fns

       00488:

 .longarm926_cache_fns

       00489:

 .size__arm926_proc_info,.-__arm926_proc_info

      

       从464行,我们可以看到__arm926_proc_info被放到了".proc.info.init"段中.

       对照structproc_info_list,我们可以看到__cpu_flush的定义是在480行,即__arm926_setup.(我们将在"4.调用平台特定的__cpu_flush函数"一节中详细分析这部分的内容.)

      

从以上的内容我们可以看出:

r5中的__proc_info_begin是proc_info_list的起始地址,r6中的__proc_info_end是proc_info_list的结束地址.

149行:

从上面的分析我们可以知道r3中存储的是3f处的物理地址,而r7存储的是3f处的虚拟地址,这一行是计算当前程序运行的物理地址和虚拟地址的差值,将其保存到r3中.

150行:

将r5存储的虚拟地址(__proc_info_begin)转换成物理地址

151行:

将r6存储的虚拟地址(__proc_info_end)转换成物理地址

152行:

对照structproc_info_list,可以得知,这句是将当前proc_info的cpu_val和cpu_mask分别存r3,r4中

153行:

r9中存储了processorid(arch/arm/kernel/head.S中的75行),与r4的cpu_mask进行逻辑与操作,得到我们需要的值

154行:

将153行中得到的值与r3中的cpu_val进行比较

155行:

如果相等,说明我们找到了对应的processortype,跳到160行,返回

156行:

(如果不相等),将r5指向下一个proc_info,

157行:

和r6比较,检查是否到了__proc_info_end.

158行:

如果没有到__proc_info_end,表明还有proc_info配置,返回152行继续查找

159行:

执行到这里,说明所有的proc_info都匹配过了,但是没有找到匹配的,将r5设置成0(unknownprocessor)

160行:

返回

本文来自:

()详细出处参考:

 

一、编译安装流程

 以linux_2.6.36在i386下编译为例

获取源码

最新kernel下载:

http:

//www.kernel.org。

解压$tarxvjflinux-x.y.z.tar.bz2或者$tarxvzflinux-x.y.z.tar.gz。

注意不要把源码放到/usr/src/linux下。

编译时不要用root用户,仅在安装时用root。

源码树

arch                      Architecture-specificsource                       不同cpu

block                    

crypto                   CryptoAPI

Documentation     Kernelsourcedocumentation                     看HOWTO,Changes,Codingstyle

drivers                  Devicedrivers

fireware                

fs                           TheVFSandindividualfilesystems           文件系统

include                   Kernelheaders                                           头文件

init                         Kernelbootandinitialization                      核引导和初始化

ipc                         Interprocesscommunicationcode              进程间通讯

kernel                    Coresubsystems,suchasthescheduler    核子系统,如调度器

lib                          Helperroutines                                            一些基本函数,因为kernel不依赖任何c库

mm                       Memorymanagement                                  存储管理

net                         Networkingsubsystem                                网络

samples

scripts                   Scriptsusedtobuildkernel                          编译核用的脚本

security                Linuxsecuritymoduler

sound                  Soundsubsystem

tools                    

usr                       Earlyuserspacecode(calledinitramfs)       引导用

virt

根目录下的文件

COPYING             kernellicense(theGNUGPLv2)

CREDITS             alistingofdevelopers

MAINTAINERS      individualswhomaintainsubsystemsanddriversinthekernel

看帮助文件

根目录下README

Doucmentation的HOWTO,Chages

编译核(在核源码目录下工作)

$makehelp     查看帮助

1.$makemrproper    清除原来的编译产生的文件。

2.可选

(1)$makedefconfig    用默认的config生成.config文件,如果不用默认的,可跳过这步。

实质上是把arch\x86\configs\i386_defconfig拷贝到核目录下,改名为.config。

ls-a查看目录。

最好是

(2)cp/boot/config-`uname-r`.config把原系统中的配置文件拿来用。

(这次用的fedora13live的)

3. $makelocalmodconfig 可选,精简不需要的模块,只保留系统当前加载的模块。

不过这个只能精简模块[M],对应[*]编译进内核的选项要还是要手动配置。

makelocalmodconfig只保留系统当前加载的模块,要注意一些模块可能之后要用到时才会加载,如一些usb设备的驱动,手动选回来。

在这个命令之前,最好先makemenuconfig,不做修改保存,防止出现一长串的选项。

(注意:

makelocalmodconfig之后要把选项CryptographicAPI--->Authencsupport选回来,避免无法登陆。

还有CryptographicAPI--->PseudoRandomNumberGenerationforCrytographicmodules和CryptographicAPI--->[*]FIPS200compliance)

4.$makemenuconfig   以菜单的方式配置核,保存到.config。

配置时选择需要的选项即可,节省编译时间。

(直接用fedora13live的.config害得我的破机子编译用了7小时!

只能说很安全啦!

主要是很多模块是没必要的啦。

注意:

如果是同版本的内核编译,还需要备份下当前模块

  cd/lib/modules

  mv2.6.312.6.31_old

  指定内核识别码

  vimMakefile

  EXTRAVERSION=.custom-1(第4行)

5.$makeall                编译,大概要一个小时。

生成的主要文件是vmlinuz,System.map和arch/x86/boot/bzImage。

要快一点的话可以用$makeall-j2>/dev/null,单核接j2,双核接j4。

6.$makemodules_install    安装模块到/lib/modules/2.6.36。

7.$makeinstall           /boot目录下出现vmlinuz-2.6.36,System.map-2.6.36,initramfs-2.6.36.img。

引导配置文件/boot/grub/grub.conf被修改,加上了新的kernel:

----------------------------------------------------------------------------------------------------------------

default=1     //改成default=0

timeout=0     //改成timeout=10,显示多内核选择菜单的延时

hiddenmenu//改成#hiddenmenu,注释掉,预防新内核失败无法再启动系统

...

titleFedora(2.6.36)

   root(hd0,0)

   kernel/vmlinuz-2.6.36vga=773roroot=/dev/mapper/VolGroup-lv_rootrd_LVM_LV=VolGroup/lv_rootrd_LVM_LV=VolGroup/lv_swaprd_NO_LUKSrd_NO_MDrd_NO_DMLANG=en_US.UTF-8SYSFONT=latarcyrheb-sun16KEYBOARDTYPE=pcKEYTABLE=usrhgbquiet

   initrd/initramfs-2.6.36.img

titleFedora(2.6.33.3-85.fc13.i686)

   root(hd0,0)

   kernel/vmlinuz-2.6.33.3-85.fc13.i686vga=773roroot=/dev/mapper/VolGroup-lv_rootrd_LVM_LV=VolGroup/lv_rootrd_LVM_LV=VolGroup/lv_swaprd_NO_LUKSrd_NO_MDrd_NO_DMLANG=en_US.UTF-8SYSFONT=latarcyrheb-sun16KEYBOARDTYPE=pcKEYTABLE=usrhgbquiet

   initrd/initramfs-2.6.33.3-85.fc13.i686.img

----------------------------------------------------------------------------------------------------------------

修改启动配置文件

/boot/grub/menu.lst它指向grub.conf

grub.conf文件中,把default=改成新生成核的顺序数

显示多内核选项菜单,timeout=10,#hiddenmenu

保存grub.conf。

重启reboot。

 

PASS 过关!

关键在于内核配置。

 

tips:

如果机器破的话,编译的时候不要用电脑,否则资源被占了本来编译1小时会变成几小时。

----------------------------------------------------------------------------------------------------------------

二、其它的详细说明

 

清除之前内核编译痕迹

makeclean-deleteeverythingnotneededforbuildingexternalmodules

makem

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2