memorylinux-kernelx86-64virtual-address-spaceaddress-space

why there are such large virtual addresses in a x86_64 kernel's memory layout


kernel's Documentation/x86/x86_64/mm.txt says:

ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory

so I assume there should not be address mappings larger than actual physical DRAM size in this region. but on a x86_64 PC with 16GB DRAM and kernel v4.2.8, I got this result from /sys/kernel/debug/kernel_page_tables:

---[ Low Kernel Mapping ]---

......

0xffff88008b3ff000-0xffff88008b400000           4K     RW                 GLB NX pte

0xffff88008b400000-0xffff8800c0000000         844M                               pmd

0xffff8800c0000000-0xffff880100000000           1G                               pud

0xffff880100000000-0xffff880400000000          12G     RW         PSE     GLB NX pud

0xffff880400000000-0xffff88043dc00000         988M     RW         PSE     GLB NX pmd

0xffff88043dc00000-0xffff88043dc25000         148K     RW                 GLB NX pte

0xffff88043dc25000-0xffff88043dc27000           8K     ro                 GLB NX pte

.......

0xffff88045c200000-0xffff88046f000000         302M     RW         PSE     GLB NX pmd

0xffff88046f000000-0xffff880480000000         272M                               pmd

0xffff880480000000-0xffff888000000000         494G                               pud

0xffff888000000000-0xffffc90000000000       66048G                               pgd

you see there is page entries with virtual address 0xffff88043dc00000, using virt_to_phys() on such virtual address will get 0x43dc00000, which is obvious illegal as it's larger than actual DRAM size (16GB is just 0x400000000).

so what's the rule with these large virtual addresses and how can I get the right physical address for it?

thanks a lot!


Solution

  • Your PC has not only DRAM but also ROM (nowadays, flash) and I/O memory. For backwards compatibility, parts of those must be mapped into the 20-bit and 32-bit address spaces, so the last part of the RAM ends up at some address above 0x400000000.