AlgoMaster Logo

Page Faults

26 min readUpdated August 7, 2026
Listen to this chapter
Unlock Audio

A process executes:

The CPU calculates the virtual address of status and attempts a write. The MMU cannot complete the access with the current translation state. Perhaps the virtual page has not yet been given a physical frame, the page is read-only, or the pointer does not belong to any valid region.

The processor cannot guess what the operating system intended. Instead, it stops the instruction's normal execution and transfers control to the kernel through a page fault.

A page fault is a synchronous processor exception raised when a virtual-memory access cannot complete using the current mappings and permissions.

The name sounds like an error, but many page faults are expected. The operating system can resolve some faults and retry the instruction without the application noticing. Other faults reveal an invalid access and are reported to the process.

Understanding this distinction turns “page fault” from a vague crash term into a precise operating-system event.

What Can Cause a Page Fault?

A page fault begins with a particular memory operation: an instruction fetch, a load, or a store.

The MMU can fault for several broad reasons.

No usable physical frame is currently associated

The address may belong to a valid process region, but its contents are not currently available through a resident physical frame. The operating system may be able to supply the contents and create a usable mapping.

Examples include a newly used anonymous page, executable or file data not currently resident, and a page whose contents were moved to backing storage.

The requested operation is not permitted

A mapping can exist while rejecting the operation:

The physical bytes may be present. The fault occurs because the access violates hardware permissions.

No valid process region covers the address

The pointer may be null-derived, corrupted, out of range, or left behind after a region was removed. There is no valid process mapping that authorizes the access.

The operating system deliberately uses a protected state

The kernel can temporarily represent a valid higher-level operation with page-table permissions that force an exception on a specific access. A write to deliberately shared read-only state, for example, can let the kernel create private state before retrying the write.

These causes all enter through the processor's page-fault mechanism. The kernel must inspect its own address-space metadata to decide which case occurred.

Synchronous Page Faults

A page fault is tied to the instruction that attempted the memory access.

Suppose:

The faulting instruction address is 0x401250. The faulting memory address is 0x7f2000304010. They answer different questions:

The processor records enough architectural state for the kernel to identify the operation and, if appropriate, resume it.

This differs from an external hardware interrupt. A network-device interrupt can arrive between instructions and is not caused by the instruction that happened to be executing. A page fault is a direct result of the current instruction's memory access.

The fault is also precise according to the architecture's exception model. The operating system sees a defined instruction boundary and can retry the operation after resolving the condition. Modern CPUs may execute instructions internally out of order, but they present the fault to software in the architectural order required for correct recovery.

The Hardware Fault Path

Consider a memory access whose translation is either unavailable in the TLB or cached with permissions that reject the operation.

The hardware first consults the TLB. On a miss, it tries to locate a usable page-table entry. If cached permissions or the page-table walk show that the access cannot complete, the processor enters the page-fault path.

A permission violation can also be detected from a cached translation. The processor does not need to walk the page table again merely to discover that a TLB entry rejects the attempted write or execution.

When raising the exception, the hardware makes architecture-specific fault information available. Conceptually, the kernel receives:

  • The faulting virtual address
  • Whether the access was a read, write, or instruction fetch
  • Whether execution was in user or kernel mode
  • Whether the failure involved a missing translation or a protection violation
  • The saved instruction location and execution state

The CPU switches to a privileged kernel exception handler using the architecture's normal exception-entry mechanism. The faulting process has not made a system call; control entered the kernel because the processor could not complete a memory instruction.

What the Kernel Knows That the MMU Does Not

The MMU understands page-table entries and hardware permissions. It does not understand why a region exists or whether the process is allowed to grow it.

The kernel maintains higher-level descriptions of a process's virtual regions. On Linux, these are commonly called virtual memory areas, or VMAs. A VMA records properties such as:

The page table and VMA describe different levels:

A virtual address can lie inside a valid VMA even when no currently usable leaf entry maps its page. That difference is what allows many faults to be recoverable.

When a fault arrives, the kernel asks:

  1. Does a valid virtual region cover the faulting address?
  2. Does that region allow the attempted read, write, or execution?
  3. Is this a condition the region's policy allows the kernel to resolve?
  4. If so, what contents and permissions should the page receive?

The MMU reports the immediate hardware condition. The kernel supplies the meaning.

The Page-Fault Handler

The kernel's page-fault handler follows a decision process like this:

For a recoverable fault, resolution can involve one of several actions:

  • Allocate a frame and provide zero-initialized contents.
  • Associate the page with data already present in a system memory cache.
  • Read the required contents from a file or backing storage.
  • Create a private writable frame for a deliberately protected shared page.
  • Extend a permitted stack region within its configured boundary.

