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)