2021-6-9 嵌入式学习笔记5:关于ioremap的一些理解

这是在工作中遇到一个问题:有两个厂家用到是不同的rtc芯片,并且设备的从地址是一样的,现在要通过一套内核源码适配这两个机器。硬件信息走的是设备树,我一开始就把两个厂家的rtc都写进去了,结果编译报错。因为从设备地址一样,设备树不报错才怪。本人才疏学浅,只能想到通过i2c静态注册注册的方式(rtc是i2c设备),写个模块编到内核里。

因为主机厂商将设备信息都写到smbios中了,可以通过相关代码获取到主机信息,判断并注册相关rtc设备。厂家那边给了一个物理地址,smbio的信息就写在这个物理地址之后(对,就是这么坑爹),在做地址映射时一开始用了ioremap,结果肯定是报错的。后来改成了phys_to_virt,如愿检索到了主机信息,根据不同主机成功注册了不同的rtc设备了。

在之前玩板子点灯时用到了ioremap,突然记起来好像见过这个玩意,于是就查漏补缺了一下,在这里插个眼,方便传送。

原因就是当时对内核空间理解的不熟,假设时32位的机器,内存最大寻址时4G。Linux内核将4G的虚拟地址分为0-3G的用户空间和3-4G的内核空间。

phys_to_virt是操作的是图中的896MB的线性地址,而ioremap则是将实际的io物理地址映射到图中highmemory中去。虚拟地址中,内核是从3G到4G的,而内核实际使用的物理地址却是从0-1G

#define__phys_to_virt(x)   ((x) - PHYS_OFFSET + PAGE_OFFSET)

#definePAGE_OFFSET       (0xc0000000UL)   

一开始没理解为啥是实际映射到0-1G,后面琢磨了一下,假设你要启动一个内核用来引导系统,肯定要先把内核加载到内存吧,假设是0-4G内存,难道直接加载到3-4g的地方么?肯定是从头来,先把内存加载到内存0-1G。内核启动后,在对剩下没用的内存进行管理。而且前16MB本身就对应DMA,硬件上都写死了。

刚才提到过,ioremap将io物理地址映射到高端内存,为啥要强调io物理地址呢,因为不同架构对I/O空间有不同解释,有些架构没有I/O空间(I/O空间直接和物理内存对应),有些将IO空间独立出来,与物理内存分开管理,但是无论是哪种,可以确定的是这块功能已经写死了,只能来做IO。ioremap映射时,内部调用的时vmalloc的变种函数,分配内存块,修改内核页表,映射到设备的IO地址空间。

ioremap会调用伙伴系统么分配物理页么(vmalloc会调用)?肯定不会啊,因为对象是IO空间,和我内存有什么关系呢?只需要按页分配一段内存。

以下摘自陈学松的《深入linux内核》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值