免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7339 | 回复: 13
打印 上一主题 下一主题

[NetBSD] NB上电启动到内核运行之前流程的简单分析 [复制链接]

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-02-25 16:22 |只看该作者 |倒序浏览
NB上电启动到内核运行之前流程的简单介绍

作者:gvim@chinaunix.net/bsd

BSD License版权发布

作为内核分析的前期工作,本文介绍了NetBSD arm port中的smdk2410板从芯片加电到内核被调用之前的前期准备活动。大家不用担心,这些概念很大程度上是和i386是类似的,因此对体系结构有所了解的朋友会发现下面的章节不难理解。选择arm芯片的理由在于我们可以清楚地认识到一个操作系统所需要的底层支持。比如cache[1,2,3],虚拟地址影射的安装[1,2],存储管理器控制[1,2]等有关硬件体系的问题[3]。NetBSD执行流程进入kernel之后,可以很大程度上脱离对硬件平台的考虑。因此,对于内核分析过程来说,将平台有关操作首先在这里以功能介绍的形式予以说明是一个不错的开端。

一 介绍
本文着重的是对功能/流程的描述而不打算深入到实际的具体代码,因此这里简单的说明下smdk2410开发板的情况。具体说明书可以在Samsung网站上找到。

由于我们不关心指令细节,对该介绍不感兴趣的可以简单略过。仅仅知其然就足够明白下面章节的文字。

处理器使用的是arm9系列的芯片。有7种不同的处理器模式,分别是FIQ(快速中断响应),IRQ(中断响应),SVC(管理模式),ABT(异常模式),UND(未定义模式),SYS(系统模式)和大家熟悉的USR(用户模式)。USR具有普通权限,其他模式具有特殊权限。每种模式有16个寄存器,其中R0-R7供所有模式公用,R15固定坐位程序计数器(PC)使用,其他寄存器依据处理器当前所在模式的不同而定。当然,必然还有状态寄存器。开发板的物理地址从0x00000000开始,到0x2FFFFFFF用作ROM空间,0x30000000以上是用作RAM,并且各种处理器的控制寄存器也被影射到不同的物理地址上(一般可以是硬件直接搭线)。该处理器有一个协处理器(称作CPx  即coprocessor)CP15来控制有关控制MMU,控制cache,取得处理器信息等的情况。下面在叙述的时候会适当的提及。

NetBSD就不多介绍了。这里只说一些有关port的问题。NetBSD的平台相关代码放在arch/xxx目录之下。其中有boot代码(一般在arch/xxx/stand/),有启动代码(xxx_start.S),有内核环境初始化代码locore.S,有内存分页相关代码(pmap.c),体系相关代码(xxx_machdep.c)。可以从这里开始对一个port进行移植。

以我们的平台为例,port文件在arch/arm/evbarm下面(对于i386是arch/i386)。在这里我们可以看到我们关心的平台smdk2xx0,进去以后可以找到一个名为smdk2410_start.S的文件。我们就从这里开始。

内核配置文件是/arch/evbarm/conf/SMDK2410 ,ld链接文件是arch/evbarm/conf/ldscript.evbarm
生成方法:

  1. get sys.tgz syssrc.tgz等相关代码
  2. cd /usr/src
  3. ./build -m evbarm tools  // 这里,交叉编译arm的编译器,-m指定平台。(或许需要你手工建立一个/usr/obj目录)
  4. ./build -m evbarm kernel=SMDK2410   // 见上面几行的说明
复制代码

现在你就有了一个可以实际在某arm板上运行的BSD内核了。存放在/usr/obj/sys/.../.../SMDK2410下面。

二 bootloader (boot stage1)
对于嵌入式芯片来说,我们需要比x86更多的知识和系统支撑。在这个过程中,我们需要设置系统启动之前所需要进行的所有活动:比如设置时钟频率,设置MMU的页面影射等。

1 首先我们关闭中断。在系统引导的时候,我们不希望外部中断的发生,因为这个时候我们还没有安装中断的处理句柄,如果发生中断而跳转到中断地址的话,会发生什么呢?这个动作是通过往芯片的控制寄存器写入掩码完成的(类比i386上的EFLAGS寄存器)。

2 接着设置处理器时钟,分频器等有关处理器实际运行的参数。由于涉及其他硬件设计方面的问题,我们忽略它而不会影响下面的分析。

