io_mapping 函数

API

linux/io-mapping.h 中的 io_mapping 函数提供了一种抽象,用于将 I/O 设备的小区域高效地映射到 CPU。 最初的用途是支持 32 位处理器上的大型图形孔径,其中 ioremap_wc 不能用于静态地将整个孔径映射到 CPU,因为它会消耗过多的内核地址空间。

映射对象在驱动程序初始化期间使用以下代码创建:

struct io_mapping *io_mapping_create_wc(unsigned long base,
                                        unsigned long size)

“base”是要使其可映射的区域的总线地址,而“size”表示要启用的映射区域的大小。两者都以字节为单位。

此 _wc 变体提供了一个只能与 io_mapping_map_atomic_wc()、io_mapping_map_local_wc() 或 io_mapping_map_wc() 一起使用的映射。

有了这个映射对象,可以根据需要临时或长期映射单个页面。 当然,临时映射效率更高。 它们有两种形式:

void *io_mapping_map_local_wc(struct io_mapping *mapping,
                              unsigned long offset)

void *io_mapping_map_atomic_wc(struct io_mapping *mapping,
                               unsigned long offset)

“offset”是定义的映射区域内的偏移量。访问超出创建函数中指定的区域的地址会产生未定义的结果。 使用未按页面对齐的偏移量会产生未定义的结果。 返回值指向 CPU 地址空间中的单个页面。

此 _wc 变体返回页面的写合并映射,并且只能与由 io_mapping_create_wc() 创建的映射一起使用。

临时映射仅在调用者的上下文中有效。 不保证该映射是全局可见的。

io_mapping_map_local_wc() 在 X86 32 位上具有副作用,因为它会禁用迁移以使映射代码正常工作。 没有调用者可以依赖此副作用。

io_mapping_map_atomic_wc() 具有禁用抢占和页面错误的副作用。 不要在新代码中使用。 请改用 io_mapping_map_local_wc()。

嵌套映射需要按相反的顺序撤消,因为映射代码使用堆栈来跟踪它们

addr1 = io_mapping_map_local_wc(map1, offset1);
addr2 = io_mapping_map_local_wc(map2, offset2);
...
io_mapping_unmap_local(addr2);
io_mapping_unmap_local(addr1);

映射使用以下命令释放:

void io_mapping_unmap_local(void *vaddr)
void io_mapping_unmap_atomic(void *vaddr)

“vaddr”必须是上次 io_mapping_map_local_wc() 或 io_mapping_map_atomic_wc() 调用返回的值。 这将取消映射指定的映射并撤消映射函数的副作用。

如果您需要在保持映射时休眠,则可以使用常规变体,尽管这可能会慢得多

void *io_mapping_map_wc(struct io_mapping *mapping,
                        unsigned long offset)

它的工作方式与 io_mapping_map_atomic/local_wc() 类似,但它没有副作用,并且指针是全局可见的。

映射使用以下命令释放:

void io_mapping_unmap(void *vaddr)

用于使用 io_mapping_map_wc() 映射的页面。

在驱动程序关闭时,必须释放 io_mapping 对象

void io_mapping_free(struct io_mapping *mapping)