How Does Linux Direct-Map Physical Memory? – Best Linux Device Drivers Course

Direct-Mapped RAM and Kernel Logical Addresses in Linux
Free Linux Kernel Development Course — Memory Management Series
Module: Memory Management
Level: Beginner to Intermediate
Format: Free Linux Device Drivers Course

« Previous Lecture  |  Next Lecture »

This lecture continues our free Linux kernel development course and is required reading before you start the free Linux device drivers course modules on DMA buffers. We explain, in simple terms, how the kernel maps physical RAM into its own virtual address space at boot time, what a kernel logical address is, and why this matters for writing correct, portable driver code.

free linux kernel development course
free linux device drivers course
free embedded systems course
kernel logical address linux
direct mapped RAM linux

What You Will Learn

  • What direct mapping of RAM means and why the kernel does it at boot
  • What a kernel logical address is and how it differs from a kernel virtual address
  • How PAGE_OFFSET works on modern 64-bit kernels
  • Why the old 32-bit 3:1 split is mostly historical now
  • How to convert between physical addresses and kernel logical addresses safely in driver code

Prerequisites

You should already understand what a page frame is and ideally have gone through our lecture on memory zones and NUMA nodes. Basic familiarity with virtual memory concepts (virtual address vs physical address) is helpful but not mandatory.

Why the Kernel Maps RAM Directly

When the Linux kernel boots, it needs fast, simple access to most of physical RAM for its own bookkeeping — page tables, slab caches, internal data structures, and so on. Constantly setting up and tearing down temporary virtual mappings for every piece of kernel data would be slow. So instead, at boot the kernel creates one large, permanent mapping that covers essentially all usable physical RAM in one shot, placing it at a fixed, predictable location within the kernel’s portion of the virtual address space.

Because every physical page frame ends up at a virtual address that is simply the physical address plus a constant offset, this scheme is called a direct mapping, sometimes also described as a 1:1 or identity-style mapping (offset by a constant, not literally identical numbers).

Direct Mapping Concept
Physical Page Frame 0
Physical Page Frame 1
Physical Page Frame 2
→
Kernel Virtual Page 0 (+ offset)
Kernel Virtual Page 1 (+ offset)
Kernel Virtual Page 2 (+ offset)

The constant offset that connects a physical address to its directly mapped kernel virtual address is held in the kernel macro PAGE_OFFSET. Any kernel address produced this way — physical address plus PAGE_OFFSET — is what the kernel community calls a kernel logical address. The region of kernel virtual address space that holds these addresses is often called the lowmem region, a name that survives from the 32-bit era even though it can describe a very large range on 64-bit systems.

Why 32-bit and 64-bit Systems Look So Different Here

Older 32-bit x86 kernels had only 4 GB of total virtual address space to share between user space and kernel space, commonly split 3 GB for user space and 1 GB for the kernel. That tiny 1 GB kernel region was nowhere near enough to directly map systems with several gigabytes of RAM, which is exactly why the now-obsolete ZONE_HIGHMEM and temporary kmap-style mappings existed — RAM beyond what the direct mapping could cover had to be mapped in and out on demand.

On modern 64-bit kernels this constraint has essentially disappeared. A 64-bit virtual address space is enormous — far larger than any RAM configuration found in real servers or embedded boards today — so the kernel can directly map all installed physical RAM permanently, with plenty of address space left over for vmalloc, module space, and other kernel regions. This is the main reason ZONE_HIGHMEM and the manual “high memory” juggling described in older books and tutorials is largely irrelevant on current x86_64 and ARM64 systems.

32-bit Limited Direct Mapping vs 64-bit Full Direct Mapping
32-bit Kernel
~1 GB kernel space — only part of RAM directly mapped, rest needs temporary mappings
64-bit Kernel
Huge kernel space — all installed RAM directly mapped permanently

Inspecting Address Layout on a Running Kernel

On a running 64-bit system you can see a human-readable breakdown of how the kernel’s virtual address space is laid out, including the direct mapping region, by checking the kernel’s documentation file for your architecture or by reading the live memory map:

sudo cat /proc/iomem | head -20

This shows which physical address ranges are recognized as System RAM versus reserved for devices, firmware, or other purposes — the ranges that the kernel’s direct mapping logic builds on top of at boot.

Why This Matters for Driver Writers

