Chinaunix

标题: 关于io_remap_pfn_range的疑惑~~ [打印本页]

作者: firocu    时间: 2012-09-25 21:27
标题: 关于io_remap_pfn_range的疑惑~~
今天看《深入linux设备驱动程序内核机制》,其中说道:
在x86下 io_remap_pfn_range 的 定义如下
# define io_remap_pfn_range(vma, vaddr, pfn, size, prot)      \
                  remap_pfn_range(vma, vaddr, pfn, size, prot)

也就是说 io_remap_pfn_range 和 remap_pfn_range 实质是一样的。

我的疑惑是:
io 端口空间是用in out 指令来访问的。
io 内存空间 是用mov 这样的指令访问的。

假如说在两个地址空间中各存在一块区域,都用io_remap_pfn_range,remap_pfn_range映射到用户空间。
那么当访问是如何区分出来,用哪套指令访问呢?
也就是说如何区分虚拟地址映射的那个物理地址是来自io端口空间 还是 io内存空间?

不知道说清楚没有, 求解惑~~~
作者: stephen_du    时间: 2012-09-26 11:17
回复 1# firocu


    我的疑惑是:
io 端口空间是用in out 指令来访问的。
io 内存空间 是用mov 这样的指令访问的。

假如说在两个地址空间中各存在一块区域,都用io_remap_pfn_range,remap_pfn_range映射到用户空间(这一句错误,是将IO port或者memory映射进入kernel的地址空间,从而允许从内核来访问这些资源)。

那么当访问是如何区分出来,用哪套指令访问呢?
也就是说如何区分虚拟地址映射的那个物理地址是来自io端口空间 还是 io内存空间?
答:IO port映射后的地址跟IO memory映射后的地址范围不会重叠而且IO port的映射是非cache的,IO memory应该是可以cache的(这一点不是很确定,希望理解的深的人来确认下该说法)

作者: firocu    时间: 2012-09-26 12:45
回复 2# stephen_du


Thanks for your reply~~~

    这里io_remap_pfn_range 和 remap_pfn_range都是驱动程序中 用来实现 mmap系统调用。
所以说 ,确实是映射到用户空间,供用户访问的。

我现在了解的概念是,在x86 32 位:

io port空间是 64KB,在/proc/ioports可以看到用途分布,地址范围0x0 ~ 0xFFFF。
io mem空间是4GB, /proc/iomem包含RAM 和 外设内存,的地址范围0x0 ~ 0xFFFF FFFF ,其中显示的如下

firo@snow:~$ head /proc/iomem
00000000-0000ffff : reserved
00010000-0009c3ff : System RAM
0009c400-0009ffff : reserved
000a0000-000bffff : PCI Bus 0000:00
。。。(略去其他输出)
两个地址空间的地址有重合的部分呀~~
我不知道是巧合,还是为了不和io port 空间造成冲突。iomem的前64KB 是reserved的。。。。
在x86 32下面
我知道在ioremap操作后,在io mem空间的外设的物理地址,会被映射的内核的vmalloc区域,供内核访问。
而在io prot空间的外设的物理地址通过 ioprot_map映射的进程的用户空间,实际上是没有真正建立映射(见源码,没有建立也表项),仍然需要通过in out这些指令访问io port空间。
而io_remap_pfn_range 后是真正建立了映射(建立了页表项),映射到了一个虚拟地址,而现在要访问这个虚拟地址映射的那个外设的物理地址要通过MMU。

而《深入linux 设备驱动程序内核机制》的作者说了,之所以io_remap_pfn_range 和 remap_pfn_range 等价,是因为映射的核心是MMU,而对MMU来说,无需区分映射的目标地址类型。
为什么不需要区分,毕竟io port 和iomem地址空间,地址重合了呀~~~

在ARM 32位下,没有这个io port 空间。在统一的io mem空间中外设的物理地址都是唯一的,所以不或造成迷惑。

我感觉自己理解的不对。。。有不知道错在哪里了。





作者: firocu    时间: 2012-09-26 13:30
自己想了快两天了,蛋疼死了~~总结了一下。

又看了一边mmap系统调用的函数原型,发现这根本和io port 空间没关系呀。是我想多了~~
作者: stephen_du    时间: 2012-09-26 13:37
回复 3# firocu


     这里io_remap_pfn_range 和 remap_pfn_range都是驱动程序中 用来实现 mmap系统调用。
所以说 ,确实是映射到用户空间,供用户访问的。
----------------------------------------------------------------
明白了。不过io_remap_pfn_range是在你驱动内部调用的,首先是先映射到内核的虚地址空间,然后,用户通过mmap系统调用来间接访问驱动中映射好的内核地址,
从而间接访问IO port或者IO memory。这个过程要透彻理解才能精确表述。



我现在了解的概念是,在x86 32 位:

io port空间是 64KB,在/proc/ioports可以看到用途分布,地址范围0x0 ~ 0xFFFF。
io mem空间是4GB, /proc/iomem包含RAM 和 外设内存,的地址范围0x0 ~ 0xFFFF FFFF ,其中显示的如下

firo@snow:~$ head /proc/iomem
00000000-0000ffff : reserved
00010000-0009c3ff : System RAM
0009c400-0009ffff : reserved
000a0000-000bffff : PCI Bus 0000:00
。。。(略去其他输出)
两个地址空间的地址有重合的部分呀~~
---------------------------------------------------------------
对于X86,物理上IO port以及 IO memory与内核的物理地址于不同的物理地址空间(ARM是位于同一空间的),但它们是被映射到同一个内核虚地址空间的。
你仔细看看上面的地址范围,应该不存在重复。上一地址范围的结束地址+1是下一地址范围的开始!

我不知道是巧合,还是为了不和io port 空间造成冲突。iomem的前64KB 是reserved的。。。。(似乎跟你上面问的重合问题不一致)
-------------------------------------------------------------------------
/proc/iomem 显示的应该是物理地址的区间即映射前的地址

在x86 32下面
我知道在ioremap操作后,在io mem空间的外设的物理地址,会被映射的内核的vmalloc区域,供内核访问。
而在io prot空间的外设的物理地址通过 ioprot_map映射的进程的用户空间,实际上是没有真正建立映射(见源码,没有建立也表项),仍然需要通过in out这些指令访问io port空间。
--------------------------------------------------------------------------
in/out是x86为了访问IO端口的专用指令,那是因为X86的IO port以及IO memory在物理上具有独立的地址空间(比较特殊)因此,必须有专用指令处理
作者: firocu    时间: 2012-09-26 13:44
回复 5# stephen_du


    嗯,非常感谢。

我自己在好好理解下~~~基础概念模糊呀~~呵呵




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2