Linux内核中__iomem的解析

news/2024/10/18 11:21:29/文章来源:https://www.cnblogs.com/linhaostudy/p/18473889

内核代码中充斥着大量的__iomem修饰的void类型的指针,像下面这样:

void __iomem *devm_ioremap_resource(struct device *dev,const struct resource *res)
{resource_size_t size;void __iomem *dest_ptr;char *pretty_name;BUG_ON(!dev);if (!res || resource_type(res) != IORESOURCE_MEM) {dev_err(dev, "invalid resource\n");return IOMEM_ERR_PTR(-EINVAL);}size = resource_size(res);if (res->name)pretty_name = devm_kasprintf(dev, GFP_KERNEL, "%s %s",dev_name(dev), res->name);elsepretty_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);if (!pretty_name)return IOMEM_ERR_PTR(-ENOMEM);if (!devm_request_mem_region(dev, res->start, size, pretty_name)) {dev_err(dev, "can't request region for resource %pR\n", res);return IOMEM_ERR_PTR(-EBUSY);}dest_ptr = devm_ioremap(dev, res->start, size);if (!dest_ptr) {dev_err(dev, "ioremap failed for resource %pR\n", res);devm_release_mem_region(dev, res->start, size);dest_ptr = IOMEM_ERR_PTR(-ENOMEM);}return dest_ptr;
}

__iomem的定义位于include/linux/compiler_types.h中,规定了GCC相关的一些属性信息。

#ifdef __CHECKER__
# define __user		__attribute__((noderef, address_space(1)))
# define __kernel	__attribute__((address_space(0)))
# define __safe		__attribute__((safe))
# define __force	__attribute__((force))
# define __nocast	__attribute__((nocast))
# define __iomem	__attribute__((noderef, address_space(2)))
# define __must_hold(x)	__attribute__((context(x,1,1)))
# define __acquires(x)	__attribute__((context(x,0,1)))
# define __releases(x)	__attribute__((context(x,1,0)))
# define __acquire(x)	__context__(x,1)
# define __release(x)	__context__(x,-1)
# define __cond_lock(x,c)	((c) ? ({ __acquire(x); 1; }) : 0)
# define __percpu	__attribute__((noderef, address_space(3)))
# define __rcu		__attribute__((noderef, address_space(4)))
# define __private	__attribute__((noderef))
extern void __chk_user_ptr(const volatile void __user *);
extern void __chk_io_ptr(const volatile void __iomem *);
# define ACCESS_PRIVATE(p, member) (*((typeof((p)->member) __force *) &(p)->member))
#else /* __CHECKER__ */
# ifdef STRUCTLEAK_PLUGIN
#  define __user __attribute__((user))
# else
#  define __user
# endif
# define __kernel
# define __safe
# define __force
# define __nocast
# define __iomem
# define __chk_user_ptr(x) (void)0
# define __chk_io_ptr(x) (void)0
# define __builtin_warning(x, y...) (1)
# define __must_hold(x)
# define __acquires(x)
# define __releases(x)
# define __acquire(x) (void)0
# define __release(x) (void)0
# define __cond_lock(x,c) (c)
# define __percpu
# define __rcu
# define __private
# define ACCESS_PRIVATE(p, member) ((p)->member)
#endif /* __CHECKER__ */

这个宏定义 __iomem 是在 Linux 内核中用于标记 I/O 内存区域的。具体来说,它使用了两个 GCC 属性:

  1. __attribute__((noderef)):这个属性告诉编译器不要对标记的指针进行解引用检查。这在处理 I/O 内存时很重要,因为这些内存区域可能不遵循普通内存的访问规则。

  2. __attribute__((address_space(2))):这个属性将指针标记为属于特定的地址空间。在 Linux 内核中,地址空间 2 通常用于 I/O 内存。这有助于编译器进行更好的优化和错误检查。

__CHECKER__是与Sparse相关的一个宏开关,从kernel顶层Makefile中可以看出,当指定参数C=1或C=2时会调用Sparse。Sparse是2004年由Linus创建的kernel代码静态检查工具。

192 # Call a source code checker (by default, "sparse") as part of the
193 # C compilation.
194 #
195 # Use 'make C=1' to enable checking of only re-compiled files.
196 # Use 'make C=2' to enable checking of *all* source files, regardless
197 # of whether they are re-compiled or not.
198 #
199 # See the file "Documentation/dev-tools/sparse.rst" for more details,
200 # including where to get the "sparse" utility.

从__CHECKER__和address_space(2)这两个信息可以看出,当基于Sparse进行通过__iomem修饰的void类型指针需要落到特定地址空间,否则会吐出警告信息。