When you allocate memory in a driver using a function from the kernel’s memory allocation APIs, the pointer you typically get back is a kernel logical address — it lives in the direct-mapped region. This matters because logical addresses have a useful property: you can convert freely between a kernel logical address and its underlying physical address using simple, fast macros, without walking page tables. This is exactly why buffers used for DMA are normally expected to come from this directly mapped region rather than from, say, vmalloc’d memory, which does not have a fixed, simple physical-to-virtual relationship.

Practical takeaway: if your driver needs a buffer to hand off to a DMA-capable device, prefer allocation functions that hand back kernel logical addresses, and use the proper conversion macros rather than assuming a fixed numeric offset, since the exact value of PAGE_OFFSET is architecture- and configuration-dependent and should never be hardcoded.

Best Practices

  • Never hardcode PAGE_OFFSET or assume a specific direct-mapping offset in driver code; always use the kernel-provided conversion helpers.
  • Remember that vmalloc memory is virtually contiguous but not necessarily physically contiguous, unlike directly mapped logical-address memory.
  • When studying older textbooks or tutorials that focus on 32-bit highmem juggling, treat that material as historical background rather than a description of how current 64-bit kernels behave.

Common Mistakes and Troubleshooting

  • Mistake: Treating “kernel virtual address” and “kernel logical address” as identical terms. Every logical address is a kernel virtual address, but not every kernel virtual address (for example, a vmalloc address) is a logical address.
  • Mistake: Assuming highmem-related code paths are still meaningfully exercised on a typical 64-bit server or embedded board.
  • Troubleshooting tip: If a DMA buffer allocation fails or behaves unexpectedly, double check whether the memory was actually obtained from the direct-mapped region versus a non-logical-address allocator.

Summary / Key Takeaways

  • The kernel direct-maps physical RAM into its own virtual address space at boot for fast, simple internal access.
  • A kernel logical address equals a physical address plus a fixed offset, PAGE_OFFSET.
  • The region holding these addresses is traditionally called lowmem, a name carried over from the 32-bit era.
  • On 64-bit kernels, the entire installed RAM is typically direct-mapped, making ZONE_HIGHMEM largely obsolete.
  • Driver code should use kernel-provided macros to convert between physical and logical addresses, never hardcoded offsets.

Conclusion

Direct mapping and kernel logical addresses are foundational concepts that explain how the kernel manages its own memory efficiently and how DMA-capable buffers are normally allocated. Understanding the historical 32-bit constraints versus the much simpler 64-bit picture will help you read both old and new kernel documentation without confusion as you progress through this free Linux kernel development course.

Frequently Asked Questions

Q1. What is a kernel logical address in Linux?
It is a kernel virtual address obtained by adding a fixed offset, PAGE_OFFSET, to a physical address, as part of the kernel’s direct mapping of RAM.

Q2. Is direct-mapped RAM the same on 32-bit and 64-bit kernels?
Conceptually yes, but practically very different. 32-bit kernels could only directly map a limited amount of RAM due to a small kernel address space, while 64-bit kernels can typically map all installed RAM directly.

Q3. Why is the term “lowmem” still used on 64-bit systems?
It is a historical name carried over from the 32-bit era, where only a “low” portion of RAM could be directly mapped. The term persists even though it can now refer to a very large region.

Q4. Can I hardcode PAGE_OFFSET in my driver?
No. PAGE_OFFSET varies by architecture and kernel configuration, so you must always use the kernel’s provided conversion macros instead of a fixed numeric value.

Q5. Is ZONE_HIGHMEM still relevant for embedded Linux development?
It is largely obsolete for current 64-bit boards, though some constrained 32-bit embedded targets may still use it.

Q6. Why do DMA buffers typically come from logical-address memory?
Because logical addresses have a simple, fixed relationship to physical addresses, making physical-to-virtual conversion fast and reliable, which is essential for DMA-capable hardware.

Q7. Where can I check the kernel’s memory map on my own system?
You can inspect /proc/iomem to see how physical address ranges are classified, including the System RAM regions the kernel direct-maps at boot.

Continue the Free Linux Kernel Development Course

Explore more lectures on memory management, device drivers, and embedded Linux at EmbeddedPathashala.

« Previous Lecture  |  Next Lecture »

Leave a Reply

Your email address will not be published. Required fields are marked *