<?xml version="1.0" encoding="gbk"?> <rss version="2.0"><channel> <title>定阅帖子更新</title> <link>http://www.broadkey.com.cn/XML.ASP</link><description>TEAM Board - 意得法电子</description> <copyright>TEAM 2.0.5 Release</copyright><generator>TEAM Board by TEAM5.Cn Studio</generator> <ttl>30</ttl><item><link>http://www.broadkey.com.cn/Thread.asp?tid=343 </link><title>MIPS，PowerPC和ARM访问I/O方式的比较</title><author>dl11</author><pubDate>2009-12-09 10:00:12</pubDate><description><![CDATA[<font size="2">最近看了一下PowerPC（E500）的MMU部分，看了ioremap的介绍，比较有感触，所以简单比较了一下MIPS，PowerPC和ARM（这里只考虑32位版本的，MIPS64和PowerPC64不在此范围内）访问I/O的方式。首先这三种体系结构都使用存储器映射的I/O，都是32位物理地址空间（排除一些特殊的处理器，比如PowerPC E500 v2支持36位物理地址）。下面分别说明一下具体的访问方式：<br />
<br />
<font color="#ff0000">MIPS：</font><br />
由于MIPS的地址空间映射机制比较特殊，kernel在访问kseg0和kseg1段时，根本不需要经过MMU，虚拟地址直接减去一个偏移就是物理地址（虽说PowerPC和ARM看起来也是虚拟地址减一个偏移，但是实际上都是经过TLB的）。MIPS处理器一般把外设映射到虚拟地址0xA0000000-0xBFFFFFFF之间的512MB地址空间中，而且不通过Cache。所以只要知道外设的物理地址，则只需在代码中直接加上0xA0000000就是外设的虚拟地址，这样访问起来速度比较快。但是，缺点是灵活性比较差，主内存和外设都只能映射在512MB的地址空间中，限制比较多。<br />
<br />
<font color="#ff0000">PowerPC（E500）：</font><br />
对于E500来说，不管访问什么地址都是要通过MMU的。kernel启动的时候，已经把kernel的虚拟地址空间的kmalloc区域在TLB1中建立了直接映射。而访问I/O则需要通过ioremap()函数，在页表中建立虚拟地址和物理地址的映射后才能正常访问。范围一般是ioremap_base（一般是0xFE000000）到ioremap_bot。这里需要注意的是，ioremap_bot是小于ioremap_base的。而这会影响vmalloc区域的使用，这段区域是从VMALLOC_START到ioremap_bot，也就是说PowerPC的vmalloc区域是随着ioremap_bot的变化而变化的。所以PowerPC访问外设要先建立页表（在TLB0中），比较麻烦，访问速度比较慢。访问结束后要使用iounmap()撤销映射。当然PowerPC也提供另外一种访问I/O的方式&mdash;&mdash;io_block_mapping()。可以在TLB1中建立永久的块映射，最大可以到256MB，这样访问的时候就不需要调用ioremap()临时分配虚拟地址，并建立页表了。不过Linux PowerPC的maintainer并不推荐这种方式，原因是滥用io_block_mapping会破坏PowerPC内核虚拟地址空间的布局。<br />
<br />
<font color="#ff0000">ARM：</font><br />
ARM有点类似于PowerPC，访问任何地址都要通过MMU。但是ARM Linux的做法是为每一个平台定义一个静态数组standard_io_desc[]，其中定义了每一个外设的物理地址和对应的虚拟地址，这是由程序员自己根据需要分配的，一般来讲是分配在虚拟地址的高端部分，比如在0xF0000000以上，并且不与vmalloc区域重叠（对于ARM来说，vmalloc区域在kmalloc区域+8MB&mdash;&mdash;I/O区域之间，不同的平台地址不太一样）。然后调用xxx_map_io()函数建立页表，一般会根据不同设备的地址范围的大小使用1MB或者4KB的页，这样就建立了外设的物理地址和内核虚拟地址的映射关系。然后，一般还会在头文件中定义外设的各个寄存器的虚拟地址，在操作外设时就直接读写这些宏所定义的虚拟地址就可以了，不需要调用ioremap动态的建立页表。这种方法类似于PowerPC的io_block_mapping()。所以ARM访问外设的速度要比PowerPC快一点，因为省去了动态建立页表的步骤。<br />
<br />
总得来说，MIPS，PowerPC和ARM访问I/O的方式各有千秋，MIPS是速度较快，操作简单，但是灵活性较差；PowerPC是灵活性大但是速度较慢；ARM算是在二者之间取了一个平衡。</font>]]></description></item></channel></rss>