Skip to content

Long Mode

Long mode is the 64-bit mode x86-64 processors add on top of everything protected mode already provides, extending general-purpose registers, virtual addresses, and instruction encoding to 64 bits. Unlike every prior mode transition, entering long mode has a precondition none of the earlier ones did: paging must already be active, with PAE enabled, before the CPU will permit the transition at all; long mode has no non-paged form to fall back to.

Every general-purpose register grows to 64 bits and gains an R-prefixed name (RAX through R15, including eight entirely new registers with no 32-bit-era equivalent, R8 through R15). Virtual addresses grow to 64 bits as well, though current hardware only implements 48 usable bits of that space by default (57 with the optional LA57 extension), requiring the unused upper bits to be a sign-extension of the highest implemented bit (a canonical address), or the CPU raises a fault rather than silently truncating. Segmentation, central to protected mode’s protection model, becomes largely vestigial: segment base and limit are ignored for most segments under long mode, with the CPU instead relying entirely on paging for memory protection, though segment selectors are still loaded and still carry the privilege-level information a ring transition depends on.

Long mode’s own availability is never assumed; it is checked ahead of time via CPUID’s extended leaf 0x80000001, whose EDX bit 29 (the LM bit) reports whether the CPU implements the mode at all, before any of the sequence below is attempted. Three conditions must all hold before the transition instruction sequence will succeed: PAE (Physical Address Extension, CR4 bit 5) must be enabled, since long mode’s page table format is PAE’s format extended with an additional table level rather than an unrelated structure; a valid set of page tables must already be loaded via CR3; and paging itself, CR0’s PG bit, must not yet be set: it is the very last step of the sequence, not a precondition satisfied earlier, since setting it is what actually completes the transition.

The sequence, executed from protected mode, is a fixed order of operations:

; 1. Enable PAE
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; 2. Load CR3 with a PML4 table already populated with at least
; identity-mapped entries covering the currently executing code
mov eax, pml4_table
mov cr3, eax
; 3. Set the long-mode-enable bit in the EFER MSR
mov ecx, 0xC0000080 ; IA32_EFER
rdmsr
or eax, 1 << 8 ; LME
wrmsr
; 4. Enable paging — this actually activates long mode
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
; 5. Far jump into a 64-bit code segment to complete the transition
jmp CODE_SEG_64:long_mode_entry

Setting CR0.PG at step 4 places the CPU in a transitional state called compatibility mode rather than full 64-bit mode directly: the final far jump at step 5, into a GDT code descriptor with its long-mode bit set, is still required to reach genuine 64-bit execution, mirroring the same “set the control bit, then far-jump to flush the pipeline” pattern the real-to-protected transition uses.

Beyond that brief transitional window, compatibility mode also persists as a selectable, ongoing state: a long-mode kernel can run 32-bit or 16-bit application code essentially unmodified by loading a compatibility-mode code segment for it, letting existing 32-bit userspace binaries run under a 64-bit kernel without recompilation. The kernel itself, however, always executes as genuine 64-bit code once fully transitioned; compatibility mode is a userspace-facing accommodation, not a mode the kernel’s own code runs in.

Because long mode requires paging active as a precondition, and the instruction pointer must remain valid throughout the transition, the page tables loaded before setting CR0.PG must identity-map (virtual address equals physical address) whatever code is currently executing: jumping straight into paging with a table that doesn’t cover the running code’s own address produces an immediate fault on the very next instruction fetch, before the CPU has any usable interrupt-handling infrastructure to report it cleanly. Many kernels handle this by identity-mapping the lowest few megabytes of physical memory temporarily during the transition, then switching to a fully correct set of mappings (including a higher-half kernel mapping, if used) once safely in 64-bit mode with proper exception handling available.

  1. ^ AMD, AMD64 Architecture Programmer’s Manual, Volume 2, Chapter 14: the original specification of the long-mode transition sequence and prerequisites.
  2. ^ Intel, Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A, Chapter 9: the corresponding Intel-side description of IA-32e mode entry.
  • Paging & Virtual Memory: the page table format long mode requires as a precondition.
  • Protected Mode: the mode long mode’s transition sequence starts from.
  • CPUID: the instruction and extended leaf that reports whether long mode is available at all.
  • Model-Specific Registers: the RDMSR/WRMSR mechanism behind the EFER register this transition writes.