linux io映射,【原创】Linux 文件系统移植全解密以linux-2.6.35内核源码为例说明一下IO静态映射的过程...
最近不断有人跟我说起静态映射的问题,今天就以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 */
.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”,这个是自己定义的,可以修改,但是不能和已经映射的重复。
可以参看内核文档\Documentation\arm\memory.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 io映射,【原创】Linux 文件系统移植全解密以linux-2.6.35内核源码为例说明一下IO静态映射的过程...相关推荐
- 基础IO(文件接口、安装内核源码超详细步骤图解、静态库与动态库)
基础IO C语言的文件操作接口 fopen fclose fread fwrite fseek 系统调用文件接口 open close read write lseek 安装内核源码 文件描述符&am ...
- 39 解决全志h3 linux内核源码里的关于script.fex的bug
在script.fex里有关于io口的配置: Port:端口+组内序号<功能分配><内部电阻状态><驱动能力><输出电平状态>[gpio_para]gp ...
- Linux移植:正点原子阿尔法IMX6ULL开发板Linux内核源码移植详细步骤(4.1.15版本内核)
Linux移植:正点原子阿尔法IMX6ULL开发板Linux内核源码移植详细步骤(4.1.15版本内核) 文章目录 Linux移植:正点原子阿尔法IMX6ULL开发板Linux内核源码移植详细步骤(4 ...
- iostat IO统计原理linux内核源码分析----基于单通道SATA盘
iostat IO统计原理linux内核源码分析----基于单通道SATA盘 先上一个IO发送submit_bio流程图,本文基本就是围绕该流程讲解. 内核版本 3.10.96 详细的源码注释:htt ...
- Linux内核移植之一:内核源码结构与Makefile分析
内容来自 韦东山<嵌入式Linux应用开发完全手册> 一.内核介绍 1.版本及其特点 Linux内核的版本号可以从源代码的顶层目录下的Makefile中看到,比如下面几行它们构成了Linu ...
- linux内核源码分析之虚拟文件系统VFS(一)
目录 一.文件系统类型 二.VFS虚拟文件系统 三.VFS中主要的对象类型 四.结构体之间的关系 五.inode 节点 一.文件系统类型 基于磁盘的文件系统:在非易失介质上存储文件,在多次会话间保持文 ...
- 【技术分享篇】Linux内核——手把手带你实现一个Linux内核文件系统丨Linux内核源码分析
手把手带你实现一个Linux内核文件系统 1. 内核文件系统架构分析 2. 行行珠玑,代码实现 [技术分享篇]Linux内核--手把手带你实现一个Linux内核文件系统丨Linux内核源码分析 更多L ...
- linux内核源码实战_3.2理解设备驱动和文件系统
linux内核源码实战_3.2理解设备驱动和文件系统 linux内核源码实战_理解设备驱动和文件系统 理解设备驱动和文件系统 理解设备驱动和文件系统详解 7-文件系统-proc文件系统实现 总结 li ...
- Linux内核源码组织结构
本文主要参考韦东山老师的<嵌入式Linux应用开发完全手册>,基于Linux-2.6.32.2源码. 概要:本文内容包含Linux源码树结构分析.Linux Makefile分析.Kcon ...
最新文章
- JavaScript服务器端开发基础之Math对象小结
- Linux命令(007) -- systemctl
- 吴恩达深度学习课程deeplearning.ai课程作业:Class 1 Week 4 assignment4_2
- 计算机科学 理学,077500计算机科学与技术(理学).doc
- java 控制台刷屏 dll_Java刷屏问题,下面是我编的代码,请大神帮忙解决下,谢谢...
- R语言的常用函数速查
- 列车控制matlab仿真,基于matlab的列车纵向碰撞建模仿真研究
- 如何从“人肉运维”升级为“智能运维”?
- 想做合格的产品经理,你需要这个证书
- 使用JSONP解决跨域
- 个人永久性免费-Excel催化剂功能第29波-追加中国特色的中文相关自定义函数
- 浙大版《C语言程序设计(第3版)》题目集习题4-11 兔子繁衍问题 (15 分)
- 打印100以内的质数
- 集成电路只有丝印如何识别引脚顺序
- oracle elsif和else if,ORACLE ELSIF 与 ELSE IF
- 码刀客-pandas中将一张表中数据拆分成多个sheet_name
- 别了,我的程序员生涯!
- Unity IK动画
- 基于SSM 和 layui 的增删查改
- wcs无线计算服务器,BKR/拜卡 WCS-10M
热门文章
- Spark _10_补充部分算子【三】
- 【Java文件操作(六)】借助内存复制图片:ByteArrayOutputStream\ByteArrayInputStream\FileOutputStream\FileInputStream辨析
- AbstractByteBuf源码分析
- 操作系统(5) -- 输入/输出管理
- leetcode-- 124. 二叉树中的最大路径和
- 【0ms优化】剑指 Offer 18. 删除链表的节点
- [leetcode]111.二叉树的最小深度
- linux设置docker自动启动,CentOS7安装Docker配置服务端和容器自启动
- android ndk使用c 11,使用c 11 std :: async在android ndk中使用不完整类型无效
- linux快捷命令怎么拼日期,liunx常用命令,快捷键