Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1265794
  • 博文数量: 482
  • 博客积分: 13297
  • 博客等级: 上将
  • 技术积分: 2890
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-12 16:25
文章分类

全部博文(482)

文章存档

2012年(9)

2011年(407)

2010年(66)

分类: LINUX

2011-12-25 22:40:29

对内存的地址问题一直很疑惑:
用户虚拟地址:0-》3G
物理地址:是CPU和MM之间用的
总线地址:外围设备和MM之间用的。IOMMU
KERNEL 逻辑地址:与物理地址相差3G
KERNEL 虚拟地址:3G-》4G
以上请大家指出错误。。呵呵:)
什么是高端内存啊?是物理内存大于896M的?

那么高端内存怎么隐射到虚拟内存上啊?

KERNEL无法操作没有映射到KERNEL虚拟地址上的内存?

PCI内存映射到哪?为什么不能用nopage对PCI内存操作?

对设备内存的引用通常不能被cached?我的理解是:控制信息不能CACHED,防止被优化,那么数据呢?
还有边际效应到底是什么啊?

比较杂,刚学,请大家指教。。:)

ypxing 发表于 2010-4-7 20:35

多看看操作系统,组成原理方面的书吧




[quote]原帖由 [i]3040602024[/i] 于 2007-9-5 20:28 发表 对内存的地址问题一直很疑惑:
用户虚拟地址:0-》3G
物理地址:是CPU和MM之间用的
总线地址:外围设备和MM之间用的。IOMMU
KERNEL 逻辑地址:与物理地址相差3G
KERNEL 虚拟地址:3G-》4G
以上请大家指出 ... [/quote]

3040602024 发表于 2010-4-7 22:32

就是没怎么看理解所以大家讨论一下嘛

塑料袋 发表于 2010-4-8 00:29

用户虚拟地址:0-》3G
物理地址:是CPU和MM之间用的
总线地址:外围设备和MM之间用的。IOMMU
KERNEL 逻辑地址:与物理地址相差3G
KERNEL 虚拟地址:3G-》4G
以上请大家指出错误。。呵呵

指不出来什么错误,不过物理地址和总线地址那两句,没太看明白什么意思.其他无问题.


什么是高端内存啊?是物理内存大于896M的?


那么高端内存怎么隐射到虚拟内存上啊?
[4G - 8M,4G - 4M ] 这段,共1024个pte项,同时还有一个数组unsigned char xxx [ 1024 ].
大于896M的page, 当前是否已经影射到了核态,由page -> virtual 决定.
有数值就是影射到了核态,这个数值就是virt_addr;
无数值就是未影射到核态,kmap会在在[4G - 8M,4G - 4M ]中随便找一个空pte项,影射到page,.同时填写page -> virtual,同时unsigned char xxx [ 1024 ] 数组中对应元素记1.哪个进程需要使用这个临时影射,就将unsigned char xxx [ 1024 ] 数组中对应元素+1,表示这个临时影射多了一个用户.
相反,kunmap会根据page -> virtual,找到这个pte项,将unsigned char xxx [ 1024 ] 数组中对应元素减1,减到1时表示这个临时影射未被使用,可以解除这个临时影射,也可以先这么缓存着,


KERNEL无法操作没有映射到KERNEL虚拟地址上的内存?
见高端内存的说明,kernel可以把物理地址在[0,4G]之间的任何内存,影射到kernel的虚拟地址上

PCI内存映射到哪?为什么不能用nopage对PCI内存操作?
PCI内存影射到[ 3G + 896M, 4G-8M] 之间,
nopage????如果PCI是个块设备,你可以将它打开后,影射到内存,缺页就调用nopage;不过对于PCI设备上那些控制用的寄存器,什么设备也一样,只能ioremap.

对设备内存的引用通常不能被cached?我的理解是:控制信息不能CACHED,防止被优化,那么数据呢?
这个没太看明白,你是说将memory作为文件打开?


还有边际效应到底是什么啊?
这个没听说过.

augustusqing 发表于 2010-4-8 02:27

站在CPU立场,物理地址和总线地址没区别,如某个PCI设备枚举后,其总线地址就是CPU的物理地址,因为可以把RAM当成一个PCI从设备

