LINUX内核静态映射表的建立过程
一. machine_desc结构体
1.1. 内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过machine_desc结构体来控制系统体系架构相关部分的初始化
2.1. 静态映射表与machine_desc关系。
2.1.1. kernel/arch/arm/mach-s5pv210/mach-smdkc110.c 这个文件是由三星在移植内核时提供的一个很重要的文件,这个文件中的函数都是与硬件相关的。mach-smdkc110.c文件中的smdkc110_map_io函数就是静态映射表建立过程调用的一个函数开机时调用映射表建立函数:
/* * Set of macros to define architecture features. This is built into * a table by the linker. */ #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 \ }; MACHINE_START(SMDKV210, "SMDKV210") /* Maintainer: Kukjin Kim <kgene.kim@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 = s5pv210_init_irq, .map_io = smdkv210_map_io, .init_machine = smdkv210_machine_init, #ifdef CONFIG_S5P_HIGH_RES_TIMERS .timer = &s5p_systimer, #else .timer = &s3c24xx_timer, #endif
2.3. 开机时(kernel启动时)smdkc110_map_io怎么被调用的
2.3.1.
start_kernel
setup_arch
paging_init
devicemaps_init
{
if (mdesc->map_io)
mdesc->map_io(); // 这个map_io指向的就是smdkc110_map_io函数,这个之前在讲内核的启动过程的时候就分析过了
}
二. 映射表建立相关函数
2.1. smdkc110_map_io
static void __init smdkv210_map_io(void) { s5p_init_io(NULL, 0, S5P_VA_CHIPID); s3c24xx_init_clocks(24000000); s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs)); }
2.2. s5p_init_io
/* 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)); }
2.3. iotable_init
/* * Create the architecture specific mappings */ void __init iotable_init(struct map_desc *io_desc, int nr) { int i; for (i = 0; i < nr; i++) create_mapping(io_desc + i); }
2.4. 通过分析上述调用过程。最终通过iotable_init函数来实现静态映射表。这里有一个重要的结构体struct map_desc。由于描述映射关系的。内核中定义了该结构体如下:
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, }, };
2.4.1. 当开发者需要增加新映射表时,只需要在此结构体数组添加即可。