Fact-checked by Grok 2 weeks ago

General protection fault

A general protection fault (GPF), also known as the #GP exception in x86 architecture, is a type of CPU-generated fault that signals a protection violation detected by the processor, encompassing a broad class of errors such as exceeding segment limits, loading invalid segment selectors, or violating privilege rules that prevent unauthorized access to memory or system resources. This mechanism, first implemented in the Intel 80286 microprocessor released in 1983, serves as a catch-all for various protection issues not covered by more specific exceptions like page faults or stack faults, ensuring the integrity of protected mode operation in x86 systems. In Microsoft Windows operating systems, particularly earlier versions such as Windows 3.x and Windows 9x, a GPF typically manifests as an unrecoverable application error (UAE), prompting a dialog box that informs the user of a program crash due to invalid memory access or other protection breaches, often requiring the application to close or, in severe cases, restarting the system. These faults arise from causes including attempts to write to read-only segments, executing instructions longer than 15 bytes, or misconfigured control registers like CR0 and CR4, and the processor provides an error code to the operating system handler for diagnosis. In modern Windows versions running on x86-64 processors, GPFs are handled more gracefully through structured exception handling (SEH), translating the hardware interrupt into software exceptions that applications can catch, though unhandled ones still lead to process termination to maintain system stability. The #GP exception plays a in enforcing and levels in multitasking environments, preventing malicious or erroneous from compromising kernel-mode operations or other processes' . Common triggers in include dereferencing pointers, overflows, or incorrect use of segment registers (e.g., , , , ), and debugging tools like in Windows or kernel debuggers analyze the fault's , which provides the segment selector index if applicable or 0, along with indicators for external events and IDT vectoring, to pinpoint the violation. While GPFs were notorious for causing instability in 16-bit Windows eras, advancements in x86 hardware and OS design have reduced their frequency, though they remain essential for security features like address space layout randomization (ASLR) and data execution prevention (DEP).

Overview

Definition

A general protection fault, denoted as #GP, is a fault exception in the x86 architecture that occurs when the processor detects a protection violation, such as attempts to access unauthorized memory, exceed segment limits, or perform invalid operations involving descriptors or privilege levels. It is triggered via interrupt vector 13 (decimal, or 13h in hexadecimal), which the CPU uses to signal these broad categories of protection issues to the operating system or handler. The primary role of #GP is to enforce the x86 protection mechanisms, including segmentation and privilege rings, by immediately halting instruction execution upon detecting violations like privilege escalation attempts or invalid control transfers, thereby maintaining system stability and preventing unauthorized access to sensitive resources. This exception covers a wide range of general protection concerns that do not fit into more specific categories, distinguishing it from page faults (#PF, vector 14), which handle paging-related memory access errors such as invalid page table entries, and double faults (#DF, vector 8), which arise from unresolvable nested exceptions leading to potential system shutdown. Upon occurrence, the CPU saves the processor state in a stack frame, pushing the return instruction pointer (EIP), code segment selector (CS), and flags register (EFLAGS) onto the stack; in cases of privilege level changes, also pushing the prior stack segment selector (SS) and stack pointer (ESP); along with an error code if applicable. An error code, a 32-bit value, is also pushed onto the stack for many #GP instances, providing details like the segment selector involved in the violation or flags indicating external triggers, though it may be zero if no specific selector applies.

Historical Development

