最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

驱动代码中__iomem的解析

XAMPP相关 admin 147浏览 0评论

内核代码中充斥着大量的__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__ */

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

END

转载请注明:XAMPP中文组官网 » 驱动代码中__iomem的解析

您必须 登录 才能发表评论!