These are examples of policies built on the fault mechanism. The fault handler selects the correct action from the region metadata and page state.

After supplying the page, the kernel installs or updates the leaf page-table entry with the physical frame and appropriate permissions. It also ensures that stale cached translation state cannot override the new mapping.

The handler then returns from the exception. The processor retries the faulting instruction, which recalculates the same virtual address. This time translation succeeds.

Application-Transparent Page-Fault Recovery

Suppose an instruction reads:

The complete execution might be:

From the program's perspective, the load happened once. It does not receive a special “try again” return value and does not call the fault handler directly.

This transparency depends on careful processor and kernel design. The architecture defines restart behavior, and the kernel must update state so repeating the instruction is safe.

Some machine instructions can touch more than one memory location or span page boundaries. One part may be accessible while another causes a fault. The architecture defines what state is visible and how such an instruction can resume. Application code should not assume that page faults occur only at explicit source-level pointer operations.

A single high-level statement can also compile into several memory instructions, any of which can fault independently.

When the Fault Is Invalid

If the address does not belong to a valid region or the attempted operation violates that region's policy, the kernel cannot legitimately create a mapping merely to satisfy the instruction.

On Linux, an invalid user-space access commonly causes the kernel to deliver SIGSEGV to the faulting thread.

Two useful siginfo_t reason codes are:

Exact reporting depends on the architecture and the nature of the failure. Some memory-related conditions can produce SIGBUS, such as accessing a portion of a file-derived mapping for which no underlying file data exists.

The signal is not the page fault itself:

A process can install a signal handler for some signals, but that does not automatically make the invalid memory operation safe. If the handler returns without changing the condition, the same instruction can fault again.

The familiar phrase segmentation fault is the user-visible Unix response to many invalid accesses. On modern paged systems, the underlying hardware event is commonly a page-translation or page-protection fault rather than a failure of a classical segmentation mechanism.

Null-Derived and Permission Faults

The faulting address often reveals the shape of a bug.

Null-derived field access

Consider:

If request is null and status begins 24 bytes into the structure, the CPU attempts a write near:

Low virtual addresses are normally left unmapped. The kernel finds no valid region covering 0x18 and reports an invalid access.

The fault address is 0x18, not necessarily zero. This is why crash reports with small addresses often suggest a null pointer plus a field offset.

Write to a read-only page

Suppose:

The address is mapped and may contain program instructions. The fault occurs because the attempted write conflicts with the mapping's permissions.

Instruction fetch from data memory

If control flow jumps to a heap address whose page is readable and writable but not executable, the MMU raises a protection fault on instruction fetch. This can indicate a corrupted function pointer or return address.

The correct diagnosis always combines:

The address alone is not enough.

User-Mode and Kernel-Mode Faults

A user-mode page fault enters the kernel so the operating system can resolve or report it.

Kernel code can also fault. This does not have one universal outcome.

The kernel deliberately accesses user memory while implementing operations such as reading a buffer supplied to a system call. That user pointer may be invalid or may require a recoverable page-fault action. Kernels use guarded routines and exception-fixup paths so a bad user pointer can become an error returned to the process rather than a kernel crash.

A page fault caused by an invalid kernel pointer is more serious. The kernel cannot isolate itself as an ordinary user process. Depending on the operating system and context, it may report a kernel fault, terminate the current process, produce an oops, or panic to prevent continued execution with corrupted state.

Privilege mode is therefore part of fault interpretation:

Not every kernel-mode fault is a kernel bug, but every kernel fault must follow an explicitly safe recovery path or be treated as fatal.

Minor and Major Page Faults

Linux and other Unix-like systems commonly classify resolved page faults as minor or major according to whether storage I/O was required.

Minor page fault

A minor fault can be resolved without reading the page's contents from storage.

Examples include:

  • Supplying a new zero-filled page
  • Mapping data that is already resident in a system cache
  • Creating a private in-memory copy for a protected shared page

Minor does not mean “no cost.” The CPU still enters the kernel, the handler examines metadata, page tables may be updated, and translation state may need synchronization. The name only says that storage I/O was unnecessary.

Major page fault

A major fault requires I/O to obtain the contents from backing storage.

Examples include:

  • Reading file-derived data that is not currently cached in memory
  • Reading anonymous process data that had been moved to swap

The faulting thread cannot continue until the required contents are available. It normally blocks while the I/O system performs the read, allowing the scheduler to run other work.

Storage access is far slower and more variable than an in-memory minor-fault path. Major faults can therefore create noticeable latency.

The distinction is not:

File-derived data already present in memory can produce a minor fault. Anonymous data that must be read from swap can produce a major fault.

The useful test is:

TLB Miss, Minor Fault, and Major Fault

These events form increasingly expensive paths, but they are not interchangeable.