3 由于嵌入式中没有普通PC的二级存储设备(一般是硬盘)。而所有内核代码必须保存在某个地方,这个地方只有是ROM(刚才我们说了在0x00000000 – 0x2FFFFFFF地址空间被影射为ROM的地址)。由于在ROM中读取、运行系统代码的速度很慢,我们需要把系统代码拷贝到RAM里面去。现在,我们拷贝内核到0x30200000(这不是硬性规定,0x30000000 之后的空间被影射为RAM)。

4 内核已经在RAM中了,但是内核还不能运行。为什么呢?因为我们还没有设置存储控制器的行为,也就是说我们不能使用虚拟地址,也不能使用MMU提供的内存保护,权限检查等机制(类比于i386的MMU)。这对于操作系统来说(而不是实时系统)是很不合适的。

细节就不详细讲述了,我们假设我们确实现在可以使用MMU提供的虚拟地址到物理地址的影射。并且,我们有如下的影射图(va表示虚拟地址virtual,pa表示物理地址physical):

va(0x30000000-0x33FFFFFF)影射到pa(0x30000000 - 0x33FFFFFF)中去,va(0xC0000000 - 0xC3FFFFFF)也影射到pa(0x30000000 - 0x33FFFFFF)中去。其余没有提及的虚拟地址和物理地址一一影射,也就是说MMU(va(0x00000000))  ==  pa(0x00000000),MMU(va(0x20000000)) == pa(0x20000000)。 (该写法表示va(0x00000000)经过MMU变换之后影射到pa(0x00000000)上)。

到这里,我们的虚拟地址变换可以这样进行:处理器发出地址va的时候,MMU在接收到va,首先在物理地址0x30000000(这个地址是记录在协处理器CP15的寄存器里,可以被读取和修改)处取得我们的影射表,查找va对应的pa进行访问(虚地址转换的概念和i386上很类似,这个转换表是存放在内存的某个地方,这里我们放在0x30000000处)。

5 好了,为了减少MMU的访村操作(回忆刚才说的转换表是放在内存里的,要转换虚拟地址首先要访问至少一次内存)。因此我们设置好最初的虚拟/物理地址影射之后,可以使用TLB,也就是转换表的高速缓存,这个在i386上也很常用。接着设置一些附属内存的属性。到这里,我们只完成了内核的加载和最初的硬件环境设置,下面可以进入boot stage2,进行内核运行环境的设置。

三 内核环境的初始化 (boot stage2)

前面讲过port的代码集中在locore.S、xxx_machdep.c(我们的例子中是smdk2410_machdep.c)和pmap.c中。其中locore.S利用xxx_machdep.c和pmap.c中的C函数设置内核运行环境。第二部分最后我们打开了MMU支持,因此下面所涉及的地址,除非特殊说明,均指的虚拟地址。

下面就功能模块进行说明。

1 由于locore.S是用汇编语言写的,smdk2410_machdep.c和pmap.c是用C语言写的,大家都知道C函数的调用需要堆栈的支持。所以,我们首先设置好调用smdk2410_machdep.c中函数的堆栈。

2 在smdk2410_machdep.c中,我们需要设置内存属性,取得处理器信息供后面使用,对开发版上的物理寄存器进行影射,安装中断处理,安装页表等操作。

为什么我们还需要对内存,页表等再一次操作呢?因为boot stage1中的设置只是为了可以运行接下来的boot stage2。为了让kernel可以运行,所以我们需要设置kernel的运行环境。

这部分如果要写的话就太多了,简单起见,我用一张图表示了。



四 进入内核

之后我们可以看到熟悉的/kern/init_main.c中的main()了。

五 小结

BSD?我才刚上路呢。(发哥广告词)

