0

Intel System Programming manual vol. 3 clearly documents that 4-level paging uses the first 48 bits of the virtual address to get the actual physical address.

When connecting to the Linux Kernel with GDB I found out that Kernel space addresses have higher bits (48-63) all set to some non zero values. Example:

(gdb) x/g 0xffffffff812eccc0
0xffffffff812eccc0 <get_page_from_freelist>:

How does this virtual address get translated to a physical address? Intel SDM Vol.3 clearly says that only the first 48-bits are used.

I found High memory wiki page describing a memory layout which is defined as

High memory is the part of physical memory in a computer which is not directly mapped by the page tables of its operating system kernel.

And this makes things even more unclear. How can a virtual address be translated without a page table for CPU running in Protected Mode?

Searching for "high memory" in Intel SDM Vol.3 did not give a lot of results.

Some Name
  • 8,555
  • 5
  • 27
  • 77
  • The high 16 bit indicate if you are in kernel or user space. They are not used for the page translation as far as I know. – fuz Jun 27 '22 at 20:16
  • @fuz Trying to throw them away produces wrong address which cannot be accessed in GDB. Example: `(gdb) x/g 0x812eccc00000` results in `0x812eccc00000: Cannot access memory at address 0x812eccc00000` – Some Name Jun 27 '22 at 20:21
  • @fuz Didn't find any official documentation related to your point, but that would make sense... – Some Name Jun 27 '22 at 20:24
  • The keyword to look for is “canonical address.” The highest 17 bit of the address must be identical in 64 bit mode using 48 bit (4 level) paging. The upper half of the address space created thus is used for kernel space (supervisor mode), the lower half for user space (user mode). – fuz Jun 27 '22 at 20:46
  • 2
    @fuz The key point that I didn't catch in the manual is _the processor enforces canonicality, meaning that the upper bits of such an address are identical_, not just zeroes. – Some Name Jun 27 '22 at 21:19
  • @_The high 16 bit indicate if you are in kernel or user space_ Did I get you right that it's enforced by the Kernel itself, not by the hardware? – Some Name Jun 27 '22 at 21:58
  • 2
    Yes, correct. Each page can have its own access rights, it's merely convention to put the kernel space up there. – fuz Jun 27 '22 at 22:03
  • @fuz Thanks much. Now that's perfectly clear. – Some Name Jun 27 '22 at 22:07
  • @fuz: It's really bit #47 (the top of the low 48) that indicates kernel vs. user. The high 16 bits are just copies of it. (Unless you have a sapphire rapids CPU with the LAM feature, Linear Address Masking, then yeah, the top bit has to match bit #47 or #56. https://software.intel.com/content/dam/develop/external/us/en/documents-tps/architecture-instruction-set-extensions-programming-reference.pdf) So I guess you could say the high bit is the significant one even without LAM, and bits down to #47 have to be copies of it. Fun fact: some LAM control bits assume high-half = kernel. – Peter Cordes Jun 28 '22 at 01:49
  • @PeterCordes Interesting. Where is that documented? I was not able to find details on that in the manual. Doesn't the ring indicate that? And each page can be configured as a user or supervisor page individually? – fuz Jun 28 '22 at 02:06
  • @fuz: Yes, each page has its own U/S bit. But if you want to use LAM (so you can use tagged pointers without manually redoing sign extension), see chapter 14 of the future-extensions manual I linked in my last comment. There are separate enable bits for u48, u57, and supervisor, but it's not based on the current mode: *Note that the LAM identification of a pointer as user or supervisor is based solely on the value of pointer bit 63 and does not, for the purposes of LAM, depend on the CPL.* So for example you can make a `read` syscall with a tagged ptr, and copy_to_user Just Works. – Peter Cordes Jun 28 '22 at 02:18
  • @PeterCordes Ah okay, if that's a new thing with LAM I was not aware of it. Good to know! – fuz Jun 28 '22 at 02:22
  • 2
    @fuz: Yes, LAM is AFAIK the only thing in the x86-64 ISA that truly depends on kernel = high-half. Other than that it's just convention. – Peter Cordes Jun 28 '22 at 02:25

0 Answers0