首页 > 系统相关 >Linux内核中__iomem的解析

Linux内核中__iomem的解析

时间:2024-10-18 11:10:04浏览次数:1  
标签:__ attribute iomem dev Linux void define

内核代码中充斥着大量的__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);
	else
		pretty_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总线地址空间来访问寄存器的。

标签:__,attribute,iomem,dev,Linux,void,define
From: https://www.cnblogs.com/linhaostudy/p/18473889

相关文章

  • 关于计算机系统中的Cache地址映射方式
    错题考查的知识点是关于计算机系统中的Cache地址映射方式。具体来说,是关于全相联映像、直接映像和组相联映像这三种Cache地址映射方法的比较,特别是它们在块冲突次数上的差异。Cache地址映射方式Cache存储器是计算机系统中的一个高速存储器,用于减少CPU访问主存时的平均等待时间。......
  • 计量经济学(九)——向量自回归VAR模型检验
    向量自回归(VAR,VectorAutoregression)模型是一种广泛用于时间序列分析的统计工具,特别是在经济学和金融学领域中。VAR模型的关键优势在于其可以捕捉多个变量之间的相互依赖关系,而无需预设变量之间的因果顺序。这使得VAR模型在处理复杂动态系统时极具灵活性。VAR模型的基本结构是将......
  • 20222407 2024-2025-1 《网络与系统攻防技术》实验二实验报告
    1.实验内容本次实验主要围绕渗透测试与远程执行控制展开,通过不同工具和技术手段实现了对目标主机的深入渗透与监控。实验内容可以概括为以下几个方面:1.远程Shell获取:实验首先通过netcat和cron定时任务,以及socat与Windows任务计划相结合的方式,实现了对目标主机的远程Shell访问。这......
  • GCM
    GaloisCounterMode(GCM)运算符与函数$0^s$包含了$s$个$0$的比特串。$\mbox{CIPH}_K⁡(X)$在密钥$K$下对分组$X$应用分组密码得到的输出。$\mbox{GCTR}_K⁡(ICB,X)$在密钥K下对包含初始组计数$ICB$的比特串X应用包含给定分组加密的$\mbox{GCTR}$函数的输出。$\m......
  • 京准 卫星时钟“安全卫士”:卫星时空安全隔离防护装置
    京准卫星时钟“安全卫士”:卫星时空安全隔离防护装置京准卫星时钟“安全卫士”:卫星时空安全隔离防护装置京准电子科技官微——ahjzsz当前,我国电力系统普遍采用北斗卫星或者GPS卫星授时来实现时间同步,但不加防护的授时装置存在卫星信号被干扰或欺骗的风险。卫星时空安全隔离装......
  • 数据结构
    Lua数据类型Lua是动态类型语言,变量不要类型定义,只需要为变量赋值。值可以存储在变量中,作为参数传递或结果返回。Lua中有8个基本类型分别为:nil、boolean、number、string、userdata、function、thread和table。数据类型描述nil这个最简单,只有值nil属于该类,表示一个无......
  • 连接人与艺术 华为平板从生产力到创作力的跃迁
    以“共绘自然”为主题的2024天生会画数字创作大赛,正在如火如荼地进行。华为平板正在吸引全球越来越多的用户拿起画笔,通过数字绘画捕捉、创作世界独特的美。以前,提到专业创作力大家往往想到的只有苹果的Procreate,而今天华为平板在创作方面的能力已经被众多专业人士认可,在很多专业......
  • 条件
    Lua条件语句Lua编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为true时执行指定程序代码,在条件为false时执行其他指定代码。实例--[0为true]if(0)thenprint("0为true")end以上代码输出结果为:0为trueLua提供了以下控制结构语句......
  • 方法
    Lua函数(方法)在Lua中,函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。Lua提供了许多的内建函数,你可以很方便的在程序中调用它们,如print()函数可以将传入的参数打印在控制台上。Lua函数主要有两种用途:完成指定的任务,这种情况......
  • table
    Luatable(表)table是Lua的一种数据结构用来帮助我们创建不同的数据类型,如:数组、字典等。Luatable使用关联型数组,你可以用任意类型的值来作数组的索引,但这个值不能是nil。Luatable是不固定大小的,你可以根据自己需要进行扩容。Lua也是通过table来解决模块(module)、......