参考:
最重要的 /usr/src/sys/*
用google搜索吧,我也不知道从哪里下下来的了
[1] um_s3c2410s_rev12_030428.pdf
[2] Addison Wesley - ARM Architecture Reference Manual (2nd Edition).pdf
[3] 计算机体系结构 --- 量化研究方法


欢迎大家提出指导意见

[ 本帖最后由 gvim 于 2006-2-25 16:48 编辑 ]

论坛徽章:
1
寅虎
日期:2013-09-29 23:15:15
2 [报告]
发表于 2006-02-25 16:24 |只看该作者
五 小结

BSD?我才刚上路呢。(发哥广告词)

呵~还没看,先顶一下!

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
3 [报告]
发表于 2006-02-25 16:34 |只看该作者
原帖由 congli 于 2006-2-25 16:24 发表

呵~还没看,先顶一下!


呵呵,当自己的一个阶段总结。我还在修改一些错误,把这个彻底弄清楚之后我就可以开始kernel之旅了,娃哈哈哈。
这篇文章只是功能上的叙述。图后面的UVM部分我没有读进去。。。。。。下次继续汇报。

论坛徽章:
0
4 [报告]
发表于 2006-02-25 18:47 |只看该作者
深入,透彻!

论坛徽章:
0
5 [报告]
发表于 2006-02-26 11:31 |只看该作者
最近看了一下《构建嵌入式Linux系统》,暂时没有条件试验,纸上得来终究是虚的,
gvim以后要继续写一些极具实践价值的好文章啊!

论坛徽章:
0
6 [报告]
发表于 2006-02-26 13:15 |只看该作者
计算机体系结构 --- 量化研究方法

这门课难啊,而且英文教材,,上了之后几乎没啥概念

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
7 [报告]
发表于 2006-02-26 14:21 |只看该作者
原帖由 bigapple2008 于 2006-2-26 13:15 发表
计算机体系结构 --- 量化研究方法

这门课难啊,而且英文教材,,上了之后几乎没啥概念


呵呵,这本书主要关注的是设计而不是实现。所以让人感觉“虚”。
比如指令系统,它应该是假设你已经知道一些实现上的细节,所以它不告诉你应当如何,而是说“通常有几种情况,那么我们遇到第一种情况时,为什么这样的指令设计相对那种好。遇到第二种情况时,我们建议可以怎样考虑设计这条指令。遇到另外一种市场需求时对于某条指令的设计需要考虑什么,比如我们是否可以在嵌入式芯片里面加入fft的指令”....
而他们的另一本书名字好像叫接口什么的,就告诉你指令怎么流过流水线,什么时候要冒汽泡等等实现细节。

非常classical的两本书。

论坛徽章:
0
8 [报告]
发表于 2006-02-26 20:04 |只看该作者
学习ing

论坛徽章:
0
9 [报告]
发表于 2006-03-07 16:21 |只看该作者
非常感谢gvim。之前就不明白的地方站内短信询问了一下gvim,得到很详尽的答复。我觉得他的回复对其他人也会有帮助。现在贴在这里:
我的问题:
我看到了您的文章,写得清楚透彻,谢谢!有几个问题:
1)我是不是可以这样理解:boot stage 1完全在是bootloader,而boot stage 2就是kernel开始了?
2)用的是哪个bootloader?
3)直接下下来的sys.tar.gz就可以,不需要打补丁了吧?
4)/usr/src/build怎么得到?我刚装了NetBSD,没有那个文件。是不是要build current?
谢谢!

下面是他的回复
呵呵,你好。
其实我这里说的bootstage并不严禁,因为在嵌入式中我没有看见NetBSD有相关文档将每一步称之为bootstage x,我之所以在这里用这个词,是因为考虑到很多朋友不是搞嵌入式的,借用了pc中的bootstage概念。

完整的过程是这样的:
一共分了3步:加载数据/代码;初始化内核内存;初始化内核对象(这步是main之后的行为)

首先,也就是传统概念上的bootloader。它的作用只是拷贝代码/数据等至RAM中去。它里面设置的堆栈,设置的硬件寄存器,设置的页表等,都仅仅为了满足第二步初始化内核内存的需要,而不是为了能够运行内核。这个时候我们还不能初始化内核。

接着,因为内核本身的运行需要内存,而我们还没有设置它,所以locore.S的initarm函数(调用分布在 smdk2410_machdep.c,pmap.c 等文件中),大部分工作就是设置地址映射表,分配内核运行需要的页面。分配每种模式运行时的页面,堆栈等等,所有工作都是为进入内核做准备。当分配完内核内存之后,我们才可能为以后的应用程序的运行计算剩余内存。

最后,内核本身初始化,虽然内核有空间了,但是我们的内核还没有实际生成,也就是说调度器,内存管理,IPC等机制还没有产生,这个是locore.S中进入main函数之后的活动。

bootloader可以在arch/evbarm/stand/中找到。
至少需要下载sys.tar.gz(系统代码)和gnu.tar.gz(编译器代码),用/usr/src/build.sh -m evbarm tools && /usr/src/build.sh -m evbarm kernel=GENERIC 编译。不需要打任何补丁。第一步NetBSD就自动为你生成交叉编译器。第二步编译内核(编译内核可以参考guide)
需要注意的是或许你需要手动 mkdir /usr/obj 这个目录出来。

论坛徽章:
0
10 [报告]
发表于 2006-03-07 18:14 |只看该作者
关于这个过程,《The Design and Implementation of the 4.4BSD Operating System》的最后一章讲得非常详细,可以参考一下。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP