28

The following image shows how a 32-bit process virtual address space is divided:

enter image description here

But how a 64-bit process virtual address space is divided?

Christopher
  • 441
  • 1
  • 4
  • 5
  • 2
    The image is not correct. Depending on Linux kernel version you can have a different split ratio. Older kernels can use 1/3, 2/2 or 3/1 split, specifying by the CONFIG_VMSPLIT_ options; and since 2007 you can also select fractional splits like 5/16ths and 15/32ths. If you modify some #defines you can even have arbitrary splits. Nowadays systems affected by Meltdown typically use 4/4 split, i.e. completely separate kernel and user address spaces – phuclv Sep 15 '21 at 11:20

1 Answers1

31

x86

The 64-bit x86 virtual memory map splits the address space into two: the lower section (with the top bit set to 0) is user-space, the upper section (with the top bit set to 1) is kernel-space. (Note that x86-64 defines “canonical” “lower half” and “higher half” addresses, with a number of bits effectively limited to 48 or 57; see Wikipedia or the Intel SDM, volume 3 section 4.5, for details.)

The complete map is documented in detail in the kernel; currently it looks like

Start addr Offset End addr Size VM area description
0000_0000_0000_0000 0 0000_7fff_ffff_ffff  128 TiB user-space virtual memory
0000_8000_0000_0000 +128 TiB ffff_7fff_ffff_ffff ~16M TiB non-canonical
ffff_8000_0000_0000 -128 TiB ffff_ffff_ffff_ffff  128 TiB kernel-space virtual memory

with 48-bit virtual addresses. The 57-bit variant has the same structure, with 64 PiB of usable address space on either side of a 16K PiB hole:

Start addr Offset End addr Size VM area description
0000_0000_0000_0000 0 00ff_ffff_ffff_ffff  64 PiB user-space virtual memory
0100_0000_0000_0000 +64 PiB feff_ffff_ffff_ffff ~16K PiB non-canonical
ff00_0000_0000_0000 -64 PiB ffff_ffff_ffff_ffff  64 PiB kernel-space virtual memory

(Note that 16K PiB = 16M TiB = 264 bytes. The vast majority of the available address space is non-canonical.)

Both of these layouts provide access to the same physical address space, using 52 address lines (4 PiB). 4-level paging only provides access to a 256 TiB subset at any given time; 5-level paging provides access to the full physical address space. Current x86 CPUs can handle far less than this; as far as I’m aware, the most a single socket CPU can handle is 6TiB.

Unlike the 32-bit case, the “64-bit” memory map is a direct reflection of hardware constraints.

ARM

64-bit ARM has a similar address distinction in hardware: the top twelve or sixteen bits are 0 for user-space, 1 for kernel-space. Linux uses 39, 42 or 48 bits for virtual addresses, depending on the number of page table levels and the page size. With ARMv8.2-LVA, another four bits are added, resulting in 52-bit virtual addresses.

This is also documented in detail in the kernel.

jeanggi90
  • 103
Stephen Kitt
  • 434,908
  • Would you please explain more of the 52 address lines of x86? Maybe I am misunderstood but I think 48 address lines are composited from 9-bit of 512 page entries x 4 levels + 12-bit of 4KiB frame offset. – sandthorn Nov 28 '22 at 08:02
  • 1
    @sandthorn there’s a detailed explanation in the SDM, section 4.5, see the link at the end of the first paragraph. See also SDM section 4.1.4 to determine the maximum physical and linear address widths supported by the CPU. – Stephen Kitt Nov 28 '22 at 08:36
  • I wonder why AAarch64 call its scheme 48-bit and 52-bit. In fact, it should call 49 and 53 bit respectively because you can't distinguish user and kernel space if not refer to 49th and 53rd bit. Moreover they are 512 TB and 8 PB space, not 256 TB and 4 PB space like in 48-bit and 52-bit respectively. – sandthorn Nov 28 '22 at 09:02