The general protection fault (GPF), designated as exception vector 13, originated with the introduction of the Intel 80286 microprocessor in 1982, marking a pivotal advancement in x86 architecture by enabling protected mode operations. This mode incorporated memory segmentation to isolate tasks and enforce privilege levels, preventing unauthorized access to system resources and supporting early multitasking environments. The GPF served as a catch-all mechanism for detecting violations such as exceeding segment limits, privilege mismatches, or invalid descriptor usage, thereby enhancing system stability over the unprotected real mode of prior processors like the 8086. As detailed in Intel's documentation, this fault was essential for the 80286's 16 MB physical address space and up to 1 GB virtual space per task, laying the groundwork for protected virtual addressing in multiuser systems. The mechanism evolved significantly with the Intel 80386 in 1985, which extended protected mode to 32-bit operations and integrated paging alongside segmentation for more granular memory protection. This expansion allowed the GPF to handle a broader array of violations, including those related to page table errors, non-present pages, and refined privilege checks via descriptor privilege levels (DPL), requestor privilege levels (RPL), and current privilege levels (CPL). The 80386's dual segmentation-paging model made the GPF indispensable for multitasking operating systems, as it trapped faults during memory accesses, control transfers, and task switches, providing error codes to aid diagnosis. Intel's reference materials emphasize how these enhancements addressed the 80286's limitations, such as 24-bit addressing constraints, enabling more robust virtual memory management up to 4 GB. In the transition to 64-bit computing with the AMD64 architecture in 2003, the GPF persisted as vector 13 but adapted to long mode, emphasizing paging over segmentation in a flat 64-bit address space with canonical addressing rules. Segmentation checks were largely de-emphasized—such as ignoring most segment limits and bases—shifting the GPF's role to enforce page-level protections, non-canonical address faults, and kernel-user boundaries, while maintaining compatibility with 32-bit modes. This evolution reduced reliance on segmentation-related triggers, aligning with modern virtual memory priorities. Key milestones include its prominence in 1990s multitasking OS like Windows 3.x, where GPFs frequently caused application crashes due to memory protection breaches in cooperative environments, underscoring early implementation challenges. Post-2000, improved OS error handling in systems like Windows NT derivatives minimized user-facing GPF visibility by isolating faults and providing structured exception mechanisms, though the fault remains critical for core protection.

Operating System Handling

Microsoft Windows