PCI内存映射到哪?为什么不能用nopage对PCI内存操作?

PCI内存要用到时map到内核虚拟地址空间,用完后要unmap掉,不能用nopage,是因为它的内存再内存中就没有建立page结构,拿什么让nopage返回了(白云奉献给蓝天,我拿什么奉献给你,我的nopage。。。。。。),非要用nopage方法的话,你可以尝试自己建一个page结构,再把它添加到全局page数组合适位置,再返回给nopage

对设备内存的引用通常不能被cached?我的理解是:控制信息不能CACHED,防止被优化,那么数据呢?
还有边际效应到底是什么啊?

设备内存中的数据相对设备来说是会频繁变化的,所以不cache,如果你确定某个设备的数据内存是很长时间恒定不变的,那你可以强行设置该区域为cachable
边际效应值得就是设备内存的特性,比如说有些寄存器,读出来就自动清零了

以上纯属个人理解,被误导莫怪俺,:)

[[i] 本帖最后由 augustusqing 于 2007-9-6 00:17 编辑 [/i]]

3040602024 发表于 2010-4-8 04:24

首先谢谢“塑料袋 “和”augustusqing“的回答。
在X86上物理地址和总线地址没区别没区别。但是别的系统结构好象不一定:设备通过DMA访问MM用的就是总线地址吧,这时候CPU就不能用总线地址访问。

还有PCI内存还是有点疑问:
LL3上说:”PCI内存被隐射到系统内存(这里是 物理内存吧?)最高端之上,因此在系统内存隐射中没有这些地址的入口。因为无法返回一个指向PAGE结构的指针,SO nopage 不能用。必须用remap_page_range“

还是不太理解啊。。

3040602024 发表于 2010-4-8 06:21

还有“KERNEL无法操作没有映射到KERNEL虚拟地址上的内存?
见高端内存的说明,kernel可以把物理地址在[0,4G]之间的任何内存,影射到kernel的虚拟地址上”

物理内存大于4G呢?

塑料袋 发表于 2010-4-8 08:18

你的nopage是指的什么啊?  看上去你的意思不是指vma_area_struct -> vm_ops->nopage.

物理内存大于4G需要更换CPU,换成PAE的或者64bit的,然后重新编译kernel.不然使用不了.

zx_wing 发表于 2010-4-8 10:16

[quote]原帖由 [i]3040602024[/i] 于 2007-9-5 20:28 发表 对内存的地址问题一直很疑惑:
用户虚拟地址:0-》3G
物理地址:是CPU和MM之间用的
总线地址:外围设备和MM之间用的。IOMMU
KERNEL 逻辑地址:与物理地址相差3G
KERNEL 虚拟地址:3G-》4G
以上请大家指出 ... [/quote]
大家都说了很多了,我就说说物理地址和总线地址,以及为什么很多设备的内存不能被cache。

物理地址和总线地址的差别主要是在引入了IOMMU后。在DMA操作的时候,CPU访问的物理地址会被IOMMU再做一次转换,转换后的地址称为总线地址。在没有IOMMU的情况下,物理地址和总线地址是相等的。

为什么很多设备内存不能被cache。举个简单的例子。在有cache的情况下,cpu的很多写操作是写到cache里的,要等一段时间才会被写回到真正的内存里,这种情况称为write back。假设一个设备在产生中断后,在设备内存的里置上一个位作为中断种类,cpu响应中断是通过把该位清零,那么在有cache的情况下,cpu只是把cache里相应的位清零了,没有立刻同步到设备内存上去。那么设备就会认为cpu没有应答它而一直发中断,而在cpu看来,它已经应答了。这就是为什么mmio空间不能被cache的原因。

另外指出一些我认为lz说的不太对的地方。
1. 逻辑地址和虚拟地址不一样。逻辑地址是针对在使用段机制而言。这个时候逻辑地址加上一个基地址才是真正的虚拟地址。如果使用页机制,既所谓的flat memory,这个时候基地址为0,逻辑地址就等于虚拟地址。

2. 在x86上,pci设备的内存映射到4G-256M这段地址。在IA64上,映射到3G+512M,称为mmio空间。访问这段地址是不会产生page fault,只有在虚拟机的情况下例外。

