CPU地址空间

转自: http://joe.is-programmer.com/posts/17559.html
CPU地址空间
(一)地址的概念

1)物理地址:CPU地址总线 传来的地址,由硬件电路控制其具体含义。物理地址中很大一部分是留给内存条中的内存的,但也常被映射到其他存储器上  (如显存、BIOS等)。在程序指令中的虚拟地址经过段映射和页面映射后,就生成了物理地址,这个物理地址被放到CPU的地址线上。
                物理地址空间,一部分给物理RAM(内存)用,一部分给总线用,这是由硬件设计来决定的,因此在32  bits地址线的x86处理器中,物理地址空间是2的32次方,即4GB,但物理RAM一般不能上到4GB,因为还有一部分要给总线用(总线上还挂着别的  许多设备)。在PC机中,一般是把低端物理地址给RAM用,高端物理地址给总线用。
 
2 )总线地址:总线的地址线或在地址周期上产生的信 号。外设使用的是总线地址,CPU使用的是物理地址。
                物理地址与总线地址之间的关系由系统的设计决定的。在x86平台上,物理地址就是总线地址,这是因为它们共享相同的地址空间——这句话有点难理解,详见下  面的“独立编址”。在其他平台上,可能需要转换/映射。比如:CPU需要访问物理地址是0xfa000的单元 ,那么在x86平台上,会产生一个PCI总线  上对0xfa000地址的访问。因为物理地址和总线地址相同,所以凭眼睛看是不能确定这个地址是用在哪儿的,它或者在内存中,或者是某个卡上的存储单元,  甚至可能这个地址上没有对应的存储器。

3)虚拟地址:现代操作系统普遍采用虚拟内存管理(Virtual  Memory  Management)机制,这需要MMU(Memory  Management  Unit)的支持。MMU通常是CPU的一部分,如果处理器没有MMU,或者有MMU但没有启用,CPU执行单元发出的内存地址将直接传到芯片引脚上,被  内存芯片(物理内存)接收,这称为物理地址(Physical  Address),如果处理器启用了MMU,CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual  Address),而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将虚拟地址映射成物理地址。
                Linux中,进程的4GB(虚拟)内存分为用户空间、内核空间。用户空间分布为0~3GB(即PAGE_OFFSET,在0X86中它等于  0xC0000000)
,剩下的1G为内核空间。程序员只能使用虚拟地址。系统中每个进程有各自的私有用户空间(0~3G),这个空间对系统中的其他进程是不可见的。
                CPU发出取指令请求时的地址是当前上下文的虚拟地址,MMU再从页表中找到这个虚拟地址的物理地址,完成取指。同样读取数据的也是虚拟地址,比如mov  ax,  var.  编译时var就是一个虚拟地址,也是通过MMU从也表中来找到物理地址,再产生总线时序,完成取数据的。


(二)编址方式
1)外设都是通过读写设备上的寄存器来进行的,外设寄存器也称为“I/O端口”,而IO端口有两种编址方式:独立编址和统一编制。

                统一编址:外设接口中的IO寄存器(即IO端口)与主存单元一样看待,每个端口占用一个存储单元的地址,将主存的一部分划出来用作IO地址空间,如,在  PDP-11中,把最高的4K主存作为IO设备寄存器地址。端口占用了存储器的地址空间,使存储量容量减小。
                统一编址也称为“I/O内存”方式,外设寄存器位于“内存空间”(很多外设有自己的内存、缓冲区,外设的寄存器和内存统称“I/O空间”)。
                如,Samsung的S3C2440,是32位ARM处理器,它的4GB地址空间被外设、RAM等瓜分:
0x8000  1000        LED  8*8点阵的地址
0x4800  0000  0x6000  0000    SFR(特殊暂存器)地址空间
0x3800  1002      键盘地址
0x3000  0000  0x3400  0000    SDRAM空间 
0x2000  0020  0x2000  002e    IDE
0x1900  0300      CS8900

                独立编址(单独编址):IO地址与存储地址分开独立编址,I/0端口地址不占用存储空间的地址范围,这样,在系统中就存在了另一种与存储地址无关的IO地  址,CPU也必须具有专用与输入输出操作的IO指令(IN、OUT等)和控制逻辑。独立编址下,地址总线上过来一个地址,设备不知道是给IO端口的、还是  给存储器的,于是处理器通过MEMR/MEMW和IOR/IOW两组控制信号来实现对I/O端口和存储器的不同寻址。 如,intel  80x86就采用单独编址,CPU内存和I/O是一起编址的,就是说内存一部分的地址和I/O地址是重叠的。
                独立编址也称为“I/O端口”方式,外设寄存器位于“I/O(地址)空间”。
                对于x86架构来说,通过IN/OUT指令访问。PC架构一共有65536个8bit的I/O端口,组成64K个I/O地址空间,编号从  0~0xFFFF,有16位,80x86用低16位地址线A0-A15来寻址。连续两个8bit的端口可以组成一个16bit的端口,连续4个组成一个  32bit的端口。I/O地址空间和CPU的物理地址空间是两个不同的概念,例如I/O地址空间为64K,一个32bit的CPU物理地址空间是4G。  如,在Intel  8086+Redhat9.0  下用“more  /proc/ioports”可看到:
0000-001f  dma1
0020-003f  pic1
0040-005f  timer
0060-006f  keyboard
0070-007f  rtc
0080-008f  dma  page  reg
00a0-00bf  pic2
00c0-00df  dma2
00f0-00ff  fpu
0170-0177  ide1
……

                不过Intel  x86平台普通使用了名为内存映射(MMIO)的技术,该技术是PCI规范的一部分,IO设备端口被映射到内存空间,映射后,CPU访问IO端口就如同访  问内存一样。看Intel  TA  719文档给出的x86/x64系统典型内存地址分配表:
系统资源    占用
------------------------------------------------------------------------
BIOS    1M
本地APIC    4K
芯片组保留  2M
IO  APIC    4K
PCI设备    256M
PCI  Express设备  256M
PCI设备(可选)  256M
显示帧缓存  16M
TSEG    1M


                对于某一既定的系统,它要么是独立编址、要么是统一编址,具体采用哪一种则取决于CPU的体系结构。  如,PowerPC、m68k等采用统一编址,而X86等则采用独立编址,存在IO空间的概念。目前,大多数嵌入式微控制器如ARM、PowerPC等并  不提供I/O空间,仅有内存空间,可直接用地址、指针访问。但对于Linux内核而言,它可能用于不同的CPU,所以它必须都要考虑这两种方式,于是它采  用一种新的方法,将基于I/O映射方式的或内存映射方式的I/O端口通称为“I/O区域”(I/O  region),不论你采用哪种方式,都要先申请IO区域: request_resource(),结束时释放  它:release_resource()。
 

2)对外设的访问

1、访问I/O内存的流程是:request_mem_region()  ->  ioremap()  ->  ioread8()/iowrite8()  ->  iounmap()  ->  release_mem_region() 
                前面说过,IO内存是统一编址下的概念,对于统一编址,IO地址空间是物理主存的一部分,对于编程而言,我们只能操作虚拟内存,所以,访问的第一步就是要把设备所处的物理地址映射到虚拟地址,Linux2.6下用ioremap():
                void  *ioremap(unsigned  long  offset,  unsigned  long  size);
然后,我们可以直接通过指针来访问这些地址,但是也可以用Linux内核的一组函数来读写:
ioread8(),  iowrite16(),  ioread8_rep(),  iowrite8_rep()......

2、访问I/O端口
                访问IO端口有2种途径:I/O映射方式(I/O-mapped)、内存映射方式(Memory-mapped)。前一种途径不映射到内存空间,直接使用  intb()/outb()之类的函数来读写IO端口;后一种MMIO是先把IO端口映射到IO内存(“内存空间”),再使用访问IO内存的函数来访问  IO端口。
                void  ioport_map(unsigned  long  port,  unsigned  int  count);
通过这个函数,可以把port开始的count个连续的IO端口映射为一段“内存空间”,然后就可以在其返回的地址是像访问IO内存一样访问这些IO端口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值