注:
原文出自taoyuetao大侠的博客上:
http://www.eetop.cn/blog/html/45/11145_itemid_1512.html
小弟参考之研究s3c2410相关代码,然后做了稍微的修改,作为一个学习笔记,方便以后的学习,也希望对后人有所帮助^_^
前一篇介绍了汇编函数__lookup_processor_type,
这一篇介绍__lookup_architecture_type函数
函数__lookup_architecture_type介绍:
每个机器(一般指的是某一个电路板)都有自己的特殊结构,如物理内存地址,物理I/O地址,显存起始地址等等,
这个结构为struct machine_desc,定义在asm-arm/mach/arch.h中:
struct machine_desc {
/*
* Note! The first five elements are used
* by assembler code in head-armv.S
*/
unsigned
int nr; /* architecture number */
unsigned
int phys_ram; /* start of physical ram */
unsigned
int phys_io; /* start of physical io */
unsigned
int io_pg_offst; /* byte offset for io
* page tabe entry */
const
char *name; /* architecture name */
unsigned
long boot_params; /* tagged list */
unsigned
int video_start; /* start of video RAM */
unsigned
int video_end; /* end of video RAM */
unsigned
int reserve_lp0 :1; /* never has lp0 */
unsigned
int reserve_lp1 :1; /* never has lp1 */
unsigned
int reserve_lp2 :1; /* never has lp2 */
unsigned
int soft_reboot :1; /* soft reboot */
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平台为例)kernel\arch\arm\mach-xxx\xxx.c中,是用宏来定义的,以s3c2410的开发板为例:
定义在kernel\arch\arm\mach-s3c2410\mach-smdk2410.c文件中,如下所示:
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new
identifier and switch to SMDK2410 */
/*
Maintainer: Jonas Dietsche */
.phys_ram = S3C2410_SDRAM_PA,
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA
+ 0x100,
.map_io = smdk2410_map_io,
.init_irq = smdk2410_init_irq,
.timer = &s3c24xx_timer,
MACHINE_END
这些宏也定义在kernel/include/asm-arm/mach/arch.h中,以MACHINE_START为例:
#define MACHINE_START(_type,_name) \
const struct machine_desc
__mach_desc_##_type \
__attribute__((__section__(".arch.info.init")))
= { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
展开之后结构的是:
__mach_desc_SMDK2410= {
.nr = MACH_TYPE_SMDK2410,
.name = "SMDK2410",
中间的1行__attribute__((__section__(".arch.info")))
= {说明将这个结构放到指定的段.arch.info中,这和前面的
.proc.info是一个意思,__attribute__((__section__的含义参考GNU手册。后面的宏都是类似的含义,这里就不再一一介绍。
下面开始说明源码:
第1行实现r3指向3b的地址,3b如__lookup_processor_type介绍的第19行,
第3行将r3所指向的数据区的数据读出到r4,r5,r6,执行结果是
R5= __arch_info_begin,r6= __arch_info_end,r4=第19行的地址
用仿真器查看:
R5= 0xc0018694
R6= 0xc00186cc
R4= 0xc0008324 (为何是0xc0008324而不是0x30008324???)
第4行算出虚、实地址的偏移,
第5-6行的结果应该是r5指向__arch_info_begin的实地址,r6指向__arch_info_end的实地址。
第7行读取__mach_desc_
SMDK2410结构中的nr参数到r3中,
第8行比较r3和r1中的机器编号是否相同,
r3中的nr值MACH_TYPE_SMDK2410定义在kernel\include\asm-arm\mach-types.h中:
#define MACH_TYPE_SMDK2410
193
r1中的值是由bootloader传递过来的,这在<<linux启动流程分析(1)---bootloader启动内核过程>>中有说明,如果机器编号相同,跳到14行返回。如果不同则将地址指针增加,在跳到7行继续查找,见10--12行的代码,如果检索完所有的machine_desc仍然没有找到则将r5清零并返回。
/*
* Lookup machine
architecture in the linker-build list of architectures.
* Note that we can't use
the absolute addresses for the __arch_info
* lists since we aren't
running with the MMU on (and therefore, we are
* not in the correct
address space). We have to calculate the
offset.
*
* r1 = machine architecture number
* Returns:
* r3, r4, r6 corrupted
* r5 = mach_info pointer in physical address
space
*/
.type __lookup_machine_type, %function
1: __lookup_machine_type:
2: adr r3,
3b
3: ldmia r3,
{r4, r5, r6}
4: sub r3,
r3, r4 @ get offset between
virt&phys
5: add r5,
r5, r3 @ convert virt addresses
to
6: add r6,
r6, r3 @ physical address space
7: 1: ldr r3,
[r5, #MACHINFO_TYPE] @ get machine type
8: teq r3,
r1 @ matches loader number?
9: beq 2f @
found
10: add r5,
r5, #SIZEOF_MACHINE_DESC @ next machine_desc
11: cmp r5,
r6
12: blo 1b
13: mov r5, #0 @
unknown machine
14 2: mov pc,
lr
posted on 2007-07-25 17:05
lfc 阅读(1294)
评论(0) 编辑 收藏 引用