kernel确实无法操作没映射到地址空间的内存,一个很常见的的情况就是bios保留一个块内存不让OS用,只要在e820表中不描述该段内存,OS则对它不可见(这是对x86平台说的)

zx_wing 发表于 2010-4-8 12:13

[quote]原帖由 [i]3040602024[/i] 于 2007-9-6 18:36 发表 还有“KERNEL无法操作没有映射到KERNEL虚拟地址上的内存?
见高端内存的说明,kernel可以把物理地址在[0,4G]之间的任何内存,影射到kernel的虚拟地址上”

物理内存大于4G呢? [/quote]
物理内存大于4G时,32位的x86平台(32位地址线)是不能访问到4G以上的。32位的pae平台(36位地址线),kenerl在建页表时使用8字节作为页表的pte(你可以参考intel架构手册3A卷第3章,里面有x86平台所有页表的结构)。64位平台当然不用说了。

3040602024 发表于 2010-4-8 14:10

十分感谢zx_wing  。你对LINUX的理解够深刻。。
不过可以把“2. 在x86上,pci设备的内存映射到4G-256M这段地址。在IA64上,映射到3G+512M,称为mmio空间。访问这段地址是不会产生page fault,只有在虚拟机的情况下例外。
”说得具体点吗??
PCI到底影射到哪啊?/PROC/IOMEM中的PCI是哪个啊。。

zx_wing 发表于 2010-4-8 16:07

[quote]原帖由 [i]3040602024[/i] 于 2007-9-6 22:09 发表 十分感谢zx_wing  。你对LINUX的理解够深刻。。
不过可以把“2. 在x86上,pci设备的内存映射到4G-256M这段地址。在IA64上,映射到3G+512M,称为mmio空间。访问这段地址是不会产生page fault,只有在虚拟机的情 ... [/quote]
我对PCI不是很熟,只讲讲我的理解,讲错的地方请大家更正。
一般PCI设备都有两种方式,一种是IO,一种是memory。前者我们通常称为port IO,也就是端口访问。后者我们称为memory IO,也就是mmio(memory map IO)。
PCI设备都有一个PCI configure space,对于通常的PCI设备是256个字节,PCIE是4K。在这个configure space里,会有两个或多个基地址,我们称为PCI bar。这里假设有两个基地址,一个是port IO的基地址port_addr,一个是mmio的基地址mmio_addr。那么port_addr加上一个端口号,就可以访问到设备上对应的端口。而mmio_addr加上一个偏移,就访问到设备上对应的内存。
操作系统会把PCI bar映射到一个固定的物理地址空间,这个是架构决定的,例如前面说的x86和ia64。假设的一个PCI设备有2M的内存,而mmio_addr映射到了3.8G这个地址,那么当OS访问3.8G+2M这个范围内的物理地址时,实际就是访问到了设备的上的内存。
PCI映射到哪儿,这个是BIOS决定的,在开机的时候,BIOS会扫描PCI总线并填写各个PCI设备的configure space,这个时候PCI设备的pci bar(基地址)就确定了。但它一定处于架构规定的mmio空间范围内,例如在x86上这个地址就一定在4G-256M内。

另外这些和其它的回复都是架构规定的,并非linux特有,windows遵循同样的原则。

塑料袋 发表于 2010-4-8 18:05

每个pci_dev上有两类寄存器.
一类是作为PCI设备的共性而存在,这部分只能通过一种类似于I2C的通讯方式,来访问这部分寄存器.无其他手段.
一类作为每个pci_dev的个性而存在,对应PCI网卡,PCI声卡.....这类寄存器最终会影射到内存.

开机时,BIOS先将这些个性寄存器影射到内存的物理地址上.正常情况不会再变动,kernel尽量不修改这部分寄存器在内存中的物理地址,如果修改的话,[ 256M , 4G]之间,任何未用空间皆可.就是[256M,4G] 是PCI设备的物理地址

PCI设备的驱动程序在初始化时,见缝插针,在虚拟地址[ 3G + 896M, 4G - 8M] 之间找一段虚拟地址,将这段虚拟地址影射到那部分寄存器在内存中的物理地址上.就是[3G + 896M, 4G - 8M] 是PCI设备的虚拟地址
 
====
阅读(1576) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~