在《Linux内存地址映射》(http://ilinuxkernel.com/?p=1276),详细介绍了在32位x86 CPU中Linux内核地址映射过程,并且给出实验验证整个地址映射过程。
64位CPU中,地址映射稍微复杂,本文介绍Linux内核在x86_64 CPU中地址映射过程,同样给出实验和源码,验证整个地址映射过程。
完整文档下载地址:Linux内核在x86_64 CPU中地址映射
实验源码下载地址:Memory_Address_Mapping_x86-64
在《Linux内存地址映射》(http://ilinuxkernel.com/?p=1276),详细介绍了在32位x86 CPU中Linux内核地址映射过程,并且给出实验验证整个地址映射过程。
64位CPU中,地址映射稍微复杂,本文介绍Linux内核在x86_64 CPU中地址映射过程,同样给出实验和源码,验证整个地址映射过程。
完整文档下载地址:Linux内核在x86_64 CPU中地址映射
实验源码下载地址:Memory_Address_Mapping_x86-64
EvoLve theme by Theme4Press • Powered by WordPress Intelligent Computing Architecture
Research & Innovation
Subscribe now to keep reading and get access to the full archive.
hi,你好!内存映射系列文章写的很不错,我正在做《Linux内核在x86_64 CPU中地址映射》的实验,没做通,使用的内核是3.11.3-201.fc19.x86_64。发现一个问题,GDTR寄存器的地址是0xffff88019bcca000,使用__pa()接口将其转化为物理地址为0x19bcca000,但是使用FILEVIEW工具查看,发现超出了物理内存的大小(总共5.6GBytes),那么是否着内存的物理地址空间也是不连续的,存在空洞?我通过搜索所有的物理页发现user cs段的descriptor应该在地址0x200a030上(通过FILEVIEW),这又是怎么回事?是否是dram驱动过于老旧不适合3.0的内核?
1、实际物理内存有多大?
2、请确认一下FILEVIEW可以支持超过4GB物理内存。
1、实际物理内存5.6GBytes,两条1条2G的,1条4G的,分别插在两个插槽,总共识别5.6G
2、FILEVIEW使用了-D_LARGEFILE64_SOURCE参数(但是用与不用都能识别到5.6GBytes,gcc/g++都试过),总内存也识别到了5.6GBytes,顺序排列,但就是线性地址转物理地址的时候,超出范围,感到很奇怪,而且直接访问线性地址也对,就是转出来的物理地址用FILEVIEW查看找不对位置。
3、我考虑可能有几方面的原因1)不应该使用__pa()去转换线性地址,应直接用MMU转化2)物理地址空间在IA32e模式下不是连续的3)FILEVIEW+dram将物理内存排列错了。但感觉哪条也不对,不解啊~~
你把内核启动过程中,打印的e820图结果贴出来。
6GB物理内存,识别5.6G,最高物理地址不一定就是5.6GB,应该是大于这个值。
[rock3@e4310 ~]$ dmesg | grep e820
[ 0.000000] e820: BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x0000000000095bff] usable
[ 0.000000] BIOS-e820: [mem 0x0000000000095c00-0x000000000009ffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000000e0000-0x00000000000fffff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x00000000db65efff] usable
[ 0.000000] BIOS-e820: [mem 0x00000000db65f000-0x00000000db67efff] ACPI data
[ 0.000000] BIOS-e820: [mem 0x00000000db67f000-0x00000000db76efff] ACPI NVS
[ 0.000000] BIOS-e820: [mem 0x00000000db76f000-0x00000000dbffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000dde00000-0x00000000dfffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000f8000000-0x00000000fbffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fed10000-0x00000000fed13fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fed18000-0x00000000fed19fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fed1c000-0x00000000fed1ffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000ff800000-0x00000000ffffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000100000000-0x000000017bffffff] usable
[ 0.000000] BIOS-e820: [mem 0x000000017c000000-0x000000017fffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000180000000-0x000000019bffffff] usable
[ 0.000000] e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
[ 0.000000] e820: remove [mem 0x000a0000-0x000fffff] usable
[ 0.000000] e820: last_pfn = 0x19c000 max_arch_pfn = 0x400000000
[ 0.000000] e820: update [mem 0xdc000000-0xffffffff] usable ==> reserved
[ 0.000000] e820: last_pfn = 0xdb65f max_arch_pfn = 0x400000000
[ 0.000000] e820: [mem 0xe0000000-0xf7ffffff] available for PCI devices
[ 0.521031] e820: reserve RAM buffer [mem 0x00095c00-0x0009ffff]
[ 0.521032] e820: reserve RAM buffer [mem 0xdb65f000-0xdbffffff]
你通过__pa()获得物理地址,是正常范围。BIOS-e820: [mem 0x0000000180000000-0x000000019bffffff] usable,0x19bcca000地址在这个范围内。
请再检查一下Fileview工具是否有问题。
多谢,我想我找到原因了,确实时e820打印的物理内存地址空间是包含那个找不到的地址的,是因为我使用的是3.11版本的内核,不巧的是3.11将dram中的num_physpages边量给删除了:https://github.com/ryao/spl/commit/4773c7a10b21f2ca52cc0fd5f8c4ed263f54a245,我随手一査,给还成了totalram_pages,可totalram_pages仅仅代表所有的物理内存页的数量,并不包含PCI等各种预留地址,所以产生了“超出地址范围”的问题,改成e820打印的地址上限后,可以明确找到相关边量了!
非常感谢~~
这个是我看过最棒的地址映射的讲解,我想说谢谢你的分享
我有一个问题,create_proc_read_entry在内核4.4.15版本不存在,请问代码该怎么改