静态映射表的建立在struct machine_desc结构体的 map_io函数中,具体到x210开发板就是在
kernel/arch/arm/mach-s5pv210/mach-x210.c文件末尾的struct machine_desc结构体的.map_io
查阅代码看到.map_io = smdkc110_map_io 也就是smdkc110_map_io是真正的建立静态映射表的函数
下面主要分析俩个部分 :
① smdkc110_map_io是如何实现的
② smdkc110_map_io是如何被调用的
☆ smdkc110_map_io的实现分析
smdkc110_map_io
s5p_init_io
iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc)); //s5p_iodesc结构体是关键
create_mapping
//在往下就是就是具体实现了,这里暂不做分析
起作用的关键就是结构体数组struct map_desc s5p_iodesc[] 里面定义了虚拟地址和物理地址的映射关系(对应的地址和大小)
如果需要添加新的映射关系只需要在结构体尾部按以下格式增加新的元素并赋值即可
{
.virtual = (unsigned long)S5P_VA_GPIO,
.pfn = __phys_to_pfn(S5P_PA_GPIO),
.length = SZ_4K,
.type = MT_DEVICE,
},
☆ smdkc110_map_io的调用分析
调用流程是:
start_kernel
setup_arch
mdesc = setup_machine(machine_arch_type); //获取板级结构体,下面再分析
paging_init
devicemaps_init
if(mdesc->map_io)
mdesc->map_io();
mdesc->map_io() 就是上面结构体我们赋的 smdkc110_map_io
然后分析 mdesc = setup_machine(machine_arch_type)是如何找到板级结构体的
setup_machine通过调用lookup_machine_type函数可得到mdesc
现在就又有了两个问题 :machine_arch_type是怎么来的 ,lookup_machine_type是如何实现的
① machine_arch_type是怎么来的
在配置内核之后在文件 mach-types.h( 此文件的生成可查看http://blog.csdn.net/yao_guet/article/details/6431359 )中有#define machine_arch_type __machine_arch_type
__machine_arch_type在arch/arm/kernel/head-common.S定义 : .long __machine_arch_type @ r5
并通过下面的 str r1, [r5] @ Save machine type 将bootloader通过r1传递过来的机器码保存到__machine_arch_type
② lookup_machine_type
lookup_machine_type在汇编代码中实现
ENTRY(lookup_machine_type)
stmfd sp!, {r4 - r6, lr}
mov r1, r0
bl __lookup_machine_type
mov r0, r5
ldmfd sp!, {r4 - r6, pc}
ENDPROC(lookup_machine_type)
可见最后调用的是__lookup_machine_type,
__lookup_machine_type函数的实现原理是获取__arch_info_begin 和 __arch_info_end
然后在其中查找__machine_arch_type所对应的struct map_desc结构体
为什么通过__arch_info_begin 和 __arch_info_end 和 __machine_arch_type 就能得到struct map_desc结构体 ?
再回到mach-x210中定义结构体的地方 调用MACHINE_START宏的时候发现把结构体的段属性设置为
__attribute__((__section__(".arch.info.init")))
这样所有的struct map_desc结构体的断属性都是.arch.info.init,而在链接脚本中
.arch.info.init段是放在__arch_info_begin 和 __arch_info_end 之间(原理和uboot中的命令体系一样)
kernel/arch/arm/mach-s5pv210/mach-x210.c文件末尾的struct machine_desc结构体的.map_io
查阅代码看到.map_io = smdkc110_map_io 也就是smdkc110_map_io是真正的建立静态映射表的函数
下面主要分析俩个部分 :
① smdkc110_map_io是如何实现的
② smdkc110_map_io是如何被调用的
☆ smdkc110_map_io的实现分析
smdkc110_map_io
s5p_init_io
iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc)); //s5p_iodesc结构体是关键
create_mapping
//在往下就是就是具体实现了,这里暂不做分析
起作用的关键就是结构体数组struct map_desc s5p_iodesc[] 里面定义了虚拟地址和物理地址的映射关系(对应的地址和大小)
如果需要添加新的映射关系只需要在结构体尾部按以下格式增加新的元素并赋值即可
{
.virtual = (unsigned long)S5P_VA_GPIO,
.pfn = __phys_to_pfn(S5P_PA_GPIO),
.length = SZ_4K,
.type = MT_DEVICE,
},
☆ smdkc110_map_io的调用分析
调用流程是:
start_kernel
setup_arch
mdesc = setup_machine(machine_arch_type); //获取板级结构体,下面再分析
paging_init
devicemaps_init
if(mdesc->map_io)
mdesc->map_io();
mdesc->map_io() 就是上面结构体我们赋的 smdkc110_map_io
然后分析 mdesc = setup_machine(machine_arch_type)是如何找到板级结构体的
setup_machine通过调用lookup_machine_type函数可得到mdesc
现在就又有了两个问题 :machine_arch_type是怎么来的 ,lookup_machine_type是如何实现的
① machine_arch_type是怎么来的
在配置内核之后在文件 mach-types.h( 此文件的生成可查看http://blog.csdn.net/yao_guet/article/details/6431359 )中有#define machine_arch_type __machine_arch_type
__machine_arch_type在arch/arm/kernel/head-common.S定义 : .long __machine_arch_type @ r5
并通过下面的 str r1, [r5] @ Save machine type 将bootloader通过r1传递过来的机器码保存到__machine_arch_type
② lookup_machine_type
lookup_machine_type在汇编代码中实现
ENTRY(lookup_machine_type)
stmfd sp!, {r4 - r6, lr}
mov r1, r0
bl __lookup_machine_type
mov r0, r5
ldmfd sp!, {r4 - r6, pc}
ENDPROC(lookup_machine_type)
可见最后调用的是__lookup_machine_type,
__lookup_machine_type函数的实现原理是获取__arch_info_begin 和 __arch_info_end
然后在其中查找__machine_arch_type所对应的struct map_desc结构体
为什么通过__arch_info_begin 和 __arch_info_end 和 __machine_arch_type 就能得到struct map_desc结构体 ?
再回到mach-x210中定义结构体的地方 调用MACHINE_START宏的时候发现把结构体的段属性设置为
__attribute__((__section__(".arch.info.init")))
这样所有的struct map_desc结构体的断属性都是.arch.info.init,而在链接脚本中
.arch.info.init段是放在__arch_info_begin 和 __arch_info_end 之间(原理和uboot中的命令体系一样)
遍历__arch_info_begin 和 __arch_info_end之间的结构体来找到.nr 为 __machine_arch_type的结构体进行返回