EventEnters kernel?Requires storage I/O?Typical outcome
TLB miss with usable PTEUsually no on hardware-managed designsNoFill translation cache
Minor page faultYesNoUpdate mapping using in-memory resources
Major page faultYesYesBlock for contents, update mapping, retry
Invalid access faultYesNot usefullySignal process or handle kernel failure

A TLB miss can cost a hardware page-table walk. A minor fault adds exception entry, kernel policy, and mapping updates. A major fault adds storage latency and scheduling.

The difference can span several orders of magnitude. Exact timings depend heavily on processor caches, kernel state, storage hardware, contention, and workload.

Loading simulation...

Concurrent Faults on the Same Page

Multiple threads can fault on the same virtual page at nearly the same time.

Suppose Thread A and Thread B share an address space and both access a page whose file-derived contents are not resident:

Thread A faults and begins obtaining the page. Thread B faults on the same page and discovers that the work is already in progress.

The kernel must coordinate them. It should not allocate conflicting frames or perform unnecessary duplicate I/O. One thread may initiate the work while the other waits. When the page becomes ready, both can use the completed mapping according to their permissions.

Mapping state can also change while a fault is being handled. Another thread may remove the region or change its permissions. The fault handler uses address-space synchronization and rechecks relevant state before installing a result.

This concurrency is one reason page-fault handling is more than “load a page and continue.” It is a kernel synchronization path operating on shared process and system memory metadata.

Page Faults and Process Scheduling

A minor fault can often be resolved while the current thread remains in the kernel and then immediately returns to retry the instruction.

A major fault must wait for I/O. The faulting thread becomes blocked:

This prevents the CPU from sitting idle during storage access, but it does not remove application latency. A request handled by the blocked thread still waits.

If many threads repeatedly require nonresident contents, the system can accumulate storage work and spend substantial time servicing faults. Fault rate therefore matters alongside fault latency.

An occasional major fault during process startup may be expected. Sustained major faults on frequently used request paths are more concerning because they make service latency depend on storage.

Measuring Page Faults on Linux

GNU /usr/bin/time reports minor and major faults for a command:

Relevant lines look like:

The exact wording “reclaiming a frame” is historical and broader than some modern minor-fault cases. Interpret the counters using the essential distinction: major faults required I/O; minor faults did not.

Linux perf can also count software page-fault events:

Availability and permission depend on the environment.

A process can query its own counts through getrusage():

These are cumulative counts. A useful measurement records values before and after the work of interest, then compares the difference.

Counts need context. Startup naturally faults in executable code, libraries, stacks, and runtime state. Compare similar workload phases, and distinguish a one-time warm-up from faults that continue during steady-state request handling.

Observing First Accesses

The following program allocates 64 MiB and writes one byte per system page:

Compile and measure it:

The loop touches approximately:

On a typical system, many first writes are resolved as minor faults because usable zero-initialized memory can be supplied without reading old contents from storage.

Do not expect the counter to equal 16,384 exactly. Program startup creates other faults, the allocator can touch some pages, page size can differ, and the operating system may use optimizations that change the observed count.

The experiment demonstrates that allocating a virtual range and first accessing its pages are separate events. It does not prove that every allocation or every later write faults.

Diagnosing Fault-Related Latency

When page faults appear in a slow service, start by separating:

Then ask when they occur.

Faults concentrated during startup or a deliberate warm-up phase can be acceptable. Major faults that correlate with high request latency suggest that frequently needed contents are not remaining resident. A burst after loading a new dataset may have a different cause from a steady rate during a stable workload.

Also inspect access patterns. A process can touch a large range once, faulting each page, and then reuse it without further faults. Another workload can continually move among more active pages than physical memory can support and keep generating expensive faults.

Page-fault counts should be combined with:

  • Wall-clock latency and CPU time
  • Storage latency and throughput
  • Memory usage and pressure
  • The process phase being measured
  • Whether the faulting contents are anonymous or file-derived

A high count is evidence of activity, not a complete diagnosis by itself.

Summary

A page fault is a synchronous exception raised when the MMU cannot complete an instruction fetch, load, or store using the current page mappings and permissions. The hardware records the faulting address, operation, privilege context, and instruction state before transferring control to the kernel.

The kernel compares the immediate page-table condition with the process's higher-level virtual-region policy. A recoverable fault causes the kernel to supply the required frame or contents, update translation state, and retry the instruction. An invalid address or prohibited operation is reported to the process, commonly through SIGSEGV on Linux.

Minor faults are resolved without storage I/O; major faults require it and can block the thread for much longer. Page-fault counts are therefore most useful when separated by type and correlated with workload phase, storage behavior, memory pressure, and application latency.

Quiz

Page Faults Quiz

5 quizzes