编写设备驱动程序时linux中__iomem的用途是什么? [英] What is the use of __iomem in linux while writing device drivers?

查看:230
本文介绍了编写设备驱动程序时linux中__iomem的用途是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到__iomem用于存储ioremap()的返回类型,但是我在ARM体系结构中使用了u32,并且效果很好.

I have seen that __iomem is used to store the return type of ioremap(), but I have used u32 in ARM architecture for it and it works well.

那么__iomem在这里有什么不同?在什么情况下我应该使用它呢?

So what difference does __iomem make here? And in which circumstances should I use it exactly?

推荐答案

很多类型转换都只是工作得很好".但是,这不是很严格.没有什么能阻止您将u32强制转换为u32 *并取消引用,但这不遵循内核API,并且容易出错.

Lots of type casts are going to just "work well". However, this is not very strict. Nothing stops you from casting a u32 to a u32 * and dereference it, but this is not following the kernel API and is prone to errors.

__iomem Sparse 使用的cookie,该工具用于查找可能的编码错误在内核中.如果您未在启用稀疏的情况下编译内核代码,则__iomem仍将被忽略.

__iomem is a cookie used by Sparse, a tool used to find possible coding faults in the kernel. If you don't compile your kernel code with Sparse enabled, __iomem will be ignored anyway.

首先安装稀疏,然后将C=1添加到您的make调用中,以使用稀疏.例如,在构建模块时,请使用:

Use Sparse by first installing it, and then adding C=1 to your make call. For example, when building a module, use:

make -C $KPATH M=$PWD C=1 modules


__iomem的定义如下:


__iomem is defined like this:

# define __iomem        __attribute__((noderef, address_space(2)))

为所有I/O访问添加(并要求)像__iomem这样的cookie是一种更严格的方法,可以避免编程错误.您不想使用具有绝对地址的I/O内存区域进行读写操作,因为您通常使用虚拟内存.因此,

Adding (and requiring) a cookie like __iomem for all I/O accesses is a way to be stricter and avoid programming errors. You don't want to read/write from/to I/O memory regions with absolute addresses because you're usually using virtual memory. Thus,

void __iomem *ioremap(phys_addr_t offset, unsigned long size);

通常调用

以获得I/O物理地址offset的虚拟地址,并以字节为单位指定长度size. ioremap()返回带有__iomem cookie的指针,因此该现在可以与诸如readl()/writel()之类的内联函数一起使用(尽管现在最好使用更明确的宏/iowrite32()),它接受__iomem地址.

is usually called to get the virtual address of an I/O physical address offset, for a specified length size in bytes. ioremap() returns a pointer with an __iomem cookie, so this may now be used with inline functions like readl()/writel() (although it's now preferable to use the more explicit macros ioread32()/iowrite32(), for example), which accept __iomem addresses.

此外,稀疏使用noderef属性来确保您不取消引用__iomem指针.取消引用应该在某些I/O确实是内存映射的体系结构上起作用,但是其他体系结构使用特殊的指令来访问I/O,在这种情况下,取消引用将不起作用.

Also, the noderef attribute is used by Sparse to make sure you don't dereference an __iomem pointer. Dereferencing should work on some architecture where the I/O is really memory-mapped, but other architectures use special instructions for accessing I/Os and in this case, dereferencing won't work.

让我们看一个例子:

void *io = ioremap(42, 4);

稀疏不开心:

warning: incorrect type in initializer (different address spaces)
    expected void *io
    got void [noderef] <asn:2>*

或者:

u32 __iomem* io = ioremap(42, 4);
pr_info("%x\n", *io);

稀疏也不高兴:

warning: dereference of noderef expression

在最后一个示例中,第一行是正确的,因为ioremap()将其值返回给__iomem变量.但是后来,我们顺从了,我们不应该这样做.

In the last example, the first line is correct, because ioremap() returns its value to an __iomem variable. But then, we deference it, and we're not supposed to.

这使稀疏快乐:

void __iomem* io = ioremap(42, 4);
pr_info("%x\n", ioread32(io));

底线:请始终在需要时使用__iomem(作为返回类型或参数类型),并使用Sparse来确保已这样做.另外:请勿取消引用__iomem指针.

Bottom line: always use __iomem where it's required (as a return type or as a parameter type), and use Sparse to make sure you did so. Also: do not dereference an __iomem pointer.

编辑:这是关于 LWN文章的精彩文章. c0>并使用它.

Edit: Here's a great LWN article about the inception of __iomem and functions using it.

这篇关于编写设备驱动程序时linux中__iomem的用途是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