In Microsoft Windows, a general protection fault (#GP) occurring in user mode is generally translated into an access violation exception with NTSTATUS code 0xC0000005, indicating an attempt to access invalid or protected memory. If the application does not handle this exception through structured exception handling (SEH), the offending process terminates abruptly. In legacy 16-bit and 32-bit applications, particularly those from the Windows 95 and Windows NT eras, this often triggered a prominent dialog box warning of a "General Protection Fault," frequently leading to application crashes that highlighted the era's stability challenges. In modern versions such as Windows 10 and 11, unhandled exceptions invoke Windows Error Reporting (WER), where the WerFault.exe process collects diagnostic data like minidumps and telemetry for submission to Microsoft, enabling automated crash analysis and potential recovery callbacks. In kernel mode, the Windows NT kernel leverages SEH to intercept and process #GP exceptions via internal dispatch mechanisms, such as KiDispatchException, allowing drivers or system components to attempt recovery if a handler is registered. This structured approach unwinds the kernel stack, executes cleanup routines, and decides whether to resume execution or propagate the exception. However, if no handler catches the fault—often due to irrecoverable issues like invalid descriptor accesses or privilege violations—the system triggers a Blue Screen of Death (BSOD) with stop code 0x0000001E (KMODE_EXCEPTION_NOT_HANDLED), where parameter 1 typically reflects the exception code 0xC0000005. The handling of #GP has evolved significantly since its prominence in early Windows versions. In 16-bit and 32-bit systems like Windows 95 and NT (mid-1990s), #GP faults were notorious for causing frequent, non-recoverable crashes in both user and kernel contexts due to less robust protection mechanisms. In 64-bit versions of Windows, starting from Windows XP x64 (2005) and continuing through modern versions such as Windows 10 and 11, integration with WER has enhanced telemetry collection for both modes, while tools like WinDbg facilitate post-mortem analysis of exception details, including NTSTATUS values, to identify root causes such as overlapping access violations.

Unix-like Systems

In Unix-like systems, a general protection fault occurring in user space is mapped to the SIGSEGV signal, commonly known as a segmentation fault, which indicates an invalid memory reference such as accessing unmapped or protected memory regions. This signal is generated by the kernel's hardware exception handler in response to the CPU's #GP interrupt, often routed through routines like exc_general_protection in the architecture-specific trap handling code. By default, receipt of SIGSEGV terminates the process and may produce a core dump for later analysis, though a custom signal handler can intercept it to attempt recovery or logging. In the Linux kernel, general protection faults in kernel space are handled differently, triggering an "oops" message or full panic to prevent further corruption, with the exception vectored through the Interrupt Descriptor Table (IDT) at entry 13 to the do_general_protection_fault routine. This routine first attempts context-specific fixups, such as for certain instruction-level issues, before invoking the die() mechanism to log the fault address, error code, and stack trace if recovery fails. BSD variants employ analogous signal delivery for user-space faults via SIGSEGV, while kernel-mode #GP events manifest as a "fatal trap 9: general protection fault," leading to a panic and system halt. Historically, in SunOS releases from the 1980s, general protection faults were frequently classified and signaled as bus errors (SIGBUS) due to hardware-level memory access violations, differing from modern treatments that align more closely with POSIX standards for segmentation violations. For debugging, tools such as GDB can load core dumps generated by SIGSEGV to inspect the process state, registers, and stack at the time of the fault, facilitating identification of issues like invalid pointers or buffer overflows. In modern Linux kernels (version 5.x and later, introduced around 2019 and refined post-2020), kernel-space #GP handling includes detailed oops reports with symbolic stack traces, aiding developers in pinpointing the faulty code without requiring external debug symbols in many cases. Unlike page faults (#PF), which primarily manage demand paging and virtual memory mapping by loading absent pages from disk, general protection faults (#GP) specifically address protection mechanism breaches unrelated to paging, such as attempts to load invalid segment selectors or execute with insufficient privileges.

Other Operating Systems

In macOS, which is built on the Darwin kernel, a general protection fault on x86 architectures is mapped to the Mach exception type EXC_I386_GPFLT, routed through the kernel's trap handler for processing. This often results in process termination and generation of a crash report viewable in Console.app, integrating with underlying Unix-like signal mechanisms while incorporating additional checks from macOS sandboxing features. In real-time operating systems like VxWorks, a general protection fault triggers an exception via vector 13, typically suspending the offending task, logging the event, and invoking an interrupt service routine for recovery or system reset to maintain real-time constraints with limited visibility to users. Similarly, in FreeRTOS ports to x86 (such as on Intel Quark), exceptions including general protection faults are managed through a configurable interrupt vector table supporting full nesting, directing control to a dedicated fault handler that may latch error status for debugging while preserving a separate ISR stack. Legacy systems handled general protection faults more primitively; in MS-DOS, it manifested as interrupt 0D, often intercepted by protected-mode extenders or memory managers, but unhandled cases typically caused system freezes or reboots. OS/2 treated it as TRAP 000D for general protection exceptions, recommending contact with software support as it indicated protection violations not covered by other traps, potentially from faulty 16-bit applications. Cross-architecture equivalents exist in non-x86 systems; on ARM, memory-related general protection violations trigger a data abort exception, entering Abort mode (or Hyp/Monitor mode if configured) to handle invalid accesses. In RISC-V, similar issues may raise a load/store access fault or illegal instruction exception, delegable across privilege modes (M, S, U) for isolation. Modern containerized environments, such as Android on x86, map general protection faults in the kernel's traps.c to SIGSEGV via notify_die, isolating the fault to the application level without broader system impact. As of 2025, the Windows Subsystem for Linux (WSL2) emulates similar mapping in its Linux guest kernel, translating host-detected protection faults to standard signals like SIGSEGV for compatibility.

Categories of Violations

Memory Access Errors

Memory access errors constitute a primary category of violations that invoke the general protection fault (#GP) in x86 architectures, stemming from attempts to reference memory locations outside the valid ranges defined by segment descriptors or paging structures. These errors typically arise when a program dereferences invalid pointers, such as a null pointer, or performs operations like buffer overflows that exceed allocated memory bounds. For instance, accessing memory at offset zero in a null data segment selector (e.g., for DS, ES, FS, or GS) triggers #GP(0), as the processor detects the invalid reference during address translation. Similarly, buffer overflows in stack or data segments can push offsets beyond the effective segment limit, generating #GP if the access violates boundary checks before paging mechanisms intervene. Read/write permission mismatches further contribute to #GP by attempting operations incompatible with a memory region's attributes, distinct from page faults (#PF) that handle pure paging violations. Executing instructions from a non-executable data segment or writing to a read-only code segment exemplifies this, where the segment descriptor's type field (e.g., code segments marked read-only) enforces the restriction at the hardware level. The Intel architecture specifies that such attempts, including loading a non-writable data segment into the stack segment register (SS), result in #GP(0) to prevent unintended modifications. These mismatches often occur in scenarios like mistaking data for code or vice versa, ensuring memory integrity without escalating to privilege-related checks. Stack overflows represent a specialized memory access error where excessive pushes or recursive calls extend beyond the stack segment's limits, potentially leading to #GP if not first caught as a stack-segment fault (#SS). In expand-down stack segments, if the stack pointer (ESP/RSP) falls below the segment base or the offset violates the limit, the processor raises #GP for operations like PUSH or CALL that reference invalid stack memory. Heap corruption, conversely, involves invalid pointers from mismanaged dynamic allocations, causing out-of-bounds accesses in user-mode programs that breach data segment boundaries. Common in C/C++ due to array overruns or unchecked pointer arithmetic, these can corrupt adjacent heap structures, leading to #GP upon dereference. Modern mitigations, such as Address Space Layout Randomization (ASLR), help reduce the exploitability of these memory access errors by randomizing the positions of stack, heap, and other regions, complicating attacks that rely on predictable addresses to craft overflows. However, ASLR does not prevent the underlying invalid accesses and thus cannot eliminate #GP occurrences from programming errors, as the hardware still enforces segment and permission rules rigorously.

Privilege and Security Errors

In x86 architectures, general protection faults (#GP) often arise from attempts to perform operations requiring higher privilege levels than the current privilege level (CPL) permits, enforcing the separation of protection rings. User-mode code executing in ring 3 (CPL=3) cannot directly access kernel-mode resources in ring 0 (CPL=0) without proper mechanisms like system calls or interrupts; unauthorized attempts, such as direct hardware port I/O or loading privileged segment descriptors, trigger a #GP to prevent privilege escalation. Ring transitions via instructions like far CALL or JMP to a more privileged code segment require conforming segments or call gates with appropriate descriptor privilege levels (DPL); if the CPL exceeds the DPL or requested privilege level (RPL), a #GP occurs, ensuring controlled escalation only through validated paths. Certain instructions are inherently privileged and executable only at CPL=0, leading to #GP faults when attempted in ring 3. For instance, the HLT instruction, which halts the processor until an interrupt, generates a #GP if CPL > 0, as it requires kernel-level authority to manage system-wide pauses. Similarly, CLI and STI, which clear or set the interrupt flag in EFLAGS, fault with #GP if CPL > IOPL (I/O Privilege Level, bits 12-13 of EFLAGS), restricting user-mode code from manipulating interrupt enables that could affect kernel operations. These checks maintain security by preventing lower-privilege code from disrupting system stability or bypassing I/O protections. I/O privilege level mismatches further contribute to #GP in scenarios involving hardware access. When user code attempts to execute IN or OUT instructions on privileged I/O ports (ports 0-0x3FF typically for kernel use), a #GP is raised if CPL > IOPL, blocking unauthorized (DMA) or device control that could compromise system integrity. In security-enhanced environments, such as those using mandatory access controls, attempted privilege violations can manifest as #GP when hardware protections enforce policy boundaries. For example, malware seeking to escalate to ring 0 by directly jumping to kernel addresses or modifying control registers often triggers #GP due to invalid CPL or descriptor checks, halting the exploit before it succeeds. Modern mitigations like Supervisor Mode Execution Prevention (SMEP), introduced in Intel processors around 2010 and enabled via CR4 bit 20, amplify this by generating a #GP when supervisor-mode (ring 0) code attempts to execute instructions from user-mode pages (U/S=1 in page tables), thwarting common escalation vectors like return-to-user attacks.

Technical Causes in x86

Segment Limit Violations

In the x86 architecture, segment limit violations occur when a memory access attempts to reference an address beyond the defined boundaries of a segment, as specified in the segment descriptor stored in the Global Descriptor Table (GDT) or Local Descriptor Table (LDT). Segment descriptors are 8-byte structures that include a 32-bit base address (the starting linear address of the segment), a 20-bit limit field (defining the segment's size), and a granularity bit (G); if G is 0, the limit applies in 1-byte units, whereas if G is 1, it applies in 4-KB units, allowing segments up to 4 GB in size. The processor performs limit checks during memory references by calculating the linear address as the sum of the segment base and the effective offset; if this linear address exceeds the base plus the effective limit (adjusted for granularity), a general protection exception (#GP) is generated with error code 0, indicating no specific selector or external cause. This check applies to code segments (CS), data segments (DS, ES, FS, GS), and stack segments (SS), ensuring that offsets do not surpass the segment's boundary—for instance, in a data segment with a limit of 0xFFFF (65,535 bytes when G=0), an offset of 0x10000 would trigger #GP(0). In 32-bit protected mode, such violations are common in segmented environments where linear addresses might attempt to exceed a 4 GB boundary if the segment limit is not set to the maximum (0xFFFFFFFF). In x86-64 long mode, the flat memory model largely ignores segment bases and limits for most segments (CS, DS, ES, SS), with protection enforced primarily through paging; however, the FS and GS segments retain base and limit checks, and non-canonical virtual addresses—those where bits 63:48 do not match bit 47 (e.g., addresses like 0xFFFF7FFFFFFFFFFF where bits 63:48 are all 1s but bit 47 is 0)—trigger #GP(0) as a form of address bound violation analogous to limit exceedance. For example, a miscalculated pointer leading to a non-canonical address during a memory load or store in user mode would fault immediately upon address translation. The CPU detects these violations synchronously during the memory reference stage of instruction execution, prior to any data access. Legacy 16-bit segmented modes, such as those used in DOS extenders, are particularly susceptible to limit violations due to smaller default limits (e.g., 64 KB per segment), where offset overflows during far pointer arithmetic could readily cause #GP equivalents under extended protection. In modern systems employing the flat memory model, segment limit violations are less frequent but can still arise in misconfigured kernel drivers or virtual machine monitors that intentionally use non-flat segmentation for isolation, such as setting a restricted limit on a thread-local storage segment (FS/GS) leading to an out-of-bounds access.

Segment Permission Breaches

In the x86 architecture's protected mode, segment permission breaches occur when an instruction attempts to access a memory segment in a manner that violates the access rights defined in its descriptor, leading to a general protection exception (#GP). These violations are detected by the processor during segment loading or memory reference operations, ensuring the integrity of the protection model by preventing unauthorized modifications or executions. The segment descriptor, stored in the Global Descriptor Table (GDT) or Local Descriptor Table (LDT), includes flags such as the type field that dictate permissible operations like reading, writing, or executing. A segment marked not present (P=0) triggers a separate #NP(selector) exception for code and data segments or #SS(0) for stack operations, distinct from #GP which applies to present (P=1) segments with type or privilege conflicts. Type mismatches further provoke #GP when the segment's type field conflicts with the intended use, such as treating a code segment as data or attempting to write to a read-only data segment. For instance, if rogue code attempts to modify the .text section—typically a read-only code segment—the processor raises #GP(selector) during the write operation at the execution stage. Code segments introduce specific permission rules based on their conforming or non-conforming nature. Non-conforming code segments require the current privilege level (CPL) to exactly match the descriptor privilege level (DPL) for jumps or calls; a violation (CPL > DPL) results in #GP(selector). Conforming code segments, designed for inter-level calls, allow access if CPL ≥ DPL but fault with #GP if CPL < DPL, enforcing downward privilege flow. Writes to execute-only code segments are prohibited, as their type field (e.g., execute-only) disallows writes, causing #GP(selector) with the error code specifying the offending selector and extent of the violation. Conversely, attempting to execute instructions from a data-only segment triggers #GP due to the incompatible type, preventing code injection attacks. Stack segment (SS) permissions add distinct checks during push or pop operations; an invalid SS selector, such as a null selector or one with mismatched type (e.g., not a writable data segment), generates #GP(selector), distinguishable from #SS which handles limit or presence issues. These checks occur primarily at instruction decode for segment loading and during execution for memory accesses, providing layered protection. While related to broader privilege errors, segment permission breaches focus on type and access right conflicts rather than ring-level escalations.

Invalid Segment Loading

In x86 architecture, a general protection fault (#GP) can occur when attempting to load an invalid segment selector into a segment register, as the processor performs validation checks during operations such as MOV instructions to registers like CS, DS, ES, FS, GS, or SS. These checks ensure the selector points to a valid descriptor in the Global Descriptor Table (GDT) or Local Descriptor Table (LDT) before loading the associated segment attributes into the register's hidden portion. A null selector (value 0) represents an invalid segment and triggers a #GP exception when loaded into the code segment register (CS) or stack segment register (SS), as these require a non-null, valid descriptor to establish the execution environment. In contrast, loading a null selector into data segment registers (DS, ES, FS, or GS) is permitted in protected mode, initializing the segment to a null state, but any subsequent memory reference using that register will generate a #GP fault due to the absence of a valid base address or limit. Invalid indices within the segment selector also provoke a #GP exception if the index (bits 3-15 of the 16-bit selector) exceeds the bounds of the GDT or LDT, such as when the computed offset (index × 8) surpasses the table limit stored in the respective register (GDTR or LDTR). Selectors must be aligned to descriptor boundaries (multiples of 8 bytes), and any misalignment or reference to a non-present descriptor entry results in the fault, with the error code pushing the faulting selector value onto the stack for diagnostic purposes. Errors in the Table Indicator (TI) bit (bit 2 of the selector) lead to #GP faults when the bit incorrectly specifies the descriptor table: TI=0 requires access to the GDT, while TI=1 mandates the LDT, and attempting to use an LDT selector without a valid LDTR (e.g., in a system without per-task local tables) or exceeding the LDT limit triggers the exception with the offending selector in the error code. Such faults commonly arise in low-level programming scenarios, such as assembly code performing far jumps or calls with malformed selectors (e.g., an out-of-bounds index in a JMP far instruction), which is frequent in hand-written bootloaders initializing the GDT before entering protected mode. The processor's validation occurs immediately upon the load attempt, ensuring segment integrity without deferring checks to memory access time, and the error code format (16-bit selector or 0 for null cases) facilitates precise error handling in operating system interrupt routines. This mechanism intersects briefly with context switching, where task state segment selectors must be validated during task switches.

Task Switching Faults

Task switching in the x86 architecture can trigger a general protection fault (#GP) when errors occur during transitions managed by the task state segment (TSS). These faults primarily arise in protected mode environments where hardware-assisted multitasking is employed, involving CALL, JMP, or IRET instructions that reference task gates or TSS selectors. The processor generates #GP(TSS selector) if the referenced TSS descriptor is invalid, such as when it is not of type TSS (types 9 or 11 for available or busy TSS) or marked not present in the global descriptor table (GDT). A specific invalid TSS condition involves the busy bit (bit 7 in the TSS descriptor). During a task switch initiated by CALL or JMP to a task gate or TSS selector, if the target TSS is already marked busy—indicating it is the current task—the processor detects this conflict and raises #GP(TSS selector) to prevent concurrent execution. This mechanism ensures proper task serialization but can fault in misconfigured multitasking setups. Issues with the nested task (NT) flag in the EFLAGS register also contribute to task switching faults during returns. When executing IRET from a nested task (one entered via CALL, interrupt, or exception), the processor uses the previous task link field in the current TSS to switch back. If NT is set but the linked TSS descriptor is invalid (e.g., not present, wrong type, or the busy bit is clear), or if the stack segment or offset for popping EFLAGS is inaccessible, a #GP results, often with error code 0 or referencing the invalid selector. This improper popping disrupts the nested task chain, enforcing strict return path validation. Faults related to the local descriptor table (LDT) selector within the TSS occur during the loading phase of a task switch. The new TSS contains an LDT selector that the processor loads into the LDTR register; if this selector points outside the GDT, has the local/global bit set incorrectly, exceeds descriptor table limits, or references a non-LDT descriptor type, #GP(TSS selector) is generated. This check ensures the per-task descriptor table is valid before establishing the new execution environment. Such task switching faults are exemplified in protected mode operating systems employing hardware multitasking, where incorrect TSS or gate configurations during context changes—such as scheduler invocations or interrupt handling—can lead to #GP, as seen in legacy implementations relying on explicit task gates for process transitions. In contemporary flat memory model operating systems, hardware task switching is rarely utilized, having been de-emphasized since the Pentium processor era in favor of efficient software context switching; however, these mechanisms persist for compatibility, particularly in hypervisors managing virtual machine task boundaries, where misaligned TSS setups still risk triggering #GP.

Miscellaneous Triggers

In the x86 architecture, general protection exceptions (#GP) can arise from the processor encountering malformed instructions that exceed the maximum allowable length of 15 bytes, as the instruction decoder cannot process them correctly; this triggers #GP(0) without involving a segment selector. Similarly, execution of undocumented or processor-specific instructions, such as certain opcodes present in legacy BIOS routines, may generate #GP if they violate the expected instruction format or are not supported in the current operating mode. Debug register operations also contribute to miscellaneous #GP triggers, particularly when configuring DR7 with values that set reserved bits or exceed the current privilege level (CPL); for instance, writing a 1 to reserved bits in DR7 (bits 15, 14:13, or 11:8 in legacy modes) results in #GP(0) to prevent invalid debug breakpoint configurations. Access attempts to unsupported debug registers like DR4 or DR5, which are aliased to other registers on modern processors, likewise cause #GP due to architectural reservations. Control register manipulations provide another avenue for #GP faults, such as writing invalid values to CR4, including setting reserved bits (e.g., bits 63:46 or specific feature bits not supported by the processor model), which generates #GP(0) to enforce architectural integrity. In 64-bit mode, loading a non-canonical base address into CR3 or other control registers via MOV instructions similarly triggers #GP to maintain address space validity. Instructions like LIDT and LGDT can induce #GP when their memory operand points to an inaccessible location or specifies a non-canonical base address in IA-32e mode, resulting in #GP(EXT) where the external indicator reflects the access violation; additionally, if the limit field in the operand is zero, subsequent interrupt handling may indirectly lead to #GP, though the load itself faults on operand access. In modern processors supporting Intel Software Guard Extensions (SGX), enclave entry or exit violations—such as attempting to execute non-enclave code within an enclave boundary or accessing unauthorized enclave pages—can trigger #GP faults delivered to the enclave if the SECS.MISCSELECT.EXINFO bit is set, allowing the enclave to handle protection breaches internally as of processor generations through 2025. These SGX-related #GP instances, often with error code 0, emphasize the extension's role in enforcing isolated execution environments without broader system disruption.

References

  1. [1]
    Interrupt 13—General Protection Exception (#GP)
    Indicates that the processor detected one of a class of protection violations called “general-protection violations.”
  2. [2]
    [PDF] Intel® 64 and IA-32 Architectures Software Developer's Manual
    This is Volume 3A, Part 1 of the Intel 64 and IA-32 manual, which is a system programming guide. The manual has nine volumes.
  3. [3]
    [PDF] Intel 80286 Programmer's Reference Manual - Bitsavers.org
    COMPLETE SET OF 9 HANDBOOKS. Save $50.00 off the retail price of $175.00. MEMORY COMPONENTS HANDBOOK. MICROCOMMUNICATIONS HANDBOOK.
  4. [4]
    [PDF] INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986
    Intel's software support consists of two levels of contracts. Standard support includes TIPS (Technical Information Phone ... General Protection Exception ...Missing: sdm history
  5. [5]
    [PDF] AMD64 Architecture Programmer's Manual, Volume 2
    ... History ... General-Protection Exception (Vector 13) ...
  6. [6]
    [MS-ERREF]: NTSTATUS Values - Microsoft Learn
    Nov 16, 2021 · This document provides the common usage details of the NTSTATUS values; individual protocol specifications provide expanded or modified definitions when needed.
  7. [7]
  8. [8]
    Windows Error Reporting - Win32 apps - Microsoft Learn
    Aug 17, 2020 · The error reporting feature enables users to notify Microsoft of application faults, kernel faults, unresponsive applications, and other application specific ...
  9. [9]
    Structured Exception Handling (C/C++) - Microsoft Learn
    Feb 9, 2023 · Structured exception handling (SEH) is a Microsoft extension to C and C++ to handle certain exceptional code situations, such as hardware faults, gracefully.
  10. [10]
    Bug Check 0x1E - Windows Drivers - Microsoft Learn
    Dec 19, 2022 · A possible cause of the error is a system BIOS incompatibility. You can resolve BIOS problems by upgrading the system BIOS version.
  11. [11]
    Hazy memories of the Windows 95 ship party - The Old New Thing
    Jul 14, 2015 · One of the moments from the Windows 95 ship party (20 years ago today) was when one of the team members drove his motorcycle through the ...
  12. [12]
    signal(7) - Linux manual page
    ### Summary of SIGSEGV Signal from signal(7)
  13. [13]
  14. [14]
    Fatal trap 9: general protection fault while in kernel mode
    Oct 30, 2024 · Got a sudden panic & reboot on our test server earlier today running FreeBSD 13.2-RELEASE-p1 while I was running some make buildworld on it: Fatal trap 9: ...
  15. [15]
    Bus Error (Solaris Common Messages and Troubleshooting Guide)
    Some common causes of bus errors are: invalid file descriptors, unreasonable I/O requests, bad memory allocation, misaligned data structures, compiler bugs, and ...Missing: historical general protection
  16. [16]
    How to get a core dump for a segfault on Linux - Julia Evans
    Apr 28, 2018 · A core dump is a copy of your program's memory, and it's useful when you're trying to debug what went wrong with your problematic program.
  17. [17]
    Bug hunting — The Linux Kernel documentation
    When a protection fault occurs the klogd daemon automatically translates important addresses in the kernel log messages to their symbolic equivalents. This ...
  18. [18]
    What's the meaning of exception code "EXC_I386_GPFLT"?
    Oct 29, 2013 · EXC_I386_GPFLT is surely referring to "General Protection fault", which is the x86's way to tell you that "you did something that you are not allowed to do".
  19. [19]
    http://web.mit.edu/darwin/src/modules/xnu/osfmk/kd...
    ... <mach/mach_types.h> #include <mach/machine.h> #include <mach/exception_types.h> #include <i386/trap.h> #include <kdp/kdp_internal.h> #define KDP_TEST_HARNESS ...
  20. [20]
    How do you build a bootable VxWorks application with Rose ... - IBM
    Jun 16, 2018 · Exception ! Vector 13 : General Protection Fault Program Counter : 0x0042d266. Status Register : 0x00010217. To correct this you must specify ...
  21. [21]
    FreeRTOS on the Intel® Galileo (x86 Quark™ SoC X1000)
    The FreeRTOS IA32 port implements a full interrupt nesting model, utilises a separate system stack to save RAM, and never globally disables interrupts (although ...
  22. [22]
    STALKING GENERAL PROTECTION FAULTS: PART I - Jacob Filipp
    If the Intel processor detects a GP fault, the interpreter should handle it by printing out a message such as "Illegal selector" or "Can't write to code segment ...
  23. [23]
    Troubleshooting OS/2 trap errors - IBM
    Jan 28, 2019 · General Protection. All protection violations which do not cause another exception, cause a TRAP000D. Contact software support. 14. 000E. Page ...
  24. [24]
    Data Abort exception - Arm Developer
    A Data Abort exception is taken to Abort mode, but a Data Abort exception can be taken to Monitor mode, or to Hyp mode.
  25. [25]
    Exceptions and Interrupts — CORE-V CV32E40S User Manual ...
    CV32E40S raises an illegal instruction exception for any instruction in the RISC-V privileged and unprivileged specifications that is explicitly defined as ...Exceptions · Non Maskable Interrupts · Clint Mode Interrupt...
  26. [26]
    Troubleshooting Windows Subsystem for Linux | Microsoft Learn
    Mar 10, 2025 · Provides detailed information about common errors and issues people run into while running Linux on the Windows Subsystem for Linux.
  27. [27]
    [PDF] Intel® 64 and IA-32 Architectures Software Developer's Manual
    ... software to set the NT bit (note that an IRET causes a general protection fault in IA-32e mode if the NT bit is set). In IA-32e mode, the SYSCALL/SYSRET ...
  28. [28]
    [PDF] Buffer Overflows - UCSB Computer Science
    –General protection fault. • If access is allowed, memory next to the ... • Buffer overflow in a network server program can be exercised by an outside ...
  29. [29]
    None
    Below is a merged summary of the General Protection Exception (#GP) in x86-64 mode, consolidating all the information from the provided segments into a comprehensive response. To maximize density and clarity, I’ll use a table in CSV format to organize key details (e.g., definition, canonical form checks, segment limits/address bounds, and references) while retaining narrative explanations where necessary. The response includes all unique details from the summaries, avoiding redundancy where possible.
  30. [30]
    SYSCALL — Fast System Call
    The SYSCALL instruction is not recognized in compatibility mode. 64-Bit Mode Exceptions ¶. #UD, If IA32_EFER.SCE = 0. If the LOCK prefix is ...Missing: general fault
  31. [31]
    [PDF] Exception Handling in Intel SGX
    In SGX2, Page faults (#PF) and general-protection faults (#GP) may also be reported to an enclave by configuring MISCSELECT. (Details on MISCSELECT are ...Missing: x86 2025