Linux file system migration full decryption

Publisher:科技创客Latest update time:2021-04-28 Source: eefocusKeywords:Linux Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Introduction: Recently, people have been talking to me about the problem of static mapping. Today, I will take the linux-2.6.35 kernel source code as an example to explain the process of IO static mapping (ARM platform).

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

};

The structure object is initialized in the BSP file of the corresponding board (here S5PC100 platform is taken as an example)


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

MACHINE_START(SMDKC100, "SMDKC100")

/* Maintainer: Byungho Min */

.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 macro definition in 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


That is, the field .map_io in struct machine_desc is registered as 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));

}

The iotable_init function above completes the IO mapping.


The structure static struct map_desc is defined in asm/io.h

struct map_desc {

unsigned long virtual; //Mapped virtual address

unsigned long pfn; //The page frame number where the mapped physical address is located

unsigned long length; //The length of the mapped IO resource

unsigned int type; //IO type

};


What is more difficult to understand here is the "mapped virtual address virtual", which is self-defined and can be modified, but cannot be repeated with the already mapped one.

You can refer to the kernel document Documentationarmmemory.txt, which describes it as follows:

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 is defined in 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


The IO mapping in S5PC100 is linearly offset from S3C_ADDR_BASE

#define S3C_ADDR_BASE (0xF4000000)


Keywords:Linux Reference address:Linux file system migration full decryption

Previous article:Design of HDLC protocol controller based on FPGA+ARM architecture
Next article:Physical design of microprocessor chip in wireless fire monitoring system

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号