__iomem存在的意义是kernel系统同时兼容了X86和ARM等类型的处理器平台,对于这两种典型的处理器平台而言,其寄存器访问方式是完全不同的。X86架构的处理器是基于IO指令进行寄存器访问的,而ARM架构的处理器是基于真实存在的32或64位的AMBA总线地址空间来访问寄存器的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/816768.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第36篇 linux服务器上启动framework应用程序流程

framework开发的应用程序,一般是不会在linux服务器上运行的,但是我们可以通过mono进行应用部署 1.查看linux服务上是否已经安装mono-core 方式1: rpm命令查看 rpm -qa | grep mono-core有结果返回,说明已经安装方式2:使用yum list installed yum list installed | grep mo…

GCM

GaloisCounter Mode (GCM) 运算符与函数$0^s$包含了$s$个$0$的比特串。$\mbox{CIPH}_K⁡(X)$在密钥$K$下对分组$X$应用分组密码得到的输出。$\mbox{GCTR}_K⁡(ICB,X)$在密钥K下对包含初始组计数$ICB$的比特串X应用包含给定分组加密的 $\mbox{GCTR}$函数的输出。$\mbox{GHASH}_H…

音频压缩

声音压缩 压缩音频在微信上的播放效果结论:在Pc环境测试后,压缩音频在微信环境中也拥有相同表现。 码率对音质的影响设置总结 将码率设置为64k和原版几乎没有差别,压缩率35% 将码率设置到48k,仔细可以听出些许差别,在对音频要求不高的地方可以使用。 转码率工具 https://w…

创新突破!天翼云荣膺CCF HPC China 2024高性能计算创新大奖

近日,第20届CCF全国高性能计算学术年会(CCF HPC China 2024)在武汉隆重召开。CCF HPC China是全球高性能计算领域三大标志性盛会之一,本届大会以“华章廿载 新质未来”为主题,由12位院士领衔,携手来自算力领域的400多位顶尖学者,进行学术交流和专题分享。近日,第20届CC…

汽车零部件行业CRM应用数字化解决方案解析

1.行业背景与挑战分析 近年来,随着国家对新能源汽车行业的大力支持,国内汽车产业不仅在国内市场实现了弯道超车,而且新能源汽车的海外出口也开拓了新的市场,为自主品牌的新能源战略贡献了新的增长点;这一迅猛发展的趋势也带动了汽车零部件行业的增长。 同时,汽车零部件行…

gjoi 10.18

模拟赛不通知,模拟赛巨大绑包,素质有待降低。T1 向量 不难发现操作次数固定,操作其实相当于在有两位的前提下减少一位,如果和 \(\geq 10\) 花费 \(9\) 的代价加 \(1\) 位。答案肯定是 \(初始位数+额外位数-1\),现在问题是额外位数是什么,不妨设序列和为 \(sum\),额外次数…

Leetcode 721. 账户合并

1.题目基本信息 1.1.题目描述 给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails 表示该账户的邮箱地址。 现在,我们想合并这些账户。如果两个账户都有一些共同的邮箱地址,则两个账户必定属于…

网管平台(基础篇):网管系统的重要性

网管系统的核心地位:数字世界的稳定舵手 在信息技术日新月异的今天,网络如同一条无形的纽带,将世界紧密相连。然而,这条纽带背后隐藏着无数复杂的节点与链路,如何确保它们高效、稳定地运行,成为了一个亟待解决的问题。网管系统,作为数字世界的稳定舵手,以其强大的监控与…

揭秘!如何设计高可用、高性能、高扩展的异地多活系统?【转】

1 关于基础架构 2 关于异地多活 3 写时延是关键 4 写量大拆分片 5 做隔离拆分片 6 其他影响因素 7 数据复制架构 8 数据影响路由 9 架构选型模式异地多活是分布式系统架构设计的一座高峰,当业务系统走到需要考虑异地多活这一步,其体量和复杂度都会达到很高的水准。接入层、逻…

引擎模块自身占用

引擎自身中存在内存开销的部分纷繁复杂,可以说是由巨量的“微小”内存所累积起来的,比如GameObject及其各种Component(最大量的Component应该算是Transform了)、ParticleSystem、MonoScript以及各种各样的模块Manager(SceneManager、CanvasManager、PersistentManager等)……

怎样修改网站ftp密码?

修改网站FTP密码的方法取决于你使用的FTP服务提供商或Web主机控制面板。以下是一些常见情况下的步骤:通过cPanel修改FTP密码:登录到你的cPanel账户。 在文件部分找到“FTP账户”选项并点击。 选择你想要修改密码的FTP账户。 点击“更改密码”按钮。 输入新密码,并确认。 点击…