|
|
PAGING
1. Begin barrier: Stop all but one logical processor; that is, cause all but one to execute the HLT instruction or to
enter a spin loop.
2. Allow the active logical processor to change the necessary paging-structure entries.
3. Allow all logical processors to perform invalidations appropriate to the modifications to the paging-structure
entries.
4. Allow all logical processors to resume normal operation.
Alternative, performance-optimized, TLB shootdown algorithms may be developed; however, software developers
must take care to ensure that the following conditions are met:
• All logical processors that are using the paging structures that are being modified must participate and perform
appropriate invalidations after the modifications are made.
• If the modifications to the paging-structure entries are made before the barrier or if there is no barrier, the
operating system must ensure one of the following: (1) that the affected linear-address range is not used
between the time of modification and the time of invalidation; or (2) that it is prepared to deal with the conse-
quences of the affected linear-address range being used during that period. For example, if the operating
system does not allow pages being freed to be reallocated for another purpose until after the required invalida-
tions, writes to those pages by errant software will not unexpectedly modify memory that is in use.
• Software must be prepared to deal with reads, instruction fetches, and prefetch requests to the affected linear-
address range that are a result of speculative execution that would never actually occur in the executed code
path.
When multiple logical processors are using the same linear-address space at the same time, they must coordinate
before any request to modify the paging-structure entries that control that linear-address space. In these cases,
the barrier in the TLB shootdown routine may not be required. For example, when freeing a range of linear
addresses, some other mechanism can assure no logical processor is using that range before the request to free it
is made. In this case, a logical processor freeing the range can clear the P flags in the PTEs associated with the
range, free the physical page frames associated with the range, and then signal the other logical processors using
that linear-address space to perform the necessary invalidations. All the affected logical processors must complete
their invalidations before the linear-address range and the physical page frames previously associated with that
range can be reallocated.
4.11
INTERACTIONS WITH VIRTUAL-MACHINE EXTENSIONS (VMX)
The architecture for virtual-machine extensions (VMX) includes features that interact with paging. Section 4.11.1
discusses ways in which VMX-specific control transfers, called VMX transitions specially affect paging. Section
4.11.2 gives an overview of VMX features specifically designed to support address translation.
4.11.1 VMX Transitions
The VMX architecture defines two control transfers called VM entries and VM exits; collectively, these are called
VMX transitions. VM entries and VM exits are described in detail in Chapter 27 and Chapter 28, respectively, in
the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3C. The following items identify
paging-related details:
• VMX transitions modify the CR0 and CR4 registers and the IA32_EFER MSR concurrently. For this reason, they
allow transitions between paging modes that would not otherwise be possible:
- VM entries allow transitions from 4-level paging directly to either 32-bit paging or PAE paging.
- VM exits allow transitions from either 32-bit paging or PAE paging directly to 4-level paging or 5-level
paging.
• VMX transitions that result in PAE paging load the PDPTE registers (see Section 4.4.1) as follows:
- VM entries load the PDPTE registers either from the physical address being loaded into CR3 or from the
virtual-machine control structure (VMCS); see Section 27.3.2.4.
- VM exits load the PDPTE registers from the physical address being loaded into CR3; see Section 28.5.4.
Vol. 3A
4-53
PAGING
• VMX transitions invalidate the TLBs and paging-structure caches based on certain control settings. See Section
27.3.2.5 and Section 28.5.5 in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3C.
4.11.2 VMX Support for Address Translation
Chapter 29, “VMX Support for Address Translation,” in the Intel® 64 and IA-32 Architectures Software Developer’s
Manual, Volume 3C, describes two features of the virtual-machine extensions (VMX) that interact directly with
paging. These are virtual-processor identifiers (VPIDs) and the extended page table mechanism (EPT).
VPIDs provide a way for software to identify to the processor the address spaces for different “virtual processors.”
The processor may use this identification to maintain concurrently information for multiple address spaces in its
TLBs and paging-structure caches, even when non-zero PCIDs are not being used. See Section 29.1 for details.
When EPT is in use, the addresses in the paging-structures are not used as physical addresses to access memory
and memory-mapped I/O. Instead, they are treated as guest-physical addresses and are translated through a set
of EPT paging structures to produce physical addresses. EPT can also specify its own access rights and memory
typing; these are used on conjunction with those specified in this chapter. See Section 29.3 for more information.
Both VPIDs and EPT may change the way that a processor maintains information in TLBs and paging structure
caches and the ways in which software can manage that information. Some of the behaviors documented in Section
4.10 may change. See Section 29.4 for details.
4.12
USING PAGING FOR VIRTUAL MEMORY
With paging, portions of the linear-address space need not be mapped to the physical-address space; data for the
unmapped addresses can be stored externally (e.g., on disk). This method of mapping the linear-address space is
referred to as virtual memory or demand-paged virtual memory.
Paging divides the linear address space into fixed-size pages that can be mapped into the physical-address space
and/or external storage. When a program (or task) references a linear address, the processor uses paging to trans-
late the linear address into a corresponding physical address if such an address is defined.
If the page containing the linear address is not currently mapped into the physical-address space, the processor
generates a page-fault exception as described in Section 4.7. The handler for page-fault exceptions typically directs
the operating system or executive to load data for the unmapped page from external storage into physical memory
(perhaps writing a different page from physical memory out to external storage in the process) and to map it using
paging (by updating the paging structures). When the page has been loaded into physical memory, a return from
the exception handler causes the instruction that generated the exception to be restarted.
Paging differs from segmentation through its use of fixed-size pages. Unlike segments, which usually are the same
size as the code or data structures they hold, pages have a fixed size. If segmentation is the only form of address
translation used, a data structure present in physical memory will have all of its parts in memory. If paging is used,
a data structure can be partly in memory and partly in disk storage.
4.13
MAPPING SEGMENTS TO PAGES
The segmentation and paging mechanisms provide support for a wide variety of approaches to memory manage-
ment. When segmentation and paging are combined, segments can be mapped to pages in several ways. To imple-
ment a flat (unsegmented) addressing environment, for example, all the code, data, and stack modules can be
mapped to one or more large segments (up to 4-GBytes) that share same range of linear addresses (see Figure 3-2
in Section 3.2.2). Here, segments are essentially invisible to applications and the operating-system or executive. If
paging is used, the paging mechanism can map a single linear-address space (contained in a single segment) into
virtual memory. Alternatively, each program (or task) can have its own large linear-address space (contained in its
own segment), which is mapped into virtual memory through its own paging structures.
Segments can be smaller than the size of a page. If one of these segments is placed in a page which is not shared
with another segment, the extra memory is wasted. For example, a small data structure, such as a 1-Byte sema-
phore, occupies 4 KBytes if it is placed in a page by itself. If many semaphores are used, it is more efficient to pack
them into a single page.
4-54
Vol. 3A
PAGING
The Intel-64 and IA-32 architectures do not enforce correspondence between the boundaries of pages and
segments. A page can contain the end of one segment and the beginning of another. Similarly, a segment can
contain the end of one page and the beginning of another.
Memory-management software may be simpler and more efficient if it enforces some alignment between page and
segment boundaries. For example, if a segment which can fit in one page is placed in two pages, there may be
twice as much paging overhead to support access to that segment.
One approach to combining paging and segmentation that simplifies memory-management software is to give
each segment its own page table, as shown in Figure 4-13. This convention gives the segment a single entry in the
page directory, and this entry provides the access control information for paging the entire segment.
Page Frames
LDT
Page Directory
Page Tables
PTE
PTE
PTE
Seg. Descript.
PDE
Seg. Descript.
PDE
PTE
PTE
Figure 4-13. Memory Management Convention That Assigns a Page Table to Each Segment
Vol. 3A
4-55
PAGING
4-56
Vol. 3A
CHAPTER 5
PROTECTION
In protected mode, the Intel 64 and IA-32 architectures provide a protection mechanism that operates at both the
segment level and the page level. This protection mechanism provides the ability to limit access to certain
segments or pages based on privilege levels (four privilege levels for segments and two privilege levels for pages).
For example, critical operating-system code and data can be protected by placing them in more privileged
segments than those that contain applications code. The processor’s protection mechanism will then prevent appli-
cation code from accessing the operating-system code and data in any but a controlled, defined manner.
Segment and page protection can be used at all stages of software development to assist in localizing and detecting
design problems and bugs. It can also be incorporated into end-products to offer added robustness to operating
systems, utilities software, and applications software.
When the protection mechanism is used, each memory reference is checked to verify that it satisfies various
protection checks. All checks are made before the memory cycle is started; any violation results in an exception.
Because checks are performed in parallel with address translation, there is no performance penalty. The protection
checks that are performed fall into the following categories:
• Limit checks.
• Type checks.
• Privilege level checks.
• Restriction of addressable domain.
• Restriction of procedure entry-points.
• Restriction of instruction set.
All protection violation results in an exception being generated. See Chapter 6, “Interrupt and Exception Handling,”
for an explanation of the exception mechanism. This chapter describes the protection mechanism and the viola-
tions which lead to exceptions.
The following sections describe the protection mechanism available in protected mode. See Chapter 21, “8086
Emulation,” for information on protection in real-address and virtual-8086 mode.
5.1
ENABLING AND DISABLING SEGMENT AND PAGE PROTECTION
Setting the PE flag in register CR0 causes the processor to switch to protected mode, which in turn enables the
segment-protection mechanism. Once in protected mode, there is no control bit for turning the protection mecha-
nism on or off. The part of the segment-protection mechanism that is based on privilege levels can essentially be
disabled while still in protected mode by assigning a privilege level of 0 (most privileged) to all segment selectors
and segment descriptors. This action disables the privilege level protection barriers between segments, but other
protection checks such as limit checking and type checking are still carried out.
Page-level protection is automatically enabled when paging is enabled (by setting the PG flag in register CR0). Here
again there is no mode bit for turning off page-level protection once paging is enabled. However, page-level protec-
tion can be disabled by performing the following operations:
• Clear the WP flag in control register CR0.
• Set the read/write (R/W) and user/supervisor (U/S) flags for each page-directory and page-table entry.
This action makes each page a writable, user page, which in effect disables page-level protection.
Vol. 3A
5-1
PROTECTION
5.2
FIELDS AND FLAGS USED FOR SEGMENT-LEVEL AND PAGE-LEVEL
PROTECTION
The processor’s protection mechanism uses the following fields and flags in the system data structures to control
access to segments and pages:
• Descriptor type (S) flag - (Bit 12 in the second doubleword of a segment descriptor.) Determines if the
segment descriptor is for a system segment or a code or data segment.
• Type field - (Bits 8 through 11 in the second doubleword of a segment descriptor.) Determines the type of
code, data, or system segment.
• Limit field - (Bits 0 through 15 of the first doubleword and bits 16 through 19 of the second doubleword of a
segment descriptor.) Determines the size of the segment, along with the G flag and E flag (for data segments).
• G flag - (Bit 23 in the second doubleword of a segment descriptor.) Determines the size of the segment, along
with the limit field and E flag (for data segments).
• E flag - (Bit 10 in the second doubleword of a data-segment descriptor.) Determines the size of the segment,
along with the limit field and G flag.
• Descriptor privilege level (DPL) field - (Bits 13 and 14 in the second doubleword of a segment descriptor.)
Determines the privilege level of the segment.
• Requested privilege level (RPL) field - (Bits 0 and 1 of any segment selector.) Specifies the requested
privilege level of a segment selector.
• Current privilege level (CPL) field - (Bits 0 and 1 of the CS segment register.) Indicates the privilege level
of the currently executing program or procedure. The term current privilege level (CPL) refers to the setting of
this field.
• User/supervisor (U/S) flag - (Bit 2 of paging-structure entries.) Determines the type of page: user or
supervisor.
• Read/write (R/W) flag - (Bit 1 of paging-structure entries.) Determines the type of access allowed to a
page: read-only or read/write.
• Execute-disable (XD) flag - (Bit 63 of certain paging-structure entries.) Determines the type of access
allowed to a page: executable or not-executable.
Figure 5-1 shows the location of the various fields and flags in the data-, code-, and system-segment descriptors;
Figure 3-6 shows the location of the RPL (or CPL) field in a segment selector (or the CS register); and Chapter 4
identifies the locations of the U/S, R/W, and XD flags in the paging-structure entries.
5-2
Vol. 3A
PROTECTION
Data-Segment Descriptor
31
24 23 22 2120 19
16 15 14 13 12 11
8
7
0
A
D
Type
Limit
Base 31:24
G
B
0
V
P
P
Base 23:16
4
19:16
L
L
1
0
E
W
A
31
16 15
0
Base Address 15:00
Segment Limit 15:00
0
Code-Segment Descriptor
31
24 23 22 2120 19
16 15 14 13 12 11
8
7
0
A
D
Type
Base 31:24
G
D
0
V
Limit
P
P
Base 23:16
4
19:16
L
L
1
1
C
R
A
31
16 15
0
Base Address 15:00
Segment Limit 15:00
0
System-Segment Descriptor
31
24 23 22 2120 19
16 15 14 13 12 11
8
7
0
D
Limit
Base 31:24
G
0
P
P
0
Type
Base 23:16
4
19:16
L
31
16 15
0
Base Address 15:00
Segment Limit 15:00
0
A
Accessed
E
Expansion Direction
AVL Available to Sys. Programmers
G
Granularity
B
Big
R
Readable
C
Conforming
LIMIT
Segment Limit
D
Default
W
Writable
DPL
Descriptor Privilege Level
P
Present
Reserved
Figure 5-1. Descriptor Fields Used for Protection
Many different styles of protection schemes can be implemented with these fields and flags. When the operating
system creates a descriptor, it places values in these fields and flags in keeping with the particular protection style
chosen for an operating system or executive. Application programs do not generally access or modify these fields
and flags.
The following sections describe how the processor uses these fields and flags to perform the various categories of
checks described in the introduction to this chapter.
5.2.1
Code-Segment Descriptor in 64-bit Mode
Code segments continue to exist in 64-bit mode even though, for address calculations, the segment base is treated
as zero. Some code-segment (CS) descriptor content (the base address and limit fields) is ignored; the remaining
fields function normally (except for the readable bit in the type field).
Code segment descriptors and selectors are needed in IA-32e mode to establish the processor’s operating mode
and execution privilege-level. The usage is as follows:
Vol. 3A
5-3
PROTECTION
• IA-32e mode uses a previously unused bit in the CS descriptor. Bit 53 is defined as the 64-bit (L) flag and is
used to select between 64-bit mode and compatibility mode when IA-32e mode is active (IA32_EFER.LMA = 1).
See Figure 5-2.
- If CS.L = 0 and IA-32e mode is active, the processor is running in compatibility mode. In this case, CS.D
selects the default size for data and addresses. If CS.D = 0, the default data and address size is 16 bits. If
CS.D = 1, the default data and address size is 32 bits.
- If CS.L = 1 and IA-32e mode is active, the only valid setting is CS.D = 0. This setting indicates a default
operand size of 32 bits and a default address size of 64 bits. The CS.L = 1 and CS.D = 1 bit combination is
reserved for future use and a #GP fault will be generated on an attempt to use a code segment with these
bits set in IA-32e mode.
• In IA-32e mode, the CS descriptor’s DPL is used for execution privilege checks (as in legacy 32-bit mode).
Code-Segment Descriptor
31
24 23 22 2120 19
16 15 14 13 12 11
8
7
0
A
D
Type
G
D
L
V
P
P
4
L
L
1
1
C
R
A
31
0
0
A
Accessed
AVL Available to Sys. Programmer’s
G
Granularity
C
Conforming
R
Readable
D
Default
P
Present
DPL
Descriptor Privilege Level
L
64-Bit Flag
Figure 5-2. Descriptor Fields with Flags used in IA-32e Mode
5.3
LIMIT CHECKING
The limit field of a segment descriptor prevents programs or procedures from addressing memory locations outside
the segment. The effective value of the limit depends on the setting of the G (granularity) flag (see Figure 5-1). For
data segments, the limit also depends on the E (expansion direction) flag and the B (default stack pointer size
and/or upper bound) flag. The E flag is one of the bits in the type field when the segment descriptor is for a data-
segment type.
When the G flag is clear (byte granularity), the effective limit is the value of the 20-bit limit field in the segment
descriptor. Here, the limit ranges from 0 to FFFFFH (1 MByte). When the G flag is set (4-KByte page granularity),
the processor scales the value in the limit field by a factor of 212 (4 KBytes). In this case, the effective limit ranges
from FFFH (4 KBytes) to FFFFFFFFH (4 GBytes). Note that when scaling is used (G flag is set), the lower 12 bits of
a segment offset (address) are not checked against the limit; for example, note that if the segment limit is 0,
offsets 0 through FFFH are still valid.
For all types of segments except expand-down data segments, the effective limit is the last address that is allowed
to be accessed in the segment, which is one less than the size, in bytes, of the segment. The processor causes a
general-protection exception (or, if the segment is SS, a stack-fault exception) any time an attempt is made to
access the following addresses in a segment:
• A byte at an offset greater than the effective limit
• A word at an offset greater than the (effective-limit - 1)
• A doubleword at an offset greater than the (effective-limit - 3)
• A quadword at an offset greater than the (effective-limit - 7)
5-4
Vol. 3A
PROTECTION
• A double quadword at an offset greater than the (effective limit - 15)
When the effective limit is FFFFFFFFH (4 GBytes), these accesses may or may not cause the indicated exceptions.
Behavior is implementation-specific and may vary from one execution to another.
For expand-down data segments, the segment limit has the same function but is interpreted differently. Here, the
effective limit specifies the last address that is not allowed to be accessed within the segment; the range of valid
offsets is from (effective-limit + 1) to FFFFFFFFH if the B flag is set and from (effective-limit + 1) to FFFFH if the B
flag is clear. An expand-down segment has maximum size when the segment limit is 0.
Limit checking catches programming errors such as runaway code, runaway subscripts, and invalid pointer calcu-
lations. These errors are detected when they occur, so identification of the cause is easier. Without limit checking,
these errors could overwrite code or data in another segment.
In addition to checking segment limits, the processor also checks descriptor table limits. The GDTR and IDTR regis-
ters contain 16-bit limit values that the processor uses to prevent programs from selecting a segment descriptors
outside the respective descriptor tables. The LDTR and task registers contain 32-bit segment limit value (read from
the segment descriptors for the current LDT and TSS, respectively). The processor uses these segment limits to
prevent accesses beyond the bounds of the current LDT and TSS. See Section 3.5.1, “Segment Descriptor Tables,”
for more information on the GDT and LDT limit fields; see Section 6.10, “Interrupt Descriptor Table (IDT),” for more
information on the IDT limit field; and see Section 8.2.4, “Task Register,” for more information on the TSS segment
limit field.
5.3.1
Limit Checking in 64-bit Mode
In 64-bit mode, the processor does not perform runtime limit checking on code or data segments. However, the
processor does check descriptor-table limits.
5.4
TYPE CHECKING
Segment descriptors contain type information in two places:
• The S (descriptor type) flag.
• The type field.
The processor uses this information to detect programming errors that result in an attempt to use a segment or
gate in an incorrect or unintended manner.
The S flag indicates whether a descriptor is a system type or a code or data type. The type field provides 4 addi-
tional bits for use in defining various types of code, data, and system descriptors. Table 3-1 shows the encoding of
the type field for code and data descriptors; Table 3-2 shows the encoding of the field for system descriptors.
The processor examines type information at various times while operating on segment selectors and segment
descriptors. The following list gives examples of typical operations where type checking is performed (this list is not
exhaustive):
• When a segment selector is loaded into a segment register - Certain segment registers can contain only
certain descriptor types, for example:
- The CS register only can be loaded with a selector for a code segment.
- Segment selectors for code segments that are not readable or for system segments cannot be loaded into
data-segment registers (DS, ES, FS, and GS).
- Only segment selectors of writable data segments can be loaded into the SS register.
• When a segment selector is loaded into the LDTR or task register - For example:
- The LDTR can only be loaded with a selector for an LDT.
- The task register can only be loaded with a segment selector for a TSS.
• When instructions access segments whose descriptors are already loaded into segment registers -
Certain segments can be used by instructions only in certain predefined ways, for example:
- No instruction may write into an executable segment.
Vol. 3A
5-5
PROTECTION
- No instruction may write into a data segment if it is not writable.
- No instruction may read an executable segment unless the readable flag is set.
•
When an instruction operand contains a segment selector - Certain instructions can access segments
or gates of only a particular type, for example:
- A far CALL or far JMP instruction can only access a segment descriptor for a conforming code segment,
nonconforming code segment, call gate, task gate, or TSS.
- The LLDT instruction must reference a segment descriptor for an LDT.
- The LTR instruction must reference a segment descriptor for a TSS.
- The LAR instruction must reference a segment or gate descriptor for an LDT, TSS, call gate, task gate, code
segment, or data segment.
- The LSL instruction must reference a segment descriptor for a LDT, TSS, code segment, or data segment.
- IDT entries must be interrupt, trap, or task gates.
•
During certain internal operations - For example:
- On a far call or far jump (executed with a far CALL or far JMP instruction), the processor determines the
type of control transfer to be carried out (call or jump to another code segment, a call or jump through a
gate, or a task switch) by checking the type field in the segment (or gate) descriptor pointed to by the
segment (or gate) selector given as an operand in the CALL or JMP instruction. If the descriptor type is for
a code segment or call gate, a call or jump to another code segment is indicated; if the descriptor type is for
a TSS or task gate, a task switch is indicated.
- On a call or jump through a call gate (or on an interrupt- or exception-handler call through a trap or
interrupt gate), the processor automatically checks that the segment descriptor being pointed to by the
gate is for a code segment.
- On a call or jump to a new task through a task gate (or on an interrupt- or exception-handler call to a new
task through a task gate), the processor automatically checks that the segment descriptor being pointed to
by the task gate is for a TSS.
- On a call or jump to a new task by a direct reference to a TSS, the processor automatically checks that the
segment descriptor being pointed to by the CALL or JMP instruction is for a TSS.
- On return from a nested task (initiated by an IRET instruction), the processor checks that the previous task
link field in the current TSS points to a TSS.
5.4.1
Null Segment Selector Checking
Attempting to load a null segment selector (see Section 3.4.2, “Segment Selectors”) into the CS or SS segment
register generates a general-protection exception (#GP). A null segment selector can be loaded into the DS, ES,
FS, or GS register, but any attempt to access a segment through one of these registers when it is loaded with a null
segment selector results in a #GP exception being generated. Loading unused data-segment registers with a null
segment selector is a useful method of detecting accesses to unused segment registers and/or preventing
unwanted accesses to data segments.
5.4.1.1
NULL Segment Checking in 64-bit Mode
In 64-bit mode, the processor does not perform runtime checking on NULL segment selectors. The processor does
not cause a #GP fault when an attempt is made to access memory where the referenced segment register has a
NULL segment selector.
5.5
PRIVILEGE LEVELS
The processor’s segment-protection mechanism recognizes 4 privilege levels, numbered from 0 to 3. The greater
numbers mean lesser privileges. Figure 5-3 shows how these levels of privilege can be interpreted as rings of
protection.
5-6
Vol. 3A
PROTECTION
The center (reserved for the most privileged code, data, and stacks) is used for the segments containing the critical
software, usually the kernel of an operating system. Outer rings are used for less critical software. (Systems that
use only 2 of the 4 possible privilege levels should use levels 0 and 3.)
Protection Rings
Operating
System
Kernel
Level 0
Operating System
Services
Level 1
Level 2
Applications
Level 3
Figure 5-3. Protection Rings
The processor uses privilege levels to prevent a program or task operating at a lesser privilege level from accessing
a segment with a greater privilege, except under controlled situations. When the processor detects a privilege level
violation, it generates a general-protection exception (#GP).
To carry out privilege-level checks between code segments and data segments, the processor recognizes the
following three types of privilege levels:
• Current privilege level (CPL) - The CPL is the privilege level of the currently executing program or task. It
is stored in bits 0 and 1 of the CS and SS segment registers. Normally, the CPL is equal to the privilege level of
the code segment from which instructions are being fetched. The processor changes the CPL when program
control is transferred to a code segment with a different privilege level. The CPL is treated slightly differently
when accessing conforming code segments. Conforming code segments can be accessed from any privilege
level that is equal to or numerically greater (less privileged) than the DPL of the conforming code segment.
Also, the CPL is not changed when the processor accesses a conforming code segment that has a different
privilege level than the CPL.
• Descriptor privilege level (DPL) - The DPL is the privilege level of a segment or gate. It is stored in the DPL
field of the segment or gate descriptor for the segment or gate. When the currently executing code segment
attempts to access a segment or gate, the DPL of the segment or gate is compared to the CPL and RPL of the
segment or gate selector (as described later in this section). The DPL is interpreted differently, depending on
the type of segment or gate being accessed:
- Data segment - The DPL indicates the numerically highest privilege level that a program or task can have
to be allowed to access the segment. For example, if the DPL of a data segment is 1, only programs running
at a CPL of 0 or 1 can access the segment.
- Nonconforming code segment (without using a call gate) - The DPL indicates the privilege level that
a program or task must be at to access the segment. For example, if the DPL of a nonconforming code
segment is 0, only programs running at a CPL of 0 can access the segment.
- Call gate - The DPL indicates the numerically highest privilege level that the currently executing program
or task can be at and still be able to access the call gate. (This is the same access rule as for a data
segment.)
- Conforming code segment and nonconforming code segment accessed through a call gate - The
DPL indicates the numerically lowest privilege level that a program or task can have to be allowed to access
the segment. For example, if the DPL of a conforming code segment is 2, programs running at a CPL of 0 or
1 cannot access the segment.
Vol. 3A
5-7
PROTECTION
- TSS - The DPL indicates the numerically highest privilege level that the currently executing program or
task can be at and still be able to access the TSS. (This is the same access rule as for a data segment.)
• Requested privilege level (RPL) - The RPL is an override privilege level that is assigned to segment
selectors. It is stored in bits 0 and 1 of the segment selector. The processor checks the RPL along with the CPL
to determine if access to a segment is allowed. Even if the program or task requesting access to a segment has
sufficient privilege to access the segment, access is denied if the RPL is not of sufficient privilege level. That is,
if the RPL of a segment selector is numerically greater than the CPL, the RPL overrides the CPL, and vice versa.
The RPL can be used to ensure that privileged code does not access a segment on behalf of an application
program unless the program itself has access privileges for that segment. See Section 5.10.4, “Checking Caller
Access Privileges (ARPL Instruction),” for a detailed description of the purpose and typical use of the RPL.
Privilege levels are checked when the segment selector of a segment descriptor is loaded into a segment register.
The checks used for data access differ from those used for transfers of program control among code segments;
therefore, the two kinds of accesses are considered separately in the following sections.
5.6
PRIVILEGE LEVEL CHECKING WHEN ACCESSING DATA SEGMENTS
To access operands in a data segment, the segment selector for the data segment must be loaded into the data-
segment registers (DS, ES, FS, or GS) or into the stack-segment register (SS). (Segment registers can be loaded
with the MOV, POP, LDS, LES, LFS, LGS, and LSS instructions.) Before the processor loads a segment selector into
a segment register, it performs a privilege check (see Figure 5-4) by comparing the privilege levels of the currently
running program or task (the CPL), the RPL of the segment selector, and the DPL of the segment’s segment
descriptor. The processor loads the segment selector into the segment register if the DPL is numerically greater
than or equal to both the CPL and the RPL. Otherwise, a general-protection fault is generated and the segment
register is not loaded.
CS Register
CPL
Segment Selector
For Data Segment
RPL
Privilege
Data-Segment Descriptor
Check
DPL
Figure 5-4. Privilege Check for Data Access
Figure 5-5 shows four procedures (located in codes segments A, B, C, and D), each running at different privilege
levels and each attempting to access the same data segment.
1. The procedure in code segment A is able to access data segment E using segment selector E1, because the CPL
of code segment A and the RPL of segment selector E1 are equal to the DPL of data segment E.
2. The procedure in code segment B is able to access data segment E using segment selector E2, because the CPL
of code segment B and the RPL of segment selector E2 are both numerically lower than (more privileged) than
the DPL of data segment E. A code segment B procedure can also access data segment E using segment
selector E1.
3. The procedure in code segment C is not able to access data segment E using segment selector E3 (dotted line),
because the CPL of code segment C and the RPL of segment selector E3 are both numerically greater than (less
privileged) than the DPL of data segment E. Even if a code segment C procedure were to use segment selector
5-8
Vol. 3A
PROTECTION
E1 or E2, such that the RPL would be acceptable, it still could not access data segment E because its CPL is not
privileged enough.
4. The procedure in code segment D should be able to access data segment E because code segment D’s CPL is
numerically less than the DPL of data segment E. However, the RPL of segment selector E3 (which the code
segment D procedure is using to access data segment E) is numerically greater than the DPL of data segment
E, so access is not allowed. If the code segment D procedure were to use segment selector E1 or E2 to access
the data segment, access would be allowed.
Code
Segment C
Segment Sel. E3
RPL=3
CPL=3
3
Lowest Privilege
Code
Segment Sel. E1
Data
Segment A
RPL=2
Segment E
CPL=2
2
DPL=2
Code
Segment Sel. E2
Segment B
RPL=1
CPL=1
1
Code
Segment D
CPL=0
Highest Privilege
0
Figure 5-5. Examples of Accessing Data Segments From Various Privilege Levels
As demonstrated in the previous examples, the addressable domain of a program or task varies as its CPL changes.
When the CPL is 0, data segments at all privilege levels are accessible; when the CPL is 1, only data segments at
privilege levels 1 through 3 are accessible; when the CPL is 3, only data segments at privilege level 3 are acces-
sible.
The RPL of a segment selector can always override the addressable domain of a program or task. When properly
used, RPLs can prevent problems caused by accidental (or intensional) use of segment selectors for privileged data
segments by less privileged programs or procedures.
It is important to note that the RPL of a segment selector for a data segment is under software control. For
example, an application program running at a CPL of 3 can set the RPL for a data- segment selector to 0. With the
RPL set to 0, only the CPL checks, not the RPL checks, will provide protection against deliberate, direct attempts to
violate privilege-level security for the data segment. To prevent these types of privilege-level-check violations, a
program or procedure can check access privileges whenever it receives a data-segment selector from another
procedure (see Section 5.10.4, “Checking Caller Access Privileges (ARPL Instruction)”).
5.6.1
Accessing Data in Code Segments
In some instances it may be desirable to access data structures that are contained in a code segment. The
following methods of accessing data in code segments are possible:
• Load a data-segment register with a segment selector for a nonconforming, readable, code segment.
• Load a data-segment register with a segment selector for a conforming, readable, code segment.
• Use a code-segment override prefix (CS) to read a readable, code segment whose selector is already loaded in
the CS register.
The same rules for accessing data segments apply to method 1. Method 2 is always valid because the privilege
level of a conforming code segment is effectively the same as the CPL, regardless of its DPL. Method 3 is always
valid because the DPL of the code segment selected by the CS register is the same as the CPL.
Vol. 3A
5-9
PROTECTION
5.7
PRIVILEGE LEVEL CHECKING WHEN LOADING THE SS REGISTER
Privilege level checking also occurs when the SS register is loaded with the segment selector for a stack segment.
Here all privilege levels related to the stack segment must match the CPL; that is, the CPL, the RPL of the stack-
segment selector, and the DPL of the stack-segment descriptor must be the same. If the RPL and DPL are not equal
to the CPL, a general-protection exception (#GP) is generated.
5.8
PRIVILEGE LEVEL CHECKING WHEN TRANSFERRING PROGRAM CONTROL
BETWEEN CODE SEGMENTS
To transfer program control from one code segment to another, the segment selector for the destination code
segment must be loaded into the code-segment register (CS). As part of this loading process, the processor exam-
ines the segment descriptor for the destination code segment and performs various limit, type, and privilege
checks. If these checks are successful, the CS register is loaded, program control is transferred to the new code
segment, and program execution begins at the instruction pointed to by the EIP register.
Program control transfers are carried out with the JMP, CALL, RET, SYSENTER, SYSEXIT, SYSCALL, SYSRET, INT n,
and IRET instructions, as well as by the exception and interrupt mechanisms. Exceptions, interrupts, and the IRET
instruction are special cases discussed in Chapter 6, “Interrupt and Exception Handling.” This chapter discusses
only the JMP, CALL, RET, SYSENTER, SYSEXIT, SYSCALL, and SYSRET instructions.
A JMP or CALL instruction can reference another code segment in any of four ways:
• The target operand contains the segment selector for the target code segment.
• The target operand points to a call-gate descriptor, which contains the segment selector for the target code
segment.
• The target operand points to a TSS, which contains the segment selector for the target code segment.
• The target operand points to a task gate, which points to a TSS, which in turn contains the segment selector for
the target code segment.
The following sections describe first two types of references. See Section 8.3, “Task Switching,” for information on
transferring program control through a task gate and/or TSS.
The SYSENTER and SYSEXIT instructions are special instructions for making fast calls to and returns from operating
system or executive procedures. These instructions are discussed in Section 5.8.7, “Performing Fast Calls to
System Procedures with the SYSENTER and SYSEXIT Instructions.”
The SYCALL and SYSRET instructions are special instructions for making fast calls to and returns from operating
system or executive procedures in 64-bit mode. These instructions are discussed in Section 5.8.8, “Fast System
Calls in 64-Bit Mode.”
5.8.1
Direct Calls or Jumps to Code Segments
The near forms of the JMP, CALL, and RET instructions transfer program control within the current code segment,
so privilege-level checks are not performed. The far forms of the JMP, CALL, and RET instructions transfer control
to other code segments, so the processor does perform privilege-level checks.
When transferring program control to another code segment without going through a call gate, the processor
examines four kinds of privilege level and type information (see Figure 5-6):
• The CPL. (Here, the CPL is the privilege level of the calling code segment; that is, the code segment that
contains the procedure that is making the call or jump.)
5-10
Vol. 3A
PROTECTION
CS Register
CPL
Segment Selector
For Code Segment
RPL
Destination Code
Privilege
Segment Descriptor
Check
DPL
C
Figure 5-6. Privilege Check for Control Transfer Without Using a Gate
• The DPL of the segment descriptor for the destination code segment that contains the called procedure.
• The RPL of the segment selector of the destination code segment.
• The conforming (C) flag in the segment descriptor for the destination code segment, which determines whether
the segment is a conforming (C flag is set) or nonconforming (C flag is clear) code segment. See Section
3.4.5.1, “Code- and Data-Segment Descriptor Types,” for more information about this flag.
The rules that the processor uses to check the CPL, RPL, and DPL depends on the setting of the C flag, as described
in the following sections.
5.8.1.1
Accessing Nonconforming Code Segments
When accessing nonconforming code segments, the CPL of the calling procedure must be equal to the DPL of the
destination code segment; otherwise, the processor generates a general-protection exception (#GP). For example
in Figure 5-7:
• Code segment C is a nonconforming code segment. A procedure in code segment A can call a procedure in code
segment C (using segment selector C1) because they are at the same privilege level (CPL of code segment A is
equal to the DPL of code segment C).
• A procedure in code segment B cannot call a procedure in code segment C (using segment selector C2 or C1)
because the two code segments are at different privilege levels.
Vol. 3A
5-11
PROTECTION
Segment Sel. D2
Code
RPL=3
Segment B
Segment Sel. C2
CPL=3
RPL=3
3
Lowest Privilege
Segment Sel. C1
Code
Code
RPL=2
Segment C
Segment A
Segment Sel. D1
DPL=2
CPL=2
RPL=2
Nonconforming
Code Segment
2
Code
Segment D
DPL=1
Conforming
1
Code Segment
Highest Privilege
0
Figure 5-7. Examples of Accessing Conforming and Nonconforming Code Segments From Various Privilege Levels
The RPL of the segment selector that points to a nonconforming code segment has a limited effect on the privilege
check. The RPL must be numerically less than or equal to the CPL of the calling procedure for a successful control
transfer to occur. So, in the example in Figure 5-7, the RPLs of segment selectors C1 and C2 could legally be set to
0, 1, or 2, but not to 3.
When the segment selector of a nonconforming code segment is loaded into the CS register, the privilege level field
is not changed; that is, it remains at the CPL (which is the privilege level of the calling procedure). This is true, even
if the RPL of the segment selector is different from the CPL.
5.8.1.2
Accessing Conforming Code Segments
When accessing conforming code segments, the CPL of the calling procedure may be numerically equal to or
greater than (less privileged) the DPL of the destination code segment; the processor generates a general-protec-
tion exception (#GP) only if the CPL is less than the DPL. (The segment selector RPL for the destination code
segment is not checked if the segment is a conforming code segment.)
In the example in Figure 5-7, code segment D is a conforming code segment. Therefore, calling procedures in both
code segment A and B can access code segment D (using either segment selector D1 or D2, respectively), because
they both have CPLs that are greater than or equal to the DPL of the conforming code segment. For conforming
code segments, the DPL represents the numerically lowest privilege level that a calling procedure may
be at to successfully make a call to the code segment.
(Note that segments selectors D1 and D2 are identical except for their respective RPLs. But since RPLs are not
checked when accessing conforming code segments, the two segment selectors are essentially interchangeable.)
When program control is transferred to a conforming code segment, the CPL does not change, even if the DPL of
the destination code segment is less than the CPL. This situation is the only one where the CPL may be different
from the DPL of the current code segment. Also, since the CPL does not change, no stack switch occurs.
Conforming segments are used for code modules such as math libraries and exception handlers, which support
applications but do not require access to protected system facilities. These modules are part of the operating
system or executive software, but they can be executed at numerically higher privilege levels (less privileged
levels). Keeping the CPL at the level of a calling code segment when switching to a conforming code segment
5-12
Vol. 3A
PROTECTION
prevents an application program from accessing nonconforming code segments while at the privilege level (DPL) of
a conforming code segment and thus prevents it from accessing more privileged data.
Most code segments are nonconforming. For these segments, program control can be transferred only to code
segments at the same level of privilege, unless the transfer is carried out through a call gate, as described in the
following sections.
5.8.2
Gate Descriptors
To provide controlled access to code segments with different privilege levels, the processor provides special set of
descriptors called gate descriptors. There are four kinds of gate descriptors:
• Call gates
• Trap gates
• Interrupt gates
• Task gates
Task gates are used for task switching and are discussed in Chapter 8, “Task Management.” Trap and interrupt
gates are special kinds of call gates used for calling exception and interrupt handlers. The are described in Chapter
6, “Interrupt and Exception Handling.” This chapter is concerned only with call gates.
5.8.3
Call Gates
Call gates facilitate controlled transfers of program control between different privilege levels. They are typically
used only in operating systems or executives that use the privilege-level protection mechanism. Call gates are also
useful for transferring program control between 16-bit and 32-bit code segments, as described in Section 22.4,
“Transferring Control Among Mixed-Size Code Segments.”
Figure 5-8 shows the format of a call-gate descriptor. A call-gate descriptor may reside in the GDT or in an LDT, but
not in the interrupt descriptor table (IDT). It performs six functions:
• It specifies the code segment to be accessed.
• It defines an entry point for a procedure in the specified code segment.
• It specifies the privilege level required for a caller trying to access the procedure.
31
16 15 14 13 12 11
8
7
6
5
4
0
D
Type
Param.
Offset in Segment 31:16
P
P
0
0
0
4
Count
L
0
1
1
0
0
31
16 15
0
Segment Selector
Offset in Segment 15:00
0
DPL
Descriptor Privilege Level
P
Gate Valid
Figure 5-8. Call-Gate Descriptor
• If a stack switch occurs, it specifies the number of optional parameters to be copied between stacks.
• It defines the size of values to be pushed onto the target stack: 16-bit gates force 16-bit pushes and 32-bit
gates force 32-bit pushes.
• It specifies whether the call-gate descriptor is valid.
The segment selector field in a call gate specifies the code segment to be accessed. The offset field specifies the
entry point in the code segment. This entry point is generally to the first instruction of a specific procedure. The DPL
field indicates the privilege level of the call gate, which in turn is the privilege level required to access the selected
Vol. 3A
5-13
PROTECTION
procedure through the gate. The P flag indicates whether the call-gate descriptor is valid. (The presence of the code
segment to which the gate points is indicated by the P flag in the code segment’s descriptor.) The parameter count
field indicates the number of parameters to copy from the calling procedures stack to the new stack if a stack
switch occurs (see Section 5.8.5, “Stack Switching”). The parameter count specifies the number of words for 16-
bit call gates and doublewords for 32-bit call gates.
Note that the P flag in a gate descriptor is normally always set to 1. If it is set to 0, a not present (#NP) exception
is generated when a program attempts to access the descriptor. The operating system can use the P flag for special
purposes. For example, it could be used to track the number of times the gate is used. Here, the P flag is initially
set to 0 causing a trap to the not-present exception handler. The exception handler then increments a counter and
sets the P flag to 1, so that on returning from the handler, the gate descriptor will be valid.
5.8.3.1
IA-32e Mode Call Gates
Call-gate descriptors in 32-bit mode provide a 32-bit offset for the instruction pointer (EIP); 64-bit extensions
double the size of 32-bit mode call gates in order to store 64-bit instruction pointers (RIP). See Figure 5-9:
• The first eight bytes (bytes 7:0) of a 64-bit mode call gate are similar but not identical to legacy 32-bit mode
call gates. The parameter-copy-count field has been removed.
• Bytes 11:8 hold the upper 32 bits of the target-segment offset in canonical form. A general-protection
exception (#GP) is generated if software attempts to use a call gate with a target offset that is not in canonical
form.
•
16-byte descriptors may reside in the same descriptor table with 16-bit and 32-bit descriptors. A type field,
used for consistency checking, is defined in bits 12:8 of the 64-bit descriptor’s highest dword (cleared to zero).
A general-protection exception (#GP) results if an attempt is made to access the upper half of a 64-bit mode
descriptor as a 32-bit mode descriptor.
31
13 12 11 10 9 8 7
0
Type
Reserved
Reserved
12
0
0
0
0
0
31
0
Offset in Segment 63:31
8
31
16 15 14 13 12 11
8
7
0
D
Type
Offset in Segment 31:16
P
P
0
4
L
0
1
1
0
0
31
16 15
0
Segment Selector
Offset in Segment 15:00
0
DPL
Descriptor Privilege Level
P
Gate Valid
Figure 5-9. Call-Gate Descriptor in IA-32e Mode
• Target code segments referenced by a 64-bit call gate must be 64-bit code segments (CS.L = 1, CS.D = 0). If
not, the reference generates a general-protection exception, #GP (CS selector).
• Only 64-bit mode call gates can be referenced in IA-32e mode (64-bit mode and compatibility mode). The
legacy 32-bit mode call gate type (0CH) is redefined in IA-32e mode as a 64-bit call-gate type; no 32-bit call-
gate type exists in IA-32e mode.
5-14
Vol. 3A
PROTECTION
• If a far call references a 16-bit call gate type (04H) in IA-32e mode, a general-protection exception (#GP) is
generated.
When a call references a 64-bit mode call gate, actions taken are identical to those taken in 32-bit mode, with the
following exceptions:
• Stack pushes are made in eight-byte increments.
• A 64-bit RIP is pushed onto the stack.
• Parameter copying is not performed.
Use a matching far-return instruction size for correct operation (returns from 64-bit calls must be performed with
a 64-bit operand-size return to process the stack correctly).
5.8.4
Accessing a Code Segment Through a Call Gate
To access a call gate, a far pointer to the gate is provided as a target operand in a CALL or JMP instruction. The
segment selector from this pointer identifies the call gate (see Figure 5-10); the offset from the pointer is required,
but not used or checked by the processor. (The offset can be set to any value.)
When the processor has accessed the call gate, it uses the segment selector from the call gate to locate the
segment descriptor for the destination code segment. (This segment descriptor can be in the GDT or the LDT.) It
then combines the base address from the code-segment descriptor with the offset from the call gate to form the
linear address of the procedure entry point in the code segment.
As shown in Figure 5-11, four different privilege levels are used to check the validity of a program control transfer
through a call gate:
• The CPL (current privilege level).
• The RPL (requestor privilege level) of the call gate’s selector.
• The DPL (descriptor privilege level) of the call gate descriptor.
• The DPL of the segment descriptor of the destination code segment.
The C flag (conforming) in the segment descriptor for the destination code segment is also checked.
Far Pointer to Call Gate
Segment Selector
Offset
Required but not used by processor
Descriptor Table
Offset
Call-Gate
Segment Selector
Offset
Descriptor
Base
Base
Code-Segment
Descriptor
Base
+
Procedure
Entry Point
Figure 5-10. Call-Gate Mechanism
Vol. 3A
5-15
PROTECTION
CS Register
CPL
Call-Gate Selector
RPL
Call Gate (Descriptor)
Privilege
Check
DPL
Destination Code-
Segment Descriptor
DPL
Figure 5-11. Privilege Check for Control Transfer with Call Gate
The privilege checking rules are different depending on whether the control transfer was initiated with a CALL or a
JMP instruction, as shown in Table 5-1.
Table 5-1. Privilege Check Rules for Call Gates
Instruction
Privilege Check Rules
CALL
CPL ≤ call gate DPL; RPL ≤ call gate DPL
Destination conforming code segment DPL ≤ CPL
Destination nonconforming code segment DPL ≤ CPL
JMP
CPL ≤ call gate DPL; RPL ≤ call gate DPL
Destination conforming code segment DPL ≤ CPL
Destination nonconforming code segment DPL = CPL
The DPL field of the call-gate descriptor specifies the numerically highest privilege level from which a calling proce-
dure can access the call gate; that is, to access a call gate, the CPL of a calling procedure must be equal to or less
than the DPL of the call gate. For example, in Figure 5-15, call gate A has a DPL of 3. So calling procedures at all
CPLs (0 through 3) can access this call gate, which includes calling procedures in code segments A, B, and C. Call
gate B has a DPL of 2, so only calling procedures at a CPL or 0, 1, or 2 can access call gate B, which includes calling
procedures in code segments B and C. The dotted line shows that a calling procedure in code segment A cannot
access call gate B.
The RPL of the segment selector to a call gate must satisfy the same test as the CPL of the calling procedure; that
is, the RPL must be less than or equal to the DPL of the call gate. In the example in Figure 5-15, a calling procedure
in code segment C can access call gate B using gate selector B2 or B1, but it could not use gate selector B3 to
access call gate B.
If the privilege checks between the calling procedure and call gate are successful, the processor then checks the
DPL of the code-segment descriptor against the CPL of the calling procedure. Here, the privilege check rules vary
between CALL and JMP instructions. Only CALL instructions can use call gates to transfer program control to more
privileged (numerically lower privilege level) nonconforming code segments; that is, to nonconforming code
segments with a DPL less than the CPL. A JMP instruction can use a call gate only to transfer program control to a
nonconforming code segment with a DPL equal to the CPL. CALL and JMP instruction can both transfer program
control to a more privileged conforming code segment; that is, to a conforming code segment with a DPL less than
or equal to the CPL.
5-16
Vol. 3A
PROTECTION
If a call is made to a more privileged (numerically lower privilege level) nonconforming destination code segment,
the CPL is lowered to the DPL of the destination code segment and a stack switch occurs (see Section 5.8.5, “Stack
Switching”). If a call or jump is made to a more privileged conforming destination code segment, the CPL is not
changed and no stack switch occurs.
Code
Gate Selector A
Call
Segment A
RPL=3
Gate A
CPL=3
Gate Selector B3
DPL=3
RPL=3
Lowest Privilege
3
Code
Call
Segment B
Gate Selector B1
Gate B
RPL=2
CPL=2
DPL=2
2
Code
Segment C
Gate Selector B2
RPL=1
CPL=1
No Stack
Stack Switch
1
Switch Occurs
Occurs
Code
Code
Segment D
Segment E
DPL=0
DPL=0
Conforming
Nonconforming
0
Highest Privilege
Code Segment
Code Segment
Figure 5-12. Example of Accessing Call Gates At Various Privilege Levels
Call gates allow a single code segment to have procedures that can be accessed at different privilege levels. For
example, an operating system located in a code segment may have some services which are intended to be used
by both the operating system and application software (such as procedures for handling character I/O). Call gates
for these procedures can be set up that allow access at all privilege levels (0 through 3). More privileged call gates
(with DPLs of 0 or 1) can then be set up for other operating system services that are intended to be used only by
the operating system (such as procedures that initialize device drivers).
5.8.5
Stack Switching
Whenever a call gate is used to transfer program control to a more privileged nonconforming code segment (that
is, when the DPL of the nonconforming destination code segment is less than the CPL), the processor automatically
switches to the stack for the destination code segment’s privilege level. This stack switching is carried out to
prevent more privileged procedures from crashing due to insufficient stack space. It also prevents less privileged
procedures from interfering (by accident or intent) with more privileged procedures through a shared stack.
Each task must define up to 4 stacks: one for applications code (running at privilege level 3) and one for each of
the privilege levels 2, 1, and 0 that are used. (If only two privilege levels are used [3 and 0], then only two stacks
must be defined.) Each of these stacks is located in a separate segment and is identified with a segment selector
and an offset into the stack segment (a stack pointer).
The segment selector and stack pointer for the privilege level 3 stack is located in the SS and ESP registers, respec-
tively, when privilege-level-3 code is being executed and is automatically stored on the called procedure’s stack
when a stack switch occurs.
Pointers to the privilege level 0, 1, and 2 stacks are stored in the TSS for the currently running task (see
Figure 8-2). Each of these pointers consists of a segment selector and a stack pointer (loaded into the ESP
register). These initial pointers are strictly read-only values. The processor does not change them while the task is
running. They are used only to create new stacks when calls are made to more privileged levels (numerically lower
Vol. 3A
5-17
PROTECTION
privilege levels). These stacks are disposed of when a return is made from the called procedure. The next time the
procedure is called, a new stack is created using the initial stack pointer. (The TSS does not specify a stack for priv-
ilege level 3 because the processor does not allow a transfer of program control from a procedure running at a CPL
of 0, 1, or 2 to a procedure running at a CPL of 3, except on a return.)
The operating system is responsible for creating stacks and stack-segment descriptors for all the privilege levels to
be used and for loading initial pointers for these stacks into the TSS. Each stack must be read/write accessible (as
specified in the type field of its segment descriptor) and must contain enough space (as specified in the limit field)
to hold the following items:
• The contents of the SS, ESP, CS, and EIP registers for the calling procedure.
• The parameters and temporary variables required by the called procedure.
• The EFLAGS register and error code, when implicit calls are made to an exception or interrupt handler.
The stack will need to require enough space to contain many frames of these items, because procedures often call
other procedures, and an operating system may support nesting of multiple interrupts. Each stack should be large
enough to allow for the worst case nesting scenario at its privilege level.
(If the operating system does not use the processor’s multitasking mechanism, it still must create at least one TSS
for this stack-related purpose.)
When a procedure call through a call gate results in a change in privilege level, the processor performs the following
steps to switch stacks and begin execution of the called procedure at a new privilege level:
1. Uses the DPL of the destination code segment (the new CPL) to select a pointer to the new stack (segment
selector and stack pointer) from the TSS.
2. Reads the segment selector and stack pointer for the stack to be switched to from the current TSS. Any limit
violations detected while reading the stack-segment selector, stack pointer, or stack-segment descriptor cause
an invalid TSS (#TS) exception to be generated.
3. Checks the stack-segment descriptor for the proper privileges and type and generates an invalid TSS (#TS)
exception if violations are detected.
4. Temporarily saves the current values of the SS and ESP registers.
5. Loads the segment selector and stack pointer for the new stack in the SS and ESP registers.
6. Pushes the temporarily saved values for the SS and ESP registers (for the calling procedure) onto the new stack
(see Figure 5-13).
7. Copies the number of parameter specified in the parameter count field of the call gate from the calling
procedure’s stack to the new stack. If the count is 0, no parameters are copied.
8. Pushes the return instruction pointer (the current contents of the CS and EIP registers) onto the new stack.
9. Loads the segment selector for the new code segment and the new instruction pointer from the call gate into
the CS and EIP registers, respectively, and begins execution of the called procedure.
See the description of the CALL instruction in Chapter 3, “Instruction Set Reference, A-L‚”, in the Intel® 64 and
IA-32 Architectures Software Developer’s Manual, Volume 2A, for a detailed description of the privilege level
checks and other protection checks that the processor performs on a far call through a call gate.
5-18
Vol. 3A
PROTECTION
Calling Procedure’s Stack
Called Procedure’s Stack
Calling SS
Parameter 1
Calling ESP
Parameter 2
Parameter 1
Parameter 3
ESP
Parameter 2
Parameter 3
Calling CS
Calling EIP
ESP
Figure 5-13. Stack Switching During an Interprivilege-Level Call
The parameter count field in a call gate specifies the number of data items (up to 31) that the processor should
copy from the calling procedure’s stack to the stack of the called procedure. If more than 31 data items need to be
passed to the called procedure, one of the parameters can be a pointer to a data structure, or the saved contents
of the SS and ESP registers may be used to access parameters in the old stack space. The size of the data items
passed to the called procedure depends on the call gate size, as described in Section 5.8.3, “Call Gates.”
5.8.5.1
Stack Switching in 64-bit Mode
Although protection-check rules for call gates are unchanged from 32-bit mode, stack-switch changes in 64-bit
mode are different.
When stacks are switched as part of a 64-bit mode privilege-level change through a call gate, a new SS (stack
segment) descriptor is not loaded; 64-bit mode only loads an inner-level RSP from the TSS. The new SS is forced
to NULL and the SS selector’s RPL field is forced to the new CPL. The new SS is set to NULL in order to handle
nested far transfers (far CALL, INTn, interrupts, and exceptions). The old SS and RSP are saved on the new stack.
On a subsequent far RET, the old SS is popped from the stack and loaded into the SS register. See Table 5-2.
Table 5-2. 64-Bit-Mode Stack Layout After Far CALL with CPL Change
32-bit Mode
IA-32e mode
Old SS Selector
+12
+24
Old SS Selector
Old ESP
+8
+16
Old RSP
CS Selector
+4
+8
Old CS Selector
EIP
0
ESP
RSP
0
RIP
< 4 Bytes >
< 8 Bytes >
In 64-bit mode, stack operations resulting from a privilege-level-changing far call or far return are eight-bytes wide
and change the RSP by eight. The mode does not support the automatic parameter-copy feature found in 32-bit
mode. The call-gate count field is ignored. Software can access the old stack, if necessary, by referencing the old
stack-segment selector and stack pointer saved on the new process stack.
In 64-bit mode, far RET is allowed to load a NULL SS under certain conditions. If the target mode is 64-bit mode
and the target CPL ≠ 3, IRET allows SS to be loaded with a NULL selector. If the called procedure itself is inter-
rupted, the NULL SS is pushed on the stack frame. On the subsequent far RET, the NULL SS on the stack acts as a
flag to tell the processor not to load a new SS descriptor.
Vol. 3A
5-19
PROTECTION
5.8.6
Returning from a Called Procedure
The RET instruction can be used to perform a near return, a far return at the same privilege level, and a far return
to a different privilege level. This instruction is intended to execute returns from procedures that were called with
a CALL instruction. It does not support returns from a JMP instruction, because the JMP instruction does not save a
return instruction pointer on the stack.
A near return only transfers program control within the current code segment; therefore, the processor performs
only a limit check. When the processor pops the return instruction pointer from the stack into the EIP register, it
checks that the pointer does not exceed the limit of the current code segment.
On a far return at the same privilege level, the processor pops both a segment selector for the code segment being
returned to and a return instruction pointer from the stack. Under normal conditions, these pointers should be
valid, because they were pushed on the stack by the CALL instruction. However, the processor performs privilege
checks to detect situations where the current procedure might have altered the pointer or failed to maintain the
stack properly.
A far return that requires a privilege-level change is only allowed when returning to a less privileged level (that is,
the DPL of the return code segment is numerically greater than the CPL). The processor uses the RPL field from the
CS register value saved for the calling procedure (see Figure 5-13) to determine if a return to a numerically higher
privilege level is required. If the RPL is numerically greater (less privileged) than the CPL, a return across privilege
levels occurs.
The processor performs the following steps when performing a far return to a calling procedure (see Figures 6-2
and 6-4 in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1, for an illustration of the
stack contents prior to and after a return):
1. Checks the RPL field of the saved CS register value to determine if a privilege level change is required on the
return.
2. Loads the CS and EIP registers with the values on the called procedure’s stack. (Type and privilege level checks
are performed on the code-segment descriptor and RPL of the code- segment selector.)
3. (If the RET instruction includes a parameter count operand and the return requires a privilege level change.)
Adds the parameter count (in bytes obtained from the RET instruction) to the current ESP register value (after
popping the CS and EIP values), to step past the parameters on the called procedure’s stack. The resulting
value in the ESP register points to the saved SS and ESP values for the calling procedure’s stack. (Note that the
byte count in the RET instruction must be chosen to match the parameter count in the call gate that the calling
procedure referenced when it made the original call multiplied by the size of the parameters.)
4. (If the return requires a privilege level change.) Loads the SS and ESP registers with the saved SS and ESP
values and switches back to the calling procedure’s stack. The SS and ESP values for the called procedure’s
stack are discarded. Any limit violations detected while loading the stack-segment selector or stack pointer
cause a general-protection exception (#GP) to be generated. The new stack-segment descriptor is also checked
for type and privilege violations.
5. (If the RET instruction includes a parameter count operand.) Adds the parameter count (in bytes obtained from
the RET instruction) to the current ESP register value, to step past the parameters on the calling procedure’s
stack. The resulting ESP value is not checked against the limit of the stack segment. If the ESP value is beyond
the limit, that fact is not recognized until the next stack operation.
6. (If the return requires a privilege level change.) Checks the contents of the DS, ES, FS, and GS segment
registers. If any of these registers refer to segments whose DPL is less than the new CPL (excluding conforming
code segments), the segment register is loaded with a null segment selector.
See the description of the RET instruction in Chapter 4 of the Intel® 64 and IA-32 Architectures Software Devel-
oper’s Manual, Volume 2B, for a detailed description of the privilege level checks and other protection checks that
the processor performs on a far return.
5.8.7
Performing Fast Calls to System Procedures with the SYSENTER and SYSEXIT
Instructions
The SYSENTER and SYSEXIT instructions were introduced into the IA-32 architecture in the Pentium II processors
for the purpose of providing a fast (low overhead) mechanism for calling operating system or executive procedures.
5-20
Vol. 3A
PROTECTION
SYSENTER is intended for use by user code running at privilege level 3 to access operating system or executive
procedures running at privilege level 0. SYSEXIT is intended for use by privilege level 0 operating system or exec-
utive procedures for fast returns to privilege level 3 user code. SYSENTER can be executed from privilege levels 3,
2, 1, or 0; SYSEXIT can only be executed from privilege level 0.
The SYSENTER and SYSEXIT instructions are companion instructions, but they do not constitute a call/return pair.
This is because SYSENTER does not save any state information for use by SYSEXIT on a return.
The target instruction and stack pointer for these instructions are not specified through instruction operands.
Instead, they are specified through parameters entered in MSRs and general-purpose registers.
For SYSENTER, target fields are generated using the following sources:
• Target code segment - Reads this from IA32_SYSENTER_CS.
• Target instruction - Reads this from IA32_SYSENTER_EIP.
• Stack segment - Computed by adding 8 to the value in IA32_SYSENTER_CS.
• Stack pointer - Reads this from the IA32_SYSENTER_ESP.
For SYSEXIT, target fields are generated using the following sources:
• Target code segment - Computed by adding 16 to the value in the IA32_SYSENTER_CS.
• Target instruction - Reads this from EDX.
• Stack segment - Computed by adding 24 to the value in IA32_SYSENTER_CS.
• Stack pointer - Reads this from ECX.
The SYSENTER and SYSEXIT instructions perform “fast” calls and returns because they force the processor into a
predefined privilege level 0 state when SYSENTER is executed and into a predefined privilege level 3 state when
SYSEXIT is executed. By forcing predefined and consistent processor states, the number of privilege checks ordi-
narily required to perform a far call to another privilege levels are greatly reduced. Also, by predefining the target
context state in MSRs and general-purpose registers eliminates all memory accesses except when fetching the
target code.
Any additional state that needs to be saved to allow a return to the calling procedure must be saved explicitly by
the calling procedure or be predefined through programming conventions.
5.8.7.1
SYSENTER and SYSEXIT Instructions in IA-32e Mode
For Intel 64 processors, the SYSENTER and SYSEXIT instructions are enhanced to allow fast system calls from user
code running at privilege level 3 (in compatibility mode or 64-bit mode) to 64-bit executive procedures running at
privilege level 0. IA32_SYSENTER_EIP MSR and IA32_SYSENTER_ESP MSR are expanded to hold 64-bit addresses.
If IA-32e mode is inactive, only the lower 32-bit addresses stored in these MSRs are used. The WRMSR instruction
ensures that the addresses stored in these MSRs are canonical. Note that, in 64-bit mode, IA32_SYSENTER_CS
must not contain a NULL selector.
When SYSENTER transfers control, the following fields are generated and bits set:
• Target code segment - Reads non-NULL selector from IA32_SYSENTER_CS.
• New CS attributes - CS base = 0, CS limit = FFFFFFFFH.
• Target instruction - Reads 64-bit canonical address from IA32_SYSENTER_EIP.
• Stack segment - Computed by adding 8 to the value from IA32_SYSENTER_CS.
• Stack pointer - Reads 64-bit canonical address from IA32_SYSENTER_ESP.
• New SS attributes - SS base = 0, SS limit = FFFFFFFFH.
When the SYSEXIT instruction transfers control to 64-bit mode user code using REX.W, the following fields are
generated and bits set:
• Target code segment - Computed by adding 32 to the value in IA32_SYSENTER_CS.
• New CS attributes - L-bit = 1 (go to 64-bit mode).
• Target instruction - Reads 64-bit canonical address in RDX.
• Stack segment - Computed by adding 40 to the value of IA32_SYSENTER_CS.
Vol. 3A
5-21
PROTECTION
• Stack pointer - Update RSP using 64-bit canonical address in RCX.
When SYSEXIT transfers control to compatibility mode user code when the operand size attribute is 32 bits, the
following fields are generated and bits set:
• Target code segment - Computed by adding 16 to the value in IA32_SYSENTER_CS.
• New CS attributes - L-bit = 0 (go to compatibility mode).
• Target instruction - Fetch the target instruction from 32-bit address in EDX.
• Stack segment - Computed by adding 24 to the value in IA32_SYSENTER_CS.
• Stack pointer - Update ESP from 32-bit address in ECX.
5.8.8
Fast System Calls in 64-Bit Mode
The SYSCALL and SYSRET instructions are designed for operating systems that use a flat memory model (segmen-
tation is not used). The instructions, along with SYSENTER and SYSEXIT, are suited for IA-32e mode operation.
SYSCALL and SYSRET, however, are not supported in compatibility mode (or in protected mode). Use CPUID to
check if SYSCALL and SYSRET are available (CPUID.80000001H.EDX[bit 11] = 1).
SYSCALL is intended for use by user code running at privilege level 3 to access operating system or executive
procedures running at privilege level 0. SYSRET is intended for use by privilege level 0 operating system or execu-
tive procedures for fast returns to privilege level 3 user code.
Stack pointers for SYSCALL/SYSRET are not specified through model specific registers. The clearing of bits in
RFLAGS is programmable rather than fixed. SYSCALL/SYSRET save and restore the RFLAGS register.
For SYSCALL, the processor saves RFLAGS into R11 and the RIP of the next instruction into RCX; it then gets the
privilege-level 0 target code segment, instruction pointer, stack segment, and flags as follows:
• Target code segment - Reads a non-NULL selector from IA32_STAR[47:32].
• Target instruction pointer - Reads a 64-bit address from IA32_LSTAR. (The WRMSR instruction ensures
that the value of the IA32_LSTAR MSR is canonical.)
• Stack segment - Computed by adding 8 to the value in IA32_STAR[47:32].
• Flags - The processor sets RFLAGS to the logical-AND of its current value with the complement of the value in
the IA32_FMASK MSR.
When SYSRET transfers control to 64-bit mode user code using REX.W, the processor gets the privilege level 3
target code segment, instruction pointer, stack segment, and flags as follows:
• Target code segment - Reads a non-NULL selector from IA32_STAR[63:48] + 16.
• Target instruction pointer - Copies the value in RCX into RIP.
• Stack segment - IA32_STAR[63:48] + 8.
• EFLAGS - Loaded from R11.
When SYSRET transfers control to 32-bit mode user code using a 32-bit operand size, the processor gets the priv-
ilege level 3 target code segment, instruction pointer, stack segment, and flags as follows:
• Target code segment - Reads a non-NULL selector from IA32_STAR[63:48].
• Target instruction pointer - Copies the value in ECX into EIP.
• Stack segment - IA32_STAR[63:48] + 8.
• EFLAGS - Loaded from R11.
It is the responsibility of the OS to ensure the descriptors in the GDT/LDT correspond to the selectors loaded by
SYSCALL/SYSRET (consistent with the base, limit, and attribute values forced by the instructions).
See Figure 5-14 for the layout of IA32_STAR, IA32_LSTAR, and IA32_FMASK.
5-22
Vol. 3A
PROTECTION
63
32 31
0
Reserved
SYSCALL EFLAGS Mask
IA32_FMASK
63
0
Target RIP for 64-bit Mode Calling Program
IA32_LSTAR
63
48 47
32 31
0
SYSRET CS and SS
SYSCALL CS and SS
Reserved
IA32_STAR
Figure 5-14. MSRs Used by SYSCALL and SYSRET
The SYSCALL instruction does not save the stack pointer, and the SYSRET instruction does not restore it. It is likely
that the OS system-call handler will change the stack pointer from the user stack to the OS stack. If so, it is the
responsibility of software first to save the user stack pointer. This might be done by user code, prior to executing
SYSCALL, or by the OS system-call handler after SYSCALL.
Because the SYSRET instruction does not modify the stack pointer, it is necessary for software to switch back to the
user stack. The OS may load the user stack pointer (if it was saved after SYSCALL) before executing SYSRET; alter-
natively, user code may load the stack pointer (if it was saved before SYSCALL) after receiving control from
SYSRET.
If the OS loads the stack pointer before executing SYSRET, it must ensure that the handler of any interrupt or
exception delivered between restoring the stack pointer and successful execution of SYSRET is not invoked with the
user stack. It can do so using approaches such as the following:
• External interrupts. The OS can prevent an external interrupt from being delivered by clearing EFLAGS.IF
before loading the user stack pointer.
• Nonmaskable interrupts (NMIs). The OS can ensure that the NMI handler is invoked with the correct stack by
using the interrupt stack table (IST) mechanism for gate 2 (NMI) in the IDT (see Section 6.14.5, “Interrupt
Stack Table”).
• General-protection exceptions (#GP). The SYSRET instruction generates #GP(0) if the value of RCX is not
canonical. The OS can address this possibility using one or more of the following approaches:
- Confirming that the value of RCX is canonical before executing SYSRET.
- Using paging to ensure that the SYSCALL instruction will never save a non-canonical value into RCX.
- Using the IST mechanism for gate 13 (#GP) in the IDT.
5.9
PRIVILEGED INSTRUCTIONS
Some of the system instructions (called “privileged instructions”) are protected from use by application programs.
The privileged instructions control system functions (such as the loading of system registers). They can be
executed only when the CPL is 0 (most privileged). If one of these instructions is executed when the CPL is not 0,
a general-protection exception (#GP) is generated. The following system instructions are privileged instructions:
• LGDT - Load GDT register.
• LLDT - Load LDT register.
Vol. 3A
5-23
PROTECTION
• LTR - Load task register.
• LIDT - Load IDT register.
• MOV (control registers) - Load and store control registers.
• LMSW - Load machine status word.
• CLTS - Clear task-switched flag in register CR0.
• MOV (debug registers) - Load and store debug registers.
• INVD - Invalidate cache, without writeback.
• WBINVD - Invalidate cache, with writeback.
• INVLPG -Invalidate TLB entry.
• HLT- Halt processor.
• RDMSR - Read Model-Specific Registers.
• WRMSR -Write Model-Specific Registers.
• RDPMC - Read Performance-Monitoring Counter.
• RDTSC - Read Time-Stamp Counter.
Some of the privileged instructions are available only in the more recent families of Intel 64 and IA-32 processors
(see Section 23.13, “New Instructions In the Pentium and Later IA-32 Processors”).
The PCE and TSD flags in register CR4 (bits 4 and 2, respectively) enable the RDPMC and RDTSC instructions,
respectively, to be executed at any CPL.
5.10
POINTER VALIDATION
When operating in protected mode, the processor validates all pointers to enforce protection between segments
and maintain isolation between privilege levels. Pointer validation consists of the following checks:
1. Checking access rights to determine if the segment type is compatible with its use.
2. Checking read/write rights.
3. Checking if the pointer offset exceeds the segment limit.
4. Checking if the supplier of the pointer is allowed to access the segment.
5. Checking the offset alignment.
The processor automatically performs first, second, and third checks during instruction execution. Software must
explicitly request the fourth check by issuing an ARPL instruction. The fifth check (offset alignment) is performed
automatically at privilege level 3 if alignment checking is turned on. Offset alignment does not affect isolation of
privilege levels.
5.10.1 Checking Access Rights (LAR Instruction)
When the processor accesses a segment using a far pointer, it performs an access rights check on the segment
descriptor pointed to by the far pointer. This check is performed to determine if type and privilege level (DPL) of the
segment descriptor are compatible with the operation to be performed. For example, when making a far call in
protected mode, the segment-descriptor type must be for a conforming or nonconforming code segment, a call
gate, a task gate, or a TSS. Then, if the call is to a nonconforming code segment, the DPL of the code segment must
be equal to the CPL, and the RPL of the code segment’s segment selector must be less than or equal to the DPL. If
type or privilege level are found to be incompatible, the appropriate exception is generated.
To prevent type incompatibility exceptions from being generated, software can check the access rights of a
segment descriptor using the LAR (load access rights) instruction. The LAR instruction specifies the segment
selector for the segment descriptor whose access rights are to be checked and a destination register. The instruc-
tion then performs the following operations:
1. Check that the segment selector is not null.
5-24
Vol. 3A
PROTECTION
2. Checks that the segment selector points to a segment descriptor that is within the descriptor table limit (GDT
or LDT).
3. Checks that the segment descriptor is a code, data, LDT, call gate, task gate, or TSS segment-descriptor type.
4. If the segment is not a conforming code segment, checks if the segment descriptor is visible at the CPL (that
is, if the CPL and the RPL of the segment selector are less than or equal to the DPL).
5. If the privilege level and type checks pass, loads the second doubleword of the segment descriptor into the
destination register (masked by the value 00FXFF00H, where X indicates that the corresponding 4 bits are
undefined) and sets the ZF flag in the EFLAGS register. If the segment selector is not visible at the current
privilege level or is an invalid type for the LAR instruction, the instruction does not modify the destination
register and clears the ZF flag.
Once loaded in the destination register, software can perform additional checks on the access rights information.
5.10.2 Checking Read/Write Rights (VERR and VERW Instructions)
When the processor accesses any code or data segment it checks the read/write privileges assigned to the
segment to verify that the intended read or write operation is allowed. Software can check read/write rights using
the VERR (verify for reading) and VERW (verify for writing) instructions. Both these instructions specify the
segment selector for the segment being checked. The instructions then perform the following operations:
1. Check that the segment selector is not null.
2. Checks that the segment selector points to a segment descriptor that is within the descriptor table limit (GDT
or LDT).
3. Checks that the segment descriptor is a code or data-segment descriptor type.
4. If the segment is not a conforming code segment, checks if the segment descriptor is visible at the CPL (that
is, if the CPL and the RPL of the segment selector are less than or equal to the DPL).
5. Checks that the segment is readable (for the VERR instruction) or writable (for the VERW) instruction.
The VERR instruction sets the ZF flag in the EFLAGS register if the segment is visible at the CPL and readable; the
VERW sets the ZF flag if the segment is visible and writable. (Code segments are never writable.) The ZF flag is
cleared if any of these checks fail.
5.10.3 Checking That the Pointer Offset Is Within Limits (LSL Instruction)
When the processor accesses any segment it performs a limit check to ensure that the offset is within the limit of
the segment. Software can perform this limit check using the LSL (load segment limit) instruction. Like the LAR
instruction, the LSL instruction specifies the segment selector for the segment descriptor whose limit is to be
checked and a destination register. The instruction then performs the following operations:
1. Check that the segment selector is not null.
2. Checks that the segment selector points to a segment descriptor that is within the descriptor table limit (GDT
or LDT).
3. Checks that the segment descriptor is a code, data, LDT, or TSS segment-descriptor type.
4. If the segment is not a conforming code segment, checks if the segment descriptor is visible at the CPL (that
is, if the CPL and the RPL of the segment selector less than or equal to the DPL).
5. If the privilege level and type checks pass, loads the unscrambled limit (the limit scaled according to the setting
of the G flag in the segment descriptor) into the destination register and sets the ZF flag in the EFLAGS register.
If the segment selector is not visible at the current privilege level or is an invalid type for the LSL instruction,
the instruction does not modify the destination register and clears the ZF flag.
Once loaded in the destination register, software can compare the segment limit with the offset of a pointer.
Vol. 3A
5-25
PROTECTION
5.10.4 Checking Caller Access Privileges (ARPL Instruction)
The requestor’s privilege level (RPL) field of a segment selector is intended to carry the privilege level of a calling
procedure (the calling procedure’s CPL) to a called procedure. The called procedure then uses the RPL to determine
if access to a segment is allowed. The RPL is said to “weaken” the privilege level of the called procedure to that of
the RPL.
Operating-system procedures typically use the RPL to prevent less privileged application programs from accessing
data located in more privileged segments. When an operating-system procedure (the called procedure) receives a
segment selector from an application program (the calling procedure), it sets the segment selector’s RPL to the
privilege level of the calling procedure. Then, when the operating system uses the segment selector to access its
associated segment, the processor performs privilege checks using the calling procedure’s privilege level (stored in
the RPL) rather than the numerically lower privilege level (the CPL) of the operating-system procedure. The RPL
thus ensures that the operating system does not access a segment on behalf of an application program unless that
program itself has access to the segment.
Figure 5-15 shows an example of how the processor uses the RPL field. In this example, an application program
(located in code segment A) possesses a segment selector (segment selector D1) that points to a privileged data
structure (that is, a data structure located in a data segment D at privilege level 0).
The application program cannot access data segment D, because it does not have sufficient privilege, but the oper-
ating system (located in code segment C) can. So, in an attempt to access data segment D, the application
program executes a call to the operating system and passes segment selector D1 to the operating system as a
parameter on the stack. Before passing the segment selector, the (well behaved) application program sets the RPL
of the segment selector to its current privilege level (which in this example is 3). If the operating system attempts
to access data segment D using segment selector D1, the processor compares the CPL (which is now 0 following
the call), the RPL of segment selector D1, and the DPL of data segment D (which is 0). Since the RPL is greater than
the DPL, access to data segment D is denied. The processor’s protection mechanism thus protects data segment D
from access by the operating system, because application program’s privilege level (represented by the RPL of
segment selector B) is greater than the DPL of data segment D.
Passed as a
parameter on
the stack.
Application Program
Code
Call
Segment A
Gate Selector B
Segment Sel. D1
Gate B
RPL=3
RPL=3
CPL=3
DPL=3
3
Lowest Privilege
2
Access
not
allowed
1
Code
Data
Operating
Segment C
Segment Sel. D2 Segment D
System
RPL=0
DPL=0
DPL=0
Access
0
Highest Privilege
allowed
Figure 5-15. Use of RPL to Weaken Privilege Level of Called Procedure
5-26
Vol. 3A
PROTECTION
Now assume that instead of setting the RPL of the segment selector to 3, the application program sets the RPL to
0 (segment selector D2). The operating system can now access data segment D, because its CPL and the RPL of
segment selector D2 are both equal to the DPL of data segment D.
Because the application program is able to change the RPL of a segment selector to any value, it can potentially use
a procedure operating at a numerically lower privilege level to access a protected data structure. This ability to
lower the RPL of a segment selector breaches the processor’s protection mechanism.
Because a called procedure cannot rely on the calling procedure to set the RPL correctly, operating-system proce-
dures (executing at numerically lower privilege-levels) that receive segment selectors from numerically higher
privilege-level procedures need to test the RPL of the segment selector to determine if it is at the appropriate level.
The ARPL (adjust requested privilege level) instruction is provided for this purpose. This instruction adjusts the RPL
of one segment selector to match that of another segment selector.
The example in Figure 5-15 demonstrates how the ARPL instruction is intended to be used. When the operating-
system receives segment selector D2 from the application program, it uses the ARPL instruction to compare the
RPL of the segment selector with the privilege level of the application program (represented by the code-segment
selector pushed onto the stack). If the RPL is less than application program’s privilege level, the ARPL instruction
changes the RPL of the segment selector to match the privilege level of the application program (segment selector
D1). Using this instruction thus prevents a procedure running at a numerically higher privilege level from
accessing numerically lower privilege-level (more privileged) segments by lowering the RPL of a segment selector.
Note that the privilege level of the application program can be determined by reading the RPL field of the segment
selector for the application-program’s code segment. This segment selector is stored on the stack as part of the call
to the operating system. The operating system can copy the segment selector from the stack into a register for
use as an operand for the ARPL instruction.
5.10.5 Checking Alignment
When the CPL is 3, alignment of memory references can be checked by setting the AM flag in the CR0 register and
the AC flag in the EFLAGS register. Unaligned memory references generate alignment exceptions (#AC). The
processor does not generate alignment exceptions when operating at privilege level 0, 1, or 2. See Table 6-7 for a
description of the alignment requirements when alignment checking is enabled.
5.11
PAGE-LEVEL PROTECTION
Page-level protection can be used alone or applied to segments. When page-level protection is used with the flat
memory model, it allows supervisor code and data (the operating system or executive) to be protected from user
code and data (application programs). It also allows pages containing code to be write protected. When the
segment- and page-level protection are combined, page-level read/write protection allows more protection granu-
larity within segments.
With page-level protection (as with segment-level protection) each memory reference is checked to verify that
protection checks are satisfied. All checks are made before the memory cycle is started, and any violation prevents
the cycle from starting and results in a page-fault exception being generated. Because checks are performed in
parallel with address translation, there is no performance penalty.
The processor performs two page-level protection checks:
• Restriction of addressable domain (supervisor and user modes).
• Page type (read only or read/write).
Violations of either of these checks results in a page-fault exception being generated. See Chapter 6, “Interrupt
14-Page-Fault Exception (#PF),” for an explanation of the page-fault exception mechanism. This chapter
describes the protection violations which lead to page-fault exceptions.
Vol. 3A
5-27
PROTECTION
5.11.1 Page-Protection Flags
Protection information for pages is contained in two flags in a paging-structure entry (see Chapter 4): the
read/write flag (bit 1) and the user/supervisor flag (bit 2). The protection checks use the flags in all paging struc-
tures.
5.11.2 Restricting Addressable Domain
The page-level protection mechanism allows restricting access to pages based on two privilege levels:
• Supervisor mode (U/S flag is 0)-(Most privileged) For the operating system or executive, other system
software (such as device drivers), and protected system data (such as page tables).
• User mode (U/S flag is 1)-(Least privileged) For application code and data.
The segment privilege levels map to the page privilege levels as follows. If the processor is currently operating at
a CPL of 0, 1, or 2, it is in supervisor mode; if it is operating at a CPL of 3, it is in user mode. When the processor is
in supervisor mode, it can access all pages; when in user mode, it can access only user-level pages. (Note that the
WP flag in control register CR0 modifies the supervisor permissions, as described in Section 5.11.3, “Page Type.”)
Note that to use the page-level protection mechanism, code and data segments must be set up for at least two
segment-based privilege levels: level 0 for supervisor code and data segments and level 3 for user code and data
segments. (In this model, the stacks are placed in the data segments.) To minimize the use of segments, a flat
memory model can be used (see Section 3.2.1, “Basic Flat Model”).
Here, the user and supervisor code and data segments all begin at address zero in the linear address space and
overlay each other. With this arrangement, operating-system code (running at the supervisor level) and application
code (running at the user level) can execute as if there are no segments. Protection between operating-system and
application code and data is provided by the processor’s page-level protection mechanism.
5.11.3 Page Type
The page-level protection mechanism recognizes two page types:
• Read-only access (R/W flag is 0).
• Read/write access (R/W flag is 1).
When the processor is in supervisor mode and the WP flag in register CR0 is clear (its state following reset initial-
ization), all pages are both readable and writable (write-protection is ignored). When the processor is in user mode,
it can write only to user-mode pages that are read/write accessible. User-mode pages which are read/write or
read-only are readable; supervisor-mode pages are neither readable nor writable from user mode. A page-fault
exception is generated on any attempt to violate the protection rules.
Starting with the P6 family, Intel processors allow user-mode pages to be write-protected against supervisor-mode
access. Setting CR0.WP = 1 enables supervisor-mode sensitivity to write protected pages. If CR0.WP = 1, read-
only pages are not writable from any privilege level. This supervisor write-protect feature is useful for imple-
menting a “copy-on-write” strategy used by some operating systems, such as UNIX*, for task creation (also called
forking or spawning). When a new task is created, it is possible to copy the entire address space of the parent task.
This gives the child task a complete, duplicate set of the parent's segments and pages. An alternative copy-on-
write strategy saves memory space and time by mapping the child's segments and pages to the same segments
and pages used by the parent task. A private copy of a page gets created only when one of the tasks writes to the
page. By using the WP flag and marking the shared pages as read-only, the supervisor can detect an attempt to
write to a page, and can copy the page at that time.
5.11.4 Combining Protection of Both Levels of Page Tables
For any one page, the protection attributes of its page-directory entry (first-level page table) may differ from those
of its page-table entry (second-level page table). The processor checks the protection for a page in both its page-
directory and the page-table entries. Table 5-3 shows the protection provided by the possible combinations of
protection attributes when the WP flag is clear.
5-28
Vol. 3A
PROTECTION
5.11.5 Overrides to Page Protection
The following types of memory accesses are checked as if they are privilege-level 0 accesses, regardless of the CPL
at which the processor is currently operating:
• Access to segment descriptors in the GDT, LDT, or IDT.
• Access to an inner-privilege-level stack during an inter-privilege-level call or a call to in exception or interrupt
handler, when a change of privilege level occurs.
5.12
COMBINING PAGE AND SEGMENT PROTECTION
When paging is enabled, the processor evaluates segment protection first, then evaluates page protection. If the
processor detects a protection violation at either the segment level or the page level, the memory access is not
carried out and an exception is generated. If an exception is generated by segmentation, no paging exception is
generated.
Page-level protections cannot be used to override segment-level protection. For example, a code segment is by
definition not writable. If a code segment is paged, setting the R/W flag for the pages to read-write does not make
the pages writable. Attempts to write into the pages will be blocked by segment-level protection checks.
Page-level protection can be used to enhance segment-level protection. For example, if a large read-write data
segment is paged, the page-protection mechanism can be used to write-protect individual pages.
Table 5-3. Combined Page-Directory and Page-Table Protection
Page-Directory Entry
Page-Table Entry
Combined Effect
Privilege
Access Type
Privilege
Access Type
Privilege
Access Type
User
Read-Only
User
Read-Only
User
Read-Only
User
Read-Only
User
Read-Write
User
Read-Only
User
Read-Write
User
Read-Only
User
Read-Only
User
Read-Write
User
Read-Write
User
Read/Write
User
Read-Only
Supervisor
Read-Only
Supervisor
Read/Write*
User
Read-Only
Supervisor
Read-Write
Supervisor
Read/Write*
User
Read-Write
Supervisor
Read-Only
Supervisor
Read/Write*
User
Read-Write
Supervisor
Read-Write
Supervisor
Read/Write
Supervisor
Read-Only
User
Read-Only
Supervisor
Read/Write*
Supervisor
Read-Only
User
Read-Write
Supervisor
Read/Write*
Supervisor
Read-Write
User
Read-Only
Supervisor
Read/Write*
Supervisor
Read-Write
User
Read-Write
Supervisor
Read/Write
Supervisor
Read-Only
Supervisor
Read-Only
Supervisor
Read/Write*
Supervisor
Read-Only
Supervisor
Read-Write
Supervisor
Read/Write*
Supervisor
Read-Write
Supervisor
Read-Only
Supervisor
Read/Write*
Supervisor
Read-Write
Supervisor
Read-Write
Supervisor
Read/Write
NOTE:
* If CR0.WP = 1, access type is determined by the R/W flags of the page-directory and page-table entries. IF CR0.WP = 0, supervisor
privilege permits read-write access.
Vol. 3A
5-29
PROTECTION
5.13
PAGE-LEVEL PROTECTION AND EXECUTE-DISABLE BIT
In addition to page-level protection offered by the U/S and R/W flags, paging structures used with PAE paging, 4-
level paging,1 and 5-level paging provide the execute-disable bit (see Chapter 4, “Paging”). This bit offers addi-
tional protection for data pages.
An Intel 64 or IA-32 processor with the execute-disable bit capability can prevent data pages from being used by
malicious software to execute code. This capability is provided in:
•
32-bit protected mode with PAE enabled.
• IA-32e mode.
While the execute-disable bit capability does not introduce new instructions, it does require operating systems to
use a PAE-enabled environment and establish a page-granular protection policy for memory pages.
If the execute-disable bit of a memory page is set, that page can be used only as data. An attempt to execute code
from a memory page with the execute-disable bit set causes a page-fault exception.
The execute-disable capability is not supported with 32-bit paging. Existing page-level protection mechanisms (see
Section 5.11, “Page-Level Protection”) continue to apply to memory pages independent of the execute-disable
setting.
5.13.1 Detecting and Enabling the Execute-Disable Capability
Software can detect the presence of the execute-disable capability using the CPUID instruction.
CPUID.80000001H:EDX.NX [bit 20] = 1 indicates the capability is available.
If the capability is available, software can enable it by setting IA32_EFER.NXE[bit 11] to 1. IA32_EFER is available
if CPUID.80000001H.EDX[bit 20 or 29] = 1.
If the execute-disable capability is not available, a write to set IA32_EFER.NXE produces a #GP exception. See
Table 5-4.
Table 5-4. Extended Feature Enable MSR (IA32_EFER)
63:12
11
10
9
8
7:1
0
Reserved
Execute-disable bit
IA-32e mode
Reserved
IA-32e mode
Reserved
SysCall enable (SCE)
enable (NXE)
active (LMA)
enable (LME)
5.13.2 Execute-Disable Page Protection
The execute-disable bit in the paging structures enhances page protection for data pages. Instructions cannot be
fetched from a memory page if IA32_EFER.NXE =1 and the execute-disable bit is set in any of the paging-structure
entries used to map the page. Table 5-5 lists the valid usage of a page in relation to the value of execute-disable bit
(bit 63) of the corresponding entry in each level of the paging structures. Execute-disable protection can be acti-
vated using the execute-disable bit at any level of the paging structure, irrespective of the corresponding entry in
other levels. When execute-disable protection is not activated, the page can be used as code or data.
1. Earlier versions of this manual used the term “IA-32e paging” to identify 4-level paging.
5-30
Vol. 3A
PROTECTION
Table 5-5. Page Level Protection Matrix with Execute-Disable Bit Capability with 4-Level Paging
Execute Disable Bit Value (Bit 63)
Valid Usage
PML4
PDP
PDE
PTE
Bit 63 = 1
*
*
*
Data
*
Bit 63 = 1
*
*
Data
*
*
Bit 63 = 1
*
Data
*
*
*
Bit 63 = 1
Data
Bit 63 = 0
Bit 63 = 0
Bit 63 = 0
Bit 63 = 0
Data/Code
NOTES:
* Value not checked.
In legacy PAE-enabled mode, Table 5-6 and Table 5-7 show the effect of setting the execute-disable bit for code
and data pages.
Table 5-6. 4-KByte Page Level Protection Matrix with Execute-Disable Bit Capability with PAE Paging
Execute Disable Bit Value (Bit 63)
Valid Usage
PDE
PTE
Bit 63 = 1
*
Data
*
Bit 63 = 1
Data
Bit 63 = 0
Bit 63 = 0
Data/Code
NOTE:
* Value not checked.
Table 5-7. 2-MByte Page Level Protection with Execute-Disable Bit Capability with PAE Paging
Execute Disable Bit Value (Bit 63)
Valid Usage
PDE
Bit 63 = 1
Data
Bit 63 = 0
Data/Code
5.13.3 Reserved Bit Checking
The processor enforces reserved bit checking in paging data structure entries. The bits being checked varies with
paging mode and may vary with the size of physical address space.
Table 5-8 shows the reserved bits that are checked when the execute disable bit capability is enabled (CR4.PAE = 1
and IA32_EFER.NXE = 1). Table 5-8 and Table 5-9 show the following paging modes:
• Non-PAE 4-KByte paging: 4-KByte-page only paging (CR4.PAE = 0, CR4.PSE = 0).
• PSE36: 4-KByte and 4-MByte pages (CR4.PAE = 0, CR4.PSE = 1).
• PAE: 4-KByte and 2-MByte pages (CR4.PAE = 1, CR4.PSE = X).
The reserved bit checking depends on the physical address size supported by the implementation, which is
reported in CPUID.80000008H. See the table note.
Vol. 3A
5-31
PROTECTION
Table 5-8. Page Level Protection Matrix with Execute-Disable Bit Capability Enabled
Mode
Paging Mode
Check Bits
32-bit
4-KByte paging (non-PAE)
No reserved bits checked
PSE36 - PDE, 4-MByte page
Bit [21]
PSE36 - PDE, 4-KByte page
No reserved bits checked
PSE36 - PTE
No reserved bits checked
PAE - PDP table entry
Bits [63:MAXPHYADDR] & [8:5] & [2:1] *
PAE - PDE, 2-MByte page
Bits [62:MAXPHYADDR] & [20:13] *
PAE - PDE, 4-KByte page
Bits [62:MAXPHYADDR] *
PAE - PTE
Bits [62:MAXPHYADDR] *
64-bit
PML5E
Bits [51:MAXPHYADDR] *
PML4E
Bits [51:MAXPHYADDR] *
PDPTE
Bits [51:MAXPHYADDR] *
PDE, 2-MByte page
Bits [51:MAXPHYADDR] & [20:13] *
PDE, 4-KByte page
Bits [51:MAXPHYADDR] *
PTE
Bits [51:MAXPHYADDR] *
NOTES:
* MAXPHYADDR is the maximum physical address size and is indicated by CPUID.80000008H:EAX[bits 7-0].
If execute disable bit capability is not enabled or not available, reserved bit checking in 64-bit mode includes bit 63
and additional bits. This and reserved bit checking for legacy 32-bit paging modes are shown in Table 5-10.
Table 5-9. Reserved Bit Checking with Execute-Disable Bit Capability Not Enabled
Mode
Paging Mode
Check Bits
32-bit
KByte paging (non-PAE)
No reserved bits checked
PSE36 - PDE, 4-MByte page
Bit [21]
PSE36 - PDE, 4-KByte page
No reserved bits checked
PSE36 - PTE
No reserved bits checked
PAE - PDP table entry
Bits [63:MAXPHYADDR] & [8:5] & [2:1]*
PAE - PDE, 2-MByte page
Bits [63:MAXPHYADDR] & [20:13]*
PAE - PDE, 4-KByte page
Bits [63:MAXPHYADDR]*
PAE - PTE
Bits [63:MAXPHYADDR]*
64-bit
PML5E
Bit [63], bits [51:MAXPHYADDR]*
PML4E
Bit [63], bits [51:MAXPHYADDR]*
PDPTE
Bit [63], bits [51:MAXPHYADDR]*
PDE, 2-MByte page
Bit [63], bits [51:MAXPHYADDR] & [20:13]*
PDE, 4-KByte page
Bit [63], bits [51:MAXPHYADDR]*
PTE
Bit [63], bits [51:MAXPHYADDR]*
NOTES:
* MAXPHYADDR is the maximum physical address size and is indicated by CPUID.80000008H:EAX[bits 7-0].
5.13.4 Exception Handling
When execute disable bit capability is enabled (IA32_EFER.NXE = 1), conditions for a page fault to occur include
the same conditions that apply to an Intel 64 or IA-32 processor without execute disable bit capability plus the
5-32
Vol. 3A
PROTECTION
following new condition: an instruction fetch to a linear address that translates to physical address in a memory
page that has the execute-disable bit set.
An Execute Disable Bit page fault can occur at all privilege levels. It can occur on any instruction fetch, including
(but not limited to): near branches, far branches, CALL/RET/INT/IRET execution, sequential instruction fetches,
and task switches. The execute-disable bit in the page translation mechanism is checked only when:
• IA32_EFER.NXE = 1.
• The instruction translation look-aside buffer (ITLB) is loaded with a page that is not already present in the ITLB.
Vol. 3A
5-33
PROTECTION
5-34
Vol. 3A
CHAPTER 6
INTERRUPT AND EXCEPTION HANDLING
This chapter describes the interrupt and exception-handling mechanism when operating in protected mode on an
Intel 64 or IA-32 processor. Most of the information provided here also applies to interrupt and exception mecha-
nisms used in real-address, virtual-8086 mode, and 64-bit mode.
Chapter 21, “8086 Emulation,” describes information specific to interrupt and exception mechanisms in real-
address and virtual-8086 mode. Section 6.14, “Exception and Interrupt Handling in 64-bit Mode,” describes infor-
mation specific to interrupt and exception mechanisms in IA-32e mode and 64-bit sub-mode.
6.1
INTERRUPT AND EXCEPTION OVERVIEW
Interrupts and exceptions are events that indicate that a condition exists somewhere in the system, the processor,
or within the currently executing program or task that requires the attention of a processor. They typically result in
a forced transfer of execution from the currently running program or task to a special software routine or task
called an interrupt handler or an exception handler. The action taken by a processor in response to an interrupt or
exception is referred to as servicing or handling the interrupt or exception.
Interrupts occur at random times during the execution of a program, in response to signals from hardware. System
hardware uses interrupts to handle events external to the processor, such as requests to service peripheral devices.
Software can also generate interrupts by executing the INT n instruction.
Exceptions occur when the processor detects an error condition while executing an instruction, such as division by
zero. The processor detects a variety of error conditions including protection violations, page faults, and internal
machine faults. The machine-check architecture of the Pentium 4, Intel Xeon, P6 family, and Pentium processors
also permits a machine-check exception to be generated when internal hardware errors and bus errors are
detected.
When an interrupt is received or an exception is detected, the currently running procedure or task is suspended
while the processor executes an interrupt or exception handler. When execution of the handler is complete, the
processor resumes execution of the interrupted procedure or task. The resumption of the interrupted procedure or
task happens without loss of program continuity, unless recovery from an exception was not possible or an inter-
rupt caused the currently running program to be terminated.
This chapter describes the processor’s interrupt and exception-handling mechanism, when operating in protected
mode. A description of the exceptions and the conditions that cause them to be generated is given at the end of this
chapter.
6.2
EXCEPTION AND INTERRUPT VECTORS
To aid in handling exceptions and interrupts, each architecturally defined exception and each interrupt condition
requiring special handling by the processor is assigned a unique identification number, called a vector number. The
processor uses the vector number assigned to an exception or interrupt as an index into the interrupt descriptor
table (IDT). The table provides the entry point to an exception or interrupt handler (see Section 6.10, “Interrupt
Descriptor Table (IDT)”).
The allowable range for vector numbers is 0 to 255. Vector numbers in the range 0 through 31 are reserved by the
Intel 64 and IA-32 architectures for architecture-defined exceptions and interrupts. Not all of the vector numbers
in this range have a currently defined function. The unassigned vector numbers in this range are reserved. Do not
use the reserved vector numbers.
Vector numbers in the range 32 to 255 are designated as user-defined interrupts and are not reserved by the Intel
64 and IA-32 architecture. These interrupts are generally assigned to external I/O devices to enable those devices
to send interrupts to the processor through one of the external hardware interrupt mechanisms (see Section 6.3,
“Sources of Interrupts”).
Vol. 3A
6-1
INTERRUPT AND EXCEPTION HANDLING
Table 6-1 shows vector number assignments for architecturally defined exceptions and for the NMI interrupt. This
table gives the exception type (see Section 6.5, “Exception Classifications”) and indicates whether an error code is
saved on the stack for the exception. The source of each predefined exception and the NMI interrupt is also given.
6.3
SOURCES OF INTERRUPTS
The processor receives interrupts from two sources:
• External (hardware generated) interrupts.
• Software-generated interrupts.
6.3.1
External Interrupts
External interrupts are received through pins on the processor or through the local APIC. The primary interrupt pins
on Pentium 4, Intel Xeon, P6 family, and Pentium processors are the LINT[1:0] pins, which are connected to the
local APIC (see Chapter 11, “Advanced Programmable Interrupt Controller (APIC)”). When the local APIC is
enabled, the LINT[1:0] pins can be programmed through the APIC’s local vector table (LVT) to be associated with
any of the processor’s exception or interrupt vectors.
When the local APIC is global/hardware disabled, these pins are configured as INTR and NMI pins, respectively.
Asserting the INTR pin signals the processor that an external interrupt has occurred. The processor reads from the
system bus the interrupt vector number provided by an external interrupt controller, such as an 8259A (see Section
6.2, “Exception and Interrupt Vectors”). Asserting the NMI pin signals a non-maskable interrupt (NMI), which is
assigned to interrupt vector 2.
Table 6-1. Protected-Mode Exceptions and Interrupts
Vector
Mnemonic
Description
Type
Error
Source
Code
0
#DE
Divide Error
Fault
No
DIV and IDIV instructions.
1
#DB
Debug Exception
Fault/ Trap
No
Instruction, data, and I/O breakpoints;
single-step; and others.
2
-
NMI Interrupt
Interrupt
No
Nonmaskable external interrupt.
3
#BP
Breakpoint
Trap
No
INT3 instruction.
4
#OF
Overflow
Trap
No
INTO instruction.
5
#BR
BOUND Range Exceeded
Fault
No
BOUND instruction.
6
#UD
Invalid Opcode (Undefined Opcode)
Fault
No
UD instruction or reserved opcode.
7
#NM
Device Not Available (No Math
Fault
No
Floating-point or WAIT/FWAIT instruction.
Coprocessor)
8
#DF
Double Fault
Abort
Yes
Any instruction that can generate an
(zero)
exception, an NMI, or an INTR.
9
Coprocessor Segment Overrun
Fault
No
Floating-point instruction.1
(reserved)
10
#TS
Invalid TSS
Fault
Yes
Task switch or TSS access.
11
#NP
Segment Not Present
Fault
Yes
Loading segment registers or accessing
system segments.
12
#SS
Stack-Segment Fault
Fault
Yes
Stack operations and SS register loads.
13
#GP
General Protection
Fault
Yes
Any memory reference and other
protection checks.
14
#PF
Page Fault
Fault
Yes
Any memory reference.
6-2
Vol. 3A
|
||
|
|
|