Linux 文件系统移植全解密

来源:本站
导读:目前正在解读《Linux 文件系统移植全解密》的相关信息,《Linux 文件系统移植全解密》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《Linux 文件系统移植全解密》的详细说明。
简介:最近不断有人跟我说起静态映射的问题,今天就以linux-2.6.35内核源码为例说明一下IO静态映射的过程(ARM平台)。


//init/main.c

asmlinkage void __init start_kernel(void){

...

setup_arch(&command_line);

...

}

//arch/arm/kernel/setup.c

void __init setup_arch(char **cmdline_p){

...

paging_init(mdesc);

...

}

//arch/arm/mm/mmu.c

void __init paging_init(struct machine_desc *mdesc){

...

devicemaps_init(mdesc);

...

}

//arch/arm/mm/mmu.c

static void __init devicemaps_init(struct machine_desc *mdesc){

...

if (mdesc->map_io) //回调map_io

mdesc->map_io();

...

}

//arch/arm/include/asm/mach/arch.h

struct machine_desc {

/*

* Note! The first four elements are used

* by assembler code in head.S, head-common.S

*/

unsigned int nr; /* architecture number */

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);

};

该结构体对象初始化在对应板子的BSP文件中(这里以S5PC100平台为例)

//arch/arm/mach-s5pc100/mach-smdkc100.c

MACHINE_START(SMDKC100, "SMDKC100")

/* Maintainer: Byungho Min <bhmin@samsung.com> */

.phys_io = S3C_PA_UART & 0xfff00000,

.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,

.boot_params = S5P_PA_SDRAM + 0x100,

.init_irq = s5pc100_init_irq,

.map_io = smdkc100_map_io,

.init_machine = smdkc100_machine_init,

.timer = &s3c24xx_timer,

MACHINE_END

//MACHINE_START宏定义在arch/arm/include/asm/mach/arch.h

#define MACHINE_START(_type,_name)

static const struct machine_desc __mach_desc_##_type

__used

__attribute__((__section__(".arch.info.init"))) = {

.nr = MACH_TYPE_##_type,

.name = _name,

#define MACHINE_END

即struct machine_desc中的域.map_io登记为smdkc100_map_io

static void __init smdkc100_map_io(void)

{

s5p_init_io(NULL, 0, S5P_VA_CHIPID);

...

}

//arch/arm/plat-s5p/cpu.c

/* minimal IO mapping */

static struct map_desc s5p_iodesc[] __initdata = {

{

.virtual = (unsigned long)S5P_VA_CHIPID,

.pfn = __phys_to_pfn(S5P_PA_CHIPID),

.length = SZ_4K,

.type = MT_DEVICE,

}, {

.virtual = (unsigned long)S3C_VA_SYS,

.pfn = __phys_to_pfn(S5P_PA_SYSCON),

.length = SZ_64K,

.type = MT_DEVICE,

}, {

.virtual = (unsigned long)S3C_VA_UART,

.pfn = __phys_to_pfn(S3C_PA_UART),

.length = SZ_4K,

.type = MT_DEVICE,

}, {

.virtual = (unsigned long)VA_VIC0,

.pfn = __phys_to_pfn(S5P_PA_VIC0),

.length = SZ_16K,

.type = MT_DEVICE,

}, {

.virtual = (unsigned long)VA_VIC1,

.pfn = __phys_to_pfn(S5P_PA_VIC1),

.length = SZ_16K,

.type = MT_DEVICE,

}, {

.virtual = (unsigned long)S3C_VA_TIMER,

.pfn = __phys_to_pfn(S5P_PA_TIMER),

.length = SZ_16K,

.type = MT_DEVICE,

}, {

.virtual = (unsigned long)S5P_VA_GPIO,

.pfn = __phys_to_pfn(S5P_PA_GPIO),

.length = SZ_4K,

.type = MT_DEVICE,

},

};

/* read cpu identification code */

void __init s5p_init_io(struct map_desc *mach_desc,

int size, void __iomem *cpuid_addr){

unsigned long idcode;

/* initialize the io descriptors we need for initialization */

iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));

if (mach_desc)

iotable_init(mach_desc, size);

idcode = __raw_readl(cpuid_addr);

s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));

}

上面的 iotable_init函数完成IO映射。

结构体static struct map_desc定义在asm/io.h中

struct map_desc {

unsigned long virtual; //映射后的虚拟地址

unsigned long pfn; //被映射的物理地址所在页帧号

unsigned long length;//被映射的IO资源长度

unsigned int type; //IO类型

};

这里比较难理解的是“映射后的虚拟地址virtual”,这个是自己定义的,可以修改,但是不能和已经映射的重复。

可以参看内核文档Documentationarmmemory.txt,其中描述如下:

VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space.

Memory returned by vmalloc/ioremap will

be dynamically placed in this region.

VMALLOC_START may be based upon the value

of the high_memory variable.

VMALLOC_START 定义在arch/arm/include/asm/pgtable.h中

/*

* Just any arbitrary offset to the start of the vmalloc VM area: the

* current 8MB value just means that there will be a 8MB "hole" after the

* physical memory until the kernel virtual memory starts. That means that

* any out-of-bounds memory accesses will hopefully be caught.

* The vmalloc() routines leaves a hole of 4kB between each vmalloced

* area for the same reason. ;)

*

* Note that platforms may override VMALLOC_START, but they must provide

* VMALLOC_END. VMALLOC_END defines the (exclusive) limit of this space,

* which may not overlap IO space.

*/

#ifndef VMALLOC_START

#define VMALLOC_OFFSET (8*1024*1024)

#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))

#endif

S5PC100中IO映射从S3C_ADDR_BASE开始线性偏移

#define S3C_ADDR_BASE (0xF4000000)

提醒:《Linux 文件系统移植全解密》最后刷新时间 2024-03-14 01:04:39,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《Linux 文件系统移植全解密》该内容的真实性请自行鉴别。