|
|
INTERRUPT AND EXCEPTION HANDLING
• If the segment descriptor pointed to by the segment selector in the destination operand is a code segment and
it has both the D-bit and the L-bit set.
• If the segment descriptor from a 64-bit call gate is in non-canonical space.
• If the DPL from a 64-bit call-gate is less than the CPL or than the RPL of the 64-bit call-gate.
• If the type field of the upper 64 bits of a 64-bit call gate is not 0.
• If an attempt is made to load a null selector in the SS register in compatibility mode.
• If an attempt is made to load null selector in the SS register in CPL3 and 64-bit mode.
• If an attempt is made to load a null selector in the SS register in non-CPL3 and 64-bit mode where RPL is not
equal to CPL.
• If an attempt is made to clear CR0.PG while IA-32e mode is enabled.
• If an attempt is made to set a reserved bit in CR3, CR4 or CR8.
Vol. 3A
6-43
INTERRUPT AND EXCEPTION HANDLING
Interrupt 14-Page-Fault Exception (#PF)
Exception Class
Fault.
Description
Indicates that, with paging enabled (the PG flag in the CR0 register is set), the processor detected one of the
following conditions while using the page-translation mechanism to translate a linear address to a physical
address:
• The P (present) flag in a page-directory or page-table entry needed for the address translation is clear,
indicating that a page table or the page containing the operand is not present in physical memory.
• The procedure does not have sufficient privilege to access the indicated page (that is, a procedure running in
user mode attempts to access a supervisor-mode page). If the SMAP flag is set in CR4, a page fault may also
be triggered by code running in supervisor mode that tries to access data at a user-mode address. If either the
PKE flag or the PKS flag is set in CR4, the protection-key rights registers may cause page faults on data
accesses to linear addresses with certain protection keys.
• Code running in user mode attempts to write to a read-only page. If the WP flag is set in CR0, the page fault
will also be triggered by code running in supervisor mode that tries to write to a read-only page.
• An instruction fetch to a linear address that translates to a physical address in a memory page with the
execute-disable bit set (for information about the execute-disable bit, see Chapter 4, “Paging”). If the SMEP
flag is set in CR4, a page fault will also be triggered by code running in supervisor mode that tries to fetch an
instruction from a user-mode address.
• One or more reserved bits in paging-structure entry are set to 1. See description below of RSVD error code flag.
• A shadow-stack access is made to a page that is not a shadow-stack page. See Section 17.2, “Shadow Stacks,”
in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1, and Section 4.6, “Access
Rights.”
• An enclave access violates one of the specified access-control requirements. See Section 35.3, “Access-control
Requirements,” and Section 35.20, “Enclave Page Cache Map (EPCM),” in Chapter 35, “Enclave Access Control
and Data Structures.” In this case, the exception is called an SGX-induced page fault. The processor uses the
error code (below) to distinguish SGX-induced page faults from ordinary page faults.
The exception handler can recover from page-not-present conditions and restart the program or task without any
loss of program continuity. It can also restart the program or task after a privilege violation, but the problem that
caused the privilege violation may be uncorrectable.
See also: Section 4.7, “Page-Fault Exceptions.”
Exception Error Code
Yes (special format). The processor provides the page-fault handler with two items of information to aid in diag-
nosing the exception and recovering from it:
• An error code on the stack. The error code for a page fault has a format different from that for other exceptions
(see Figure 6-11). The processor establishes the bits in the error code as follows:
- P flag (bit 0).
This flag is 0 if there is no translation for the linear address because the P flag was 0 in one of the paging-
structure entries used to translate that address.
- W/R (bit 1).
If the access causing the page-fault exception was a write, this flag is 1; otherwise, it is 0. This flag
describes the access causing the page-fault exception, not the access rights specified by paging.
- U/S (bit 2).
If a user-mode access caused the page-fault exception, this flag is 1; it is 0 if a supervisor-mode access did
so. This flag describes the access causing the page-fault exception, not the access rights specified by
paging.
6-44
Vol. 3A
INTERRUPT AND EXCEPTION HANDLING
- RSVD flag (bit 3).
This flag is 1 if there is no translation for the linear address because a reserved bit was set in one of the
paging-structure entries used to translate that address.
- I/D flag (bit 4).
This flag is 1 if the access causing the page-fault exception was an instruction fetch. This flag describes the
access causing the page-fault exception, not the access rights specified by paging.
- PK flag (bit 5).
This flag is 1 if the access causing the page-fault exception was a data access to a linear address with a
protection key for which the protection-key rights registers disallow access.
- SS (bit 6).
If the access causing the page-fault exception was a shadow-stack access (including shadow-stack
accesses in enclave mode), this flag is 1; otherwise, it is 0. This flag describes the access causing the page-
fault exception, not the access rights specified by paging.
- HLAT (bit 7).
This flag is 1 if there is no translation for the linear address using HLAT paging because, in one of the
paging-structure entries used to translate that address, either the P flag was 0 or a reserved bit was set. An
error code will set this flag only if it clears bit 0 or sets bit 3. This flag will not be set by a page fault resulting
from a violation of access rights, nor for one encountered during ordinary paging, including the case in
which there has been a restart of HLAT paging.
- SGX flag (bit 15).
This flag is 1 if the exception is unrelated to paging and resulted from violation of SGX-specific access-
control requirements. Because such a violation can occur only if there is no ordinary page fault, this flag is
set only if the P flag (bit 0) is 1 and the RSVD flag (bit 3) and the PK flag (bit 5) are both 0.
See Section 4.6, “Access Rights,” and Section 4.7, “Page-Fault Exceptions,” for more information about page-
fault exceptions and the error codes that they produce.
Vol. 3A
6-45
INTERRUPT AND EXCEPTION HANDLING
31
15
7
6
5
4
3
2
1
0
Reserved
Reserved
0 The fault was caused by a non-present page.
P
1 The fault was caused by a page-level protection violation.
W/R
0
The access causing the fault was a read.
1
The access causing the fault was a write.
U/S
0
A supervisor-mode access caused the fault.
1 A user-mode access caused the fault.
0 The fault was not caused by reserved bit violation.
RSVD
1
The fault was caused by a reserved bit set to 1 in some
paging-structure entry.
I/D
0 The fault was not caused by an instruction fetch.
1 The fault was caused by an instruction fetch.
PK
0 The fault was not caused by protection keys.
1 There was a protection-key violation.
SS
0 The fault was not caused by a shadow-stack access.
1 The fault was caused by a shadow-stack access.
HLAT
0 The fault occurred during ordinary paging or due to access rights.
1 The fault occurred during HLAT paging.
SGX
0 The fault is not related to SGX.
1 The fault resulted from violation of SGX-specific access-control
requirements.
Figure 6-11. Page-Fault Error Code
• The contents of the CR2 register. The processor loads the CR2 register with the 32-bit linear address that
generated the exception. The page-fault handler can use this address to locate the corresponding page
directory and page-table entries. Another page fault can potentially occur during execution of the page-fault
handler; the handler should save the contents of the CR2 register before a second page fault can occur.1 If a
page fault is caused by a page-level protection violation, the access flag in the page-directory entry is set when
the fault occurs. The behavior of IA-32 processors regarding the access flag in the corresponding page-table
entry is model specific and not architecturally defined.
Saved Instruction Pointer
The saved contents of CS and EIP registers generally point to the instruction that generated the exception. If the
page-fault exception occurred during a task switch, the CS and EIP registers may point to the first instruction of the
new task (as described in the following “Program State Change” section).
Program State Change
A program-state change does not normally accompany a page-fault exception, because the instruction that causes
the exception to be generated is not executed. After the page-fault exception handler has corrected the violation
(for example, loaded the missing page into memory), execution of the program or task can be resumed.
1. Processors update CR2 whenever a page fault is detected. If a second page fault occurs while an earlier page fault is being deliv-
ered, the faulting linear address of the second fault will overwrite the contents of CR2 (replacing the previous address). These
updates to CR2 occur even if the page fault results in a double fault or occurs during the delivery of a double fault.
6-46
Vol. 3A
INTERRUPT AND EXCEPTION HANDLING
When a page-fault exception is generated during a task switch, the program-state may change, as follows. During
a task switch, a page-fault exception can occur during any of following operations:
• While writing the state of the original task into the TSS of that task.
• While reading the GDT to locate the TSS descriptor of the new task.
• While reading the TSS of the new task.
• While reading segment descriptors associated with segment selectors from the new task.
• While reading the LDT of the new task to verify the segment registers stored in the new TSS.
In the last two cases the exception occurs in the context of the new task. The instruction pointer refers to the first
instruction of the new task, not to the instruction which caused the task switch (or the last instruction to be
executed, in the case of an interrupt). If the design of the operating system permits page faults to occur during
task-switches, the page-fault handler should be called through a task gate.
If a page fault occurs during a task switch, the processor will load all the state information from the new TSS
(without performing any additional limit, present, or type checks) before it generates the exception. The page-fault
handler should thus not rely on being able to use the segment selectors found in the CS, SS, DS, ES, FS, and GS
registers without causing another exception. (See the Program State Change description for “Interrupt 10-Invalid
TSS Exception (#TS)” in this chapter for additional information on how to handle this situation.)
Additional Exception-Handling Information
Special care should be taken to ensure that an exception that occurs during an explicit stack switch does not cause
the processor to use an invalid stack pointer (SS:ESP). Software written for 16-bit IA-32 processors often use a
pair of instructions to change to a new stack, for example:
MOV SS, AX
MOV SP, StackTop
When executing this code on one of the 32-bit IA-32 processors, it is possible to get a page fault, general-protec-
tion fault (#GP), or alignment check fault (#AC) after the segment selector has been loaded into the SS register
but before the ESP register has been loaded. At this point, the two parts of the stack pointer (SS and ESP) are
inconsistent. The new stack segment is being used with the old stack pointer.
The processor does not use the inconsistent stack pointer if the exception handler switches to a well defined stack
(that is, the handler is a task or a more privileged procedure). However, if the exception handler is called at the
same privilege level and from the same task, the processor will attempt to use the inconsistent stack pointer.
In systems that handle page-fault, general-protection, or alignment check exceptions within the faulting task (with
trap or interrupt gates), software executing at the same privilege level as the exception handler should initialize a
new stack by using the LSS instruction rather than a pair of MOV instructions, as described earlier in this note.
When the exception handler is running at privilege level 0 (the normal case), the problem is limited to procedures
or tasks that run at privilege level 0, typically the kernel of the operating system.
Vol. 3A
6-47
INTERRUPT AND EXCEPTION HANDLING
Interrupt 16-x87 FPU Floating-Point Error (#MF)
Exception Class
Fault.
Description
Indicates that the x87 FPU has detected a floating-point error. The NE flag in the register CR0 must be set for an
interrupt 16 (floating-point error exception) to be generated. (See Section 2.5, “Control Registers,” for a detailed
description of the NE flag.)
NOTE
SIMD floating-point exceptions (#XM) are signaled through interrupt 19.
While executing x87 FPU instructions, the x87 FPU detects and reports six types of floating-point error conditions:
• Invalid operation (#I)
- Stack overflow or underflow (#IS)
- Invalid arithmetic operation (#IA)
• Divide-by-zero (#Z)
• Denormalized operand (#D)
• Numeric overflow (#O)
• Numeric underflow (#U)
• Inexact result (precision) (#P)
Each of these error conditions represents an x87 FPU exception type, and for each of exception type, the x87 FPU
provides a flag in the x87 FPU status register and a mask bit in the x87 FPU control register. If the x87 FPU detects
a floating-point error and the mask bit for the exception type is set, the x87 FPU handles the exception automati-
cally by generating a predefined (default) response and continuing program execution. The default responses have
been designed to provide a reasonable result for most floating-point applications.
If the mask for the exception is clear and the NE flag in register CR0 is set, the x87 FPU does the following:
1. Sets the necessary flag in the FPU status register.
2. Waits until the next “waiting” x87 FPU instruction or WAIT/FWAIT instruction is encountered in the program’s
instruction stream.
3. Generates an internal error signal that cause the processor to generate a floating-point exception (#MF).
Prior to executing a waiting x87 FPU instruction or the WAIT/FWAIT instruction, the x87 FPU checks for pending x87
FPU floating-point exceptions (as described in step 2 above). Pending x87 FPU floating-point exceptions are
ignored for “non-waiting” x87 FPU instructions, which include the FNINIT, FNCLEX, FNSTSW, FNSTSW AX, FNSTCW,
FNSTENV, and FNSAVE instructions. Pending x87 FPU exceptions are also ignored when executing the state
management instructions FXSAVE and FXRSTOR.
All of the x87 FPU floating-point error conditions can be recovered from. The x87 FPU floating-point-error exception
handler can determine the error condition that caused the exception from the settings of the flags in the x87 FPU
status word. See “Software Exception Handling” in Chapter 8 of the Intel® 64 and IA-32 Architectures Software
Developer’s Manual, Volume 1, for more information on handling x87 FPU floating-point exceptions.
Exception Error Code
None. The x87 FPU provides its own error information.
Saved Instruction Pointer
The saved contents of CS and EIP registers point to the floating-point or WAIT/FWAIT instruction that was about to
be executed when the floating-point-error exception was generated. This is not the faulting instruction in which the
error condition was detected. The address of the faulting instruction is contained in the x87 FPU instruction pointer
6-48
Vol. 3A
INTERRUPT AND EXCEPTION HANDLING
register. See Section 8.1.8, “x87 FPU Instruction and Data (Operand) Pointers,” in Chapter 8 of the Intel® 64 and
IA-32 Architectures Software Developer’s Manual, Volume 1, for more information about information the FPU saves
for use in handling floating-point-error exceptions.
Program State Change
A program-state change generally accompanies an x87 FPU floating-point exception because the handling of the
exception is delayed until the next waiting x87 FPU floating-point or WAIT/FWAIT instruction following the faulting
instruction. The x87 FPU, however, saves sufficient information about the error condition to allow recovery from the
error and re-execution of the faulting instruction if needed.
In situations where non- x87 FPU floating-point instructions depend on the results of an x87 FPU floating-point
instruction, a WAIT or FWAIT instruction can be inserted in front of a dependent instruction to force a pending x87
FPU floating-point exception to be handled before the dependent instruction is executed. See “x87 FPU Exception
Synchronization” in Chapter 8 of the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1, for
more information about synchronization of x87 floating-point-error exceptions.
Vol. 3A
6-49
INTERRUPT AND EXCEPTION HANDLING
Interrupt 17-Alignment Check Exception (#AC)
Exception Class
Fault.
Description
Indicates that the processor detected an unaligned memory operand when alignment checking was enabled. Align-
ment checks are only carried out in data (or stack) accesses (not in code fetches or system segment accesses). An
example of an alignment-check violation is a word stored at an odd byte address, or a doubleword stored at an
address that is not an integer multiple of 4. Table 6-7 lists the alignment requirements various data types recog-
nized by the processor.
Table 6-7. Alignment Requirements by Data Type
Data Type
Address Must Be Divisible By
Word
2
Doubleword
4
Single precision floating-point (32-bits)
4
Double precision floating-point (64-bits)
8
Double extended precision floating-point (80-bits)
8
Quadword
8
Double quadword
16
Segment Selector
2
32-bit Far Pointer
2
48-bit Far Pointer
4
32-bit Pointer
4
GDTR, IDTR, LDTR, or Task Register Contents
4
FSTENV/FLDENV Save Area
4 or 2, depending on operand size
FSAVE/FRSTOR Save Area
4 or 2, depending on operand size
Bit String
2 or 4 depending on the operand-size attribute.
Note that the alignment check exception (#AC) is generated only for data types that must be aligned on word,
doubleword, and quadword boundaries. A general-protection exception (#GP) is generated 128-bit data types that
are not aligned on a 16-byte boundary.
To enable alignment checking, the following conditions must be true:
• AM flag in CR0 register is set.
• AC flag in the EFLAGS register is set.
• The CPL is 3 (including virtual-8086 mode).
Alignment-check exceptions (#AC) are generated only when operating at privilege level 3 (user mode). Memory
references that default to privilege level 0, such as segment descriptor loads, do not generate alignment-check
exceptions, even when caused by a memory reference made from privilege level 3.
Storing the contents of the GDTR, IDTR, LDTR, or task register in memory while at privilege level 3 can generate
an alignment-check exception. Although application programs do not normally store these registers, the fault can
be avoided by aligning the information stored on an even word-address.
The FXSAVE/XSAVE and FXRSTOR/XRSTOR instructions save and restore a 512-byte data structure, the first byte
of which must be aligned on a 16-byte boundary. If the alignment-check exception (#AC) is enabled when
executing these instructions (and CPL is 3), a misaligned memory operand can cause either an alignment-check
exception or a general-protection exception (#GP) depending on the processor implementation (see “FXSAVE-Save
x87 FPU, MMX, SSE, and SSE2 State” and “FXRSTOR-Restore x87 FPU, MMX, SSE, and SSE2 State” in Chapter 3
6-50
Vol. 3A
INTERRUPT AND EXCEPTION HANDLING
of the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2A; see “XSAVE-Save Processor
Extended States” and “XRSTOR-Restore Processor Extended States” in Chapter 6 of the Intel® 64 and IA-32
Architectures Software Developer’s Manual, Volume 2D).
The MOVDQU, MOVUPS, and MOVUPD instructions perform 128-bit unaligned loads or stores. The LDDQU instruc-
tions loads 128-bit unaligned data. They do not generate general-protection exceptions (#GP) when operands are
not aligned on a 16-byte boundary. If alignment checking is enabled, alignment-check exceptions (#AC) may or
may not be generated depending on processor implementation when data addresses are not aligned on an 8-byte
boundary.
FSAVE and FRSTOR instructions can generate unaligned references, which can cause alignment-check faults.
These instructions are rarely needed by application programs.
Exception Error Code
Yes. The error code is null; all bits are clear except possibly bit 0 - EXT; see Section 6.13. EXT is set if the #AC is
recognized during delivery of an event other than a software interrupt (see “INT n/INTO/INT3/INT1-Call to Inter-
rupt Procedure” in Chapter 3 of the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2A).
Saved Instruction Pointer
The saved contents of CS and EIP registers point to the instruction that generated the exception.
Program State Change
A program-state change does not accompany an alignment-check fault, because the instruction is not executed.
Vol. 3A
6-51
INTERRUPT AND EXCEPTION HANDLING
Interrupt 18-Machine-Check Exception (#MC)
Exception Class
Abort.
Description
Indicates that the processor detected an internal machine error or a bus error, or that an external agent detected
a bus error. The machine-check exception is model-specific, available on the Pentium and later generations of
processors. The implementation of the machine-check exception is different between different processor families,
and these implementations may not be compatible with future Intel 64 or IA-32 processors. (Use the CPUID
instruction to determine whether this feature is present.)
Bus errors detected by external agents are signaled to the processor on dedicated pins: the BINIT# and MCERR#
pins on the Pentium 4, Intel Xeon, and P6 family processors and the BUSCHK# pin on the Pentium processor. When
one of these pins is enabled, asserting the pin causes error information to be loaded into machine-check registers
and a machine-check exception is generated.
The machine-check exception and machine-check architecture are discussed in detail in Chapter 16, “Machine-
Check Architecture.” Also, see the data books for the individual processors for processor-specific hardware infor-
mation.
Exception Error Code
None. Error information is provided by machine-check MSRs.
Saved Instruction Pointer
For the Pentium 4 and Intel Xeon processors, the saved contents of extended machine-check state registers are
directly associated with the error that caused the machine-check exception to be generated (see Section 16.3.1.2,
“IA32_MCG_STATUS MSR,” and Section 16.3.2.6, “IA32_MCG Extended Machine Check State MSRs”).
For the P6 family processors, if the EIPV flag in the MCG_STATUS MSR is set, the saved contents of CS and EIP
registers are directly associated with the error that caused the machine-check exception to be generated; if the flag
is clear, the saved instruction pointer may not be associated with the error (see Section 16.3.1.2, “IA32_MC-
G_STATUS MSR”).
For the Pentium processor, contents of the CS and EIP registers may not be associated with the error.
Program State Change
The machine-check mechanism is enabled by setting the MCE flag in control register CR4.
For the Pentium 4, Intel Xeon, P6 family, and Pentium processors, a program-state change always accompanies a
machine-check exception, and an abort class exception is generated. For abort exceptions, information about the
exception can be collected from the machine-check MSRs, but the program cannot generally be restarted.
If the machine-check mechanism is not enabled (the MCE flag in control register CR4 is clear), a machine-check
exception causes the processor to enter the shutdown state.
6-52
Vol. 3A
INTERRUPT AND EXCEPTION HANDLING
Interrupt 19-SIMD Floating-Point Exception (#XM)
Exception Class
Fault.
Description
Indicates the processor has detected an SSE/SSE2/SSE3 SIMD floating-point exception. The appropriate status
flag in the MXCSR register must be set and the particular exception unmasked for this interrupt to be generated.
There are six classes of numeric exception conditions that can occur while executing an SSE/ SSE2/SSE3 SIMD
floating-point instruction:
• Invalid operation (#I)
• Divide-by-zero (#Z)
• Denormal operand (#D)
• Numeric overflow (#O)
• Numeric underflow (#U)
• Inexact result (Precision) (#P)
The invalid operation, divide-by-zero, and denormal-operand exceptions are pre-computation exceptions; that is,
they are detected before any arithmetic operation occurs. The numeric underflow, numeric overflow, and inexact
result exceptions are post-computational exceptions.
See “SIMD Floating-Point Exceptions” in Chapter 11 of the Intel® 64 and IA-32 Architectures Software Developer’s
Manual, Volume 1, for additional information about the SIMD floating-point exception classes.
When a SIMD floating-point exception occurs, the processor does either of the following things:
• It handles the exception automatically by producing the most reasonable result and allowing program
execution to continue undisturbed. This is the response to masked exceptions.
• It generates a SIMD floating-point exception, which in turn invokes a software exception handler. This is the
response to unmasked exceptions.
Each of the six SIMD floating-point exception conditions has a corresponding flag bit and mask bit in the MXCSR
register. If an exception is masked (the corresponding mask bit in the MXCSR register is set), the processor takes
an appropriate automatic default action and continues with the computation. If the exception is unmasked (the
corresponding mask bit is clear) and the operating system supports SIMD floating-point exceptions (the OSXM-
MEXCPT flag in control register CR4 is set), a software exception handler is invoked through a SIMD floating-point
exception. If the exception is unmasked and the OSXMMEXCPT bit is clear (indicating that the operating system
does not support unmasked SIMD floating-point exceptions), an invalid opcode exception (#UD) is signaled instead
of a SIMD floating-point exception.
Note that because SIMD floating-point exceptions are precise and occur immediately, the situation does not arise
where an x87 FPU instruction, a WAIT/FWAIT instruction, or another SSE/SSE2/SSE3 instruction will catch a
pending unmasked SIMD floating-point exception.
In situations where a SIMD floating-point exception occurred while the SIMD floating-point exceptions were
masked (causing the corresponding exception flag to be set) and the SIMD floating-point exception was subse-
quently unmasked, then no exception is generated when the exception is unmasked.
When SSE/SSE2/SSE3 SIMD floating-point instructions operate on packed operands (made up of two or four sub-
operands), multiple SIMD floating-point exception conditions may be detected. If no more than one exception
condition is detected for one or more sets of sub-operands, the exception flags are set for each exception condition
detected. For example, an invalid exception detected for one sub-operand will not prevent the reporting of a divide-
by-zero exception for another sub-operand. However, when two or more exceptions conditions are generated for
one sub-operand, only one exception condition is reported, according to the precedences shown in Table 6-8. This
exception precedence sometimes results in the higher priority exception condition being reported and the lower
priority exception conditions being ignored.
Vol. 3A
6-53
INTERRUPT AND EXCEPTION HANDLING
Table 6-8. SIMD Floating-Point Exceptions Priority
Priority
Description
1 (Highest)
Invalid operation exception due to SNaN operand (or any NaN operand for maximum, minimum, or certain compare and
convert operations).
2
QNaN operand1.
3
Any other invalid operation exception not mentioned above or a divide-by-zero exception2.
4
Denormal operand exception2.
5
Numeric overflow and underflow exceptions possibly in conjunction with the inexact result exception2.
6 (Lowest)
Inexact result exception.
NOTES:
1. Though a QNaN this is not an exception, the handling of a QNaN operand has precedence over lower priority exceptions. For exam-
ple, a QNaN divided by zero results in a QNaN, not a divide-by-zero- exception.
2. If masked, then instruction execution continues, and a lower priority exception can occur as well.
Exception Error Code
None.
Saved Instruction Pointer
The saved contents of CS and EIP registers point to the SSE/SSE2/SSE3 instruction that was executed when the
SIMD floating-point exception was generated. This is the faulting instruction in which the error condition was
detected.
Program State Change
A program-state change does not accompany a SIMD floating-point exception because the handling of the excep-
tion is immediate unless the particular exception is masked. The available state information is often sufficient to
allow recovery from the error and re-execution of the faulting instruction if needed.
6-54
Vol. 3A
INTERRUPT AND EXCEPTION HANDLING
Interrupt 20-Virtualization Exception (#VE)
Exception Class
Fault.
Description
Indicates that the processor detected an EPT violation in VMX non-root operation. Not all EPT violations cause
virtualization exceptions. See Section 26.5.7.2 for details.
The exception handler can recover from EPT violations and restart the program or task without any loss of program
continuity. In some cases, however, the problem that caused the EPT violation may be uncorrectable.
Exception Error Code
None.
Saved Instruction Pointer
The saved contents of CS and EIP registers generally point to the instruction that generated the exception.
Program State Change
A program-state change does not normally accompany a virtualization exception, because the instruction that
causes the exception to be generated is not executed. After the virtualization exception handler has corrected the
violation (for example, by executing the EPTP-switching VM function), execution of the program or task can be
resumed.
Additional Exception-Handling Information
The processor saves information about virtualization exceptions in the virtualization-exception information area.
See Section 26.5.7.2 for details.
Vol. 3A
6-55
INTERRUPT AND EXCEPTION HANDLING
Interrupt 21-Control Protection Exception (#CP)
Exception Class
Fault.
Description
Indicates a control flow transfer attempt violated the control flow enforcement technology constraints.
Exception Error Code
Yes (special format). The processor provides the control protection exception handler with following information
through the error code on the stack.
31
15 14
0
ENCL
CPEC
Reserved
Figure 6-12. Exception Error Code Information
• Bit 14:0 - CPEC
- 1 - NEAR-RET: Indicates the #CP was caused by a near RET instruction.
- 2 - FAR-RET/IRET: Indicates the #CP was caused by a FAR RET or IRET instruction.
- 3 - ENDBRANCH: indicates the #CP was due to missing ENDBRANCH at target of an indirect call or jump
instruction.
- 4 - RSTORSSP: Indicates the #CP was caused by a shadow-stack-restore token check failure in the
RSTORSSP instruction.
- 5- SETSSBSY: Indicates #CP was caused by a supervisor shadow stack token check failure in the SETSSBSY
instruction.
• Bit 15 (ENCL) of the error code, if set to 1, indicates the #CP occurred during enclave execution.
Saved Instruction Pointer
The saved contents of the CS and EIP registers generally point to the instruction that generated the exception.
Program State Change
A program-state change does not normally accompany a control protection exception, because the instruction that
causes the exception to be generated is not executed.
When a control protection exception is generated during a task switch, the program-state may change as follows.
During a task switch, a control protection exception can occur during any of following operations:
• If task switch is initiated by IRET, CS and LIP stored on old task shadow stack do not match CS and LIP of new
task (where LIP is the linear address of the return address).
• If task switch is initiated by IRET and SSP of new task loaded from shadow stack of old task (if new task CPL is
< 3), OR the SSP from IA32_PL3_SSP (if new task CPL = 3) is not aligned to 4 bytes or is a value beyond 4GB.
6-56
Vol. 3A
INTERRUPT AND EXCEPTION HANDLING
In these cases the exception occurs in the context of the new task. The instruction pointer refers to the first instruc-
tion of the new task, not to the instruction which caused the task switch (or the last instruction to be executed, in
the case of an interrupt). If the design of the operating system permits control protection faults to occur during
task-switches, the control protection fault handler should be called through a task gate.
Vol. 3A
6-57
INTERRUPT AND EXCEPTION HANDLING
Interrupts 32 to 255-User Defined Interrupts
Exception Class
Not applicable.
Description
Indicates that the processor did one of the following things:
• Executed an INT n instruction where the instruction operand is one of the vector numbers from 32 through 255.
• Responded to an interrupt request at the INTR pin or from the local APIC when the interrupt vector number
associated with the request is from 32 through 255.
Exception Error Code
Not applicable.
Saved Instruction Pointer
The saved contents of CS and EIP registers point to the instruction that follows the INT n instruction or instruction
following the instruction on which the INTR signal occurred.
Program State Change
A program-state change does not accompany interrupts generated by the INT n instruction or the INTR signal. The
INT n instruction generates the interrupt within the instruction stream. When the processor receives an INTR
signal, it commits all state changes for all previous instructions before it responds to the interrupt; so, program
execution can resume upon returning from the interrupt handler.
6-58
Vol. 3A
CHAPTER 7
USER INTERRUPTS
7.1
INTRODUCTION
This chapter provides details of an architectural feature called user interrupts.
This feature defines user interrupts as new events in the architecture. User interrupts are delivered to software
operating in 64-bit mode with CPL = 3 without any change to segmentation state. An individual user interrupt is
identified by a 6-bit user-interrupt vector, which is pushed on the stack as part of user-interrupt delivery. The
UIRET (user-interrupt return) instruction reverses user-interrupt delivery.
System software configures the user-interrupt architecture with MSRs. An operating system (OS) may update the
content of some of these MSRs when switching between OS-managed threads.
One of these MSRs references a data structure called the user posted-interrupt descriptor (UPID). User inter-
rupts for an OS-managed thread can be posted in the UPID associated with that thread. Such user interrupts will
be delivered after receipt of an ordinary interrupt (identified in the UPID) called a user-interrupt notification.1
System software can define operations to post user interrupts and to send user-interrupt notifications. In addition,
the user-interrupt feature defines the SENDUIPI instruction, by which application software can send interprocessor
user interrupts (user IPIs). An execution of SENDUIPI posts a user interrupt in a UPID and may send a user-inter-
rupt notification.
(Platforms may include mechanisms to process external interrupts as either ordinary interrupts or user interrupts.
Those processed as user interrupts would be posted in UPIDs and may result in user-interrupt notifications.
Specifics of such mechanisms are outside of the scope of this manual.)
Section 7.2 explains how a processor enumerates support for user interrupts and how they are enabled by system
software. Section 7.3 identifies the new processor state defined for user interrupts. Section 7.4 explains how a
processor identifies and delivers user interrupts. Section 7.5 describes how a processor identifies and processes
user-interrupt notifications. Section 7.6 enumerates new instructions that support management of user interrupts.
Section 7.7 defines new support for user inter-processor interrupts (user IPIs).
7.2
ENUMERATION AND ENABLING
Software enables user interrupts by setting bit 25 (UINTR) in control register CR4. Setting CR4.UINTR enables
user-interrupt delivery (Section 7.4.2), user-interrupt notification identification (Section 7.5.1), and the user-inter-
rupt instructions (Section 7.6). It does not affect the accessibility of the user-interrupt MSRs (Section 7.3) by
RDMSR, WRMSR or the XSAVE feature set.
Processor support for user interrupts is enumerated by CPUID.(EAX=7,ECX=0):EDX[5]. If this bit is set, software
can set CR4.UINTR to 1 and can access the user-interrupt MSRs using RDMSR and WRMSR (see Section 7.3).
The user-interrupt feature is XSAVE-managed (see Section 13.5). This implies that aspects of the feature are
enumerated as part of enumeration of the XSAVE feature set. See Section 13.5.11 in the Intel® 64 and IA-32 Archi-
tectures Software Developer’s Manual, Volume 1, for details.
7.3
USER-INTERRUPT STATE AND USER-INTERRUPT MSRS
The user-interrupt architecture defines the following new state. Some of this state can be accessed via the RDMSR
and WRMSR instructions (through new user-interrupt MSRs detailed in Section 7.3.2) and some can be accessed
using instructions described in Section 7.6.
1. For clarity, this chapter uses the term ordinary interrupts to refer to those events in the existing interrupt architecture, which are
typically delivered to system software operating with CPL = 0.
Vol. 3A
7-1
USER INTERRUPTS
7.3.1
User-Interrupt State
The following are the elements of the user-interrupt state (listed here independent of how they are accessed):
•
UIRR: user-interrupt request register.
This value includes one bit for each of the 64 user-interrupt vectors. If UIRR[i] = 1, a user interrupt with
vector i is requesting service. The notation UIRRV is used to refer to the position of the most significant bit
set in UIRR; if UIRR = 0, UIRRV = 0.
•
UIF: user-interrupt flag.
If UIF = 0, user-interrupt delivery is blocked; if UIF = 1, user interrupts may be delivered. User-interrupt
delivery clears UIF, and the new UIRET instruction sets it. Section 7.6 defines other instructions for accessing
UIF.
•
UIHANDLER: user-interrupt handler.
This is the linear address of the user-interrupt handler. User-interrupt delivery loads this address into RIP.
•
UISTACKADJUST: user-interrupt stack adjustment.
This value controls adjustment to the stack pointer (RSP) prior to user-interrupt delivery. It can be configured
to load RSP with an alternate stack pointer or configured to prevent user-interrupt delivery from overwriting
data above the current stack top.
The value UISTACKADJUST must be canonical. If bit 0 is 1, user-interrupt delivery loads RSP with UISTACK-
ADJUST; otherwise, it subtracts UISTACKADJUST from RSP. Either way, user-interrupt delivery then aligns
RSP to a 16-byte boundary. See Section 7.4.2 for details.
•
UINV: user-interrupt notification vector.
This is the vector of the ordinary interrupts that are treated as user-interrupt notifications (Section 7.5.1).
When the logical processor receives user-interrupt notification, it processes the user interrupts in the user
posted-interrupt descriptor (UPID) referenced by UPIDADDR (see below and Section 7.5.2).
•
UPIDADDR: user posted-interrupt descriptor address.
This is the linear address of the UPID that the logical processor consults upon receiving an ordinary interrupt
with vector UINV.
•
UITTADDR: user-interrupt target table address.
This is the linear address of user-interrupt target table (UITT), which the logical processor consults when
software executes the SENDUIPI instruction (see Section 7.7).
•
UITTSZ: user-interrupt target table size.
This value is the highest index of a valid entry in the UITT (see Section 7.7).
7.3.2
User-Interrupt MSRs
Some of the state elements identified in Section 7.3.1 can be accessed as user-interrupt MSRs using the RDMSR
and WRMSR instructions:
• IA32_UINTR_RR MSR (MSR address 985H). This MSR is an interface to UIRR (64 bits).
Following a WRMSR to this MSR, the logical processor recognizes a pending user interrupt if and only if some bit
is set in the MSR.
• IA32_UINTR_HANDLER MSR (MSR address 986H). This MSR is an interface to the UIHANDLER address. This is
a linear address that must be canonical relative to the maximum linear-address width supported by the
processor.1 WRMSR to this MSR causes a general-protection fault (#GP) if its source operand does not meet
this requirement.
• IA32_UINTR_STACKADJUST MSR (MSR address 987H). This MSR is an interface to the UISTACKADJUST value.
This value includes a linear address that must be canonical relative to the maximum linear-address width
supported by the processor. WRMSR to this MSR causes a #GP if its source operand does not meet this
requirement.
1. CPUID.80000008H:EAX[15:8] enumerates the maximum linear-address width supported by the processor.
7-2
Vol. 3A
USER INTERRUPTS
Bit 0 of this MSR corresponds to UISTACKADJUST[0], which controls how user-interrupt delivery updates the
stack pointer. WRMSR may set it to either 0 or 1.
• IA32_UINTR_MISC MSR (MSR address 988H). This MSR is an interface to the UITTSZ and UINV values. The
MSR has the following format:
- Bits 31:0 are UITTSZ.
- Bits 39:32 are UINV.
- Bits 63:40 are reserved. WRMSR causes a #GP if it would set any of those bits (if
EDX[31:8] ≠ 000000H).
Because this MSR will share an 8-byte portion of the XSAVE area with UIF (see Section 13.5.11 of Intel® 64
and IA-32 Architectures Software Developer’s Manual, Volume 1), bit 63 of the MSR will never be used and
will always be reserved.
• IA32_UINTR_PD MSR (MSR address 989H). This MSR is an interface to the UPIDADDR address. This is a linear
address that must be canonical relative to the maximum linear-address width supported by the processor.
WRMSR to this MSR causes a #GP if its source operand does not meet this requirement.
Bits 5:0 of this MSR are reserved. WRMSR causes a #GP if it would set any of those bits (if
EAX[5:0] ≠ 000000b).
• IA32_UINTR_TT MSR (MSR address 98AH). This MSR is an interface to the UITTADDR address (in addition, bit
0 enables SENDUIPI).
Bit 63:4 of this MSR holds the current value of UITTADDR. This a linear address that must be canonical relative
to the maximum linear-address width supported by the processor. WRMSR to this MSR causes a #GP if its
source operand does not meet this requirement.
Bits 3:1 of this MSR are reserved. WRMSR causes a #GP if it would set any of those bits (if EAX[3:1] ≠ 000b).
Bit 0 of this MSR determines whether the SENDUIPI instruction is enabled. WRMSR may set it to either 0 or 1.
7.4
EVALUATION AND DELIVERY OF USER INTERRUPTS
A processor determines whether there is a user interrupt to deliver based on UIRR. Section 7.4.1 describes this
recognition of pending user interrupts. Once a logical processor has recognized a pending user interrupt, it will
deliver it on a subsequent instruction boundary by causing a control-flow change asynchronous to software execu-
tion. Section 7.4.2 details this process of user-interrupt delivery.
7.4.1
User-Interrupt Recognition
There is a user interrupt pending whenever UIRR ≠ 0.
Any instruction or operation that modifies UIRR updates the logical processor’s recognition of a pending user inter-
rupt. The following instructions and operations may do this:
• WRMSR to the IA32_UINTR_RR MSR (Section 7.3).
• XRSTORS of the user-interrupt state component.
• User-interrupt delivery (Section 7.4.2).
• User-interrupt notification processing (Section 7.5.2).
• VMX transitions that load the IA32_UINTR_RR MSR.
Each of these instructions or operations results in recognition of a pending user interrupt if it completes with
UIRR ≠ 0; if it completes with UIRR = 0, no pending user interrupt is recognized.
Once recognized, a pending user interrupt may be delivered to software; see Section 7.4.2.
Vol. 3A
7-3
USER INTERRUPTS
7.4.2
User-Interrupt Delivery
If CR4.UINTR = 1 and a user interrupt has been recognized (see Section 7.4.1), it will be delivered at an instruction
boundary when the following conditions all hold: (1) UIF = 1; (2) there is no blocking by MOV SS or by POP SS1;
(3) CPL = 3; (4) IA32_EFER.LMA = CS.L = 1 (the logical processor is in 64-bit mode); and (5) software is not
executing inside an enclave.
User-interrupt delivery has priority just below that of ordinary interrupts. It wakes a logical processor from the
states entered using the TPAUSE and UMWAIT instructions2; it does not wake a logical processor in the shutdown
state or in the wait-for-SIPI state.
User-interrupt delivery does not change CPL (it occurs entirely with CPL = 3). The following pseudocode details the
behavior of user-interrupt delivery:
IF UIHANDLER is not canonical in current paging mode
THEN #GP(0);
FI;
holdRSP := RSP;
IF UISTACKADJUST[0] = 1
THEN RSP := UISTACKADJUST;
ELSE RSP := RSP - UISTACKADJUST;
FI;
RSP := RSP & ~FH;
// force the stack to be 16-byte aligned
Push holdRSP;
Push RFLAGS;
Push RIP;
Push UIRRV;
// 64-bit push; upper 58 bits pushed as 0
IF shadow stack is enabled for CPL = 3
THEN ShadowStackPush RIP;
FI;
IF end-branch is enabled for CPL = 3
THEN IA32_U_CET.TRACKER := WAIT_FOR_ENDBRANCH;
FI;
UIRR[Vector] := 0;
IF UIRR = 0
THEN cease recognition of any pending user interrupt;
FI;
UIF := 0;
RFLAGS.TF := 0;
RFLAGS.RF := 0;
RIP := UIHANDLER;
If UISTACKADJUST[0] = 0, user-interrupt delivery decrements RSP by UISTACKADJUST; otherwise, it loads RSP
with UISTACKADJUST. In either case, user-interrupt delivery aligns RSP to a 16-byte boundary by clearing
RSP[3:0].
User-interrupt delivery that occurs during transactional execution causes transactional execution to abort and a
transition to a non-transactional execution. The transactional abort loads EAX as it would had it been due to an
ordinary interrupt. User-interrupt delivery occurs after the transactional abort.
1. Execution of the STI instruction does not block delivery of user interrupts for one instruction as it does ordinary interrupts. If a user
interrupt is delivered immediately following execution of a STI instruction, ordinary interrupts are not blocked after delivery of the
user interrupt.
2. User-interrupt delivery occurs only if CPL = 3. Since the HLT and MWAIT instructions can be executed only if CPL = 0, a user inter-
rupt can never be delivered when a logical processor is an activity state that was entered using one of those instructions.
7-4
Vol. 3A
USER INTERRUPTS
The stack accesses performed by user-interrupt delivery may incur faults (page faults, or stack faults due to
canonicality violations). Before such a fault is delivered, RSP is restored to its original value (memory locations
above the top of the stack may have been written). If such a fault produces an error code that uses the EXT bit,
that bit will be cleared to 0.
If a fault occurs during user-interrupt delivery, UIRR is not updated and UIF is not cleared and, as a result, the
logical processor continues to recognize that a user interrupt is pending, and user-interrupt delivery will normally
recur after the fault is handled.
If the shadow-stack feature of control-flow enforcement technology (CET) is enabled for CPL = 3, user-interrupt
delivery pushes the return instruction pointer on the shadow stack. If indirect-branch-tracking feature of CET is
enabled, user-interrupt delivery transitions the indirect branch tracker to the WAIT_FOR_ENDBRANCH state; an
ENDBR64 instruction is expected as first instruction of the user-interrupt handler.
User-interrupt delivery can be tracked by Architectural Last Branch Records (LBRs), Intel® Processor Trace (Intel®
PT), and Performance Monitoring. For both Intel PT and LBRs, user-interrupt delivery is recorded in precisely the
same manner as ordinary interrupt delivery. Hence for LBRs, user interrupts fall into the OTHER_BRANCH category,
which implies that IA32_LBR_CTL.OTHER_BRANCH[bit 22] must be set to record user-interrupt delivery, and that
the IA32_LBR_x_INFO.BR_TYPE field will indicate OTHER_BRANCH for any recorded user interrupt. For Intel PT,
control flow tracing must be enabled by setting IA32_RTIT_CTL.BranchEn[bit 13].
User-interrupt delivery will also increment performance counters for which counting
BR_INST_RETIRED.FAR_BRANCH is enabled. Some implementations may have dedicated events for counting
user-interrupt delivery; see processor-specific event lists at https://download.01.org/perfmon/index/.
7.5
USER-INTERRUPT NOTIFICATION IDENTIFICATION AND PROCESSING
User-interrupt posting is the process by which a platform agent (or software operating on a CPU) records user
interrupts in a user posted-interrupt descriptor (UPID) in memory. The platform agent (or software) may send
an ordinary interrupt (called a user-interrupt notification) to the logical processor on which the target of the
user interrupt is operating.
Table 7-1 gives the format of a UPID.
Table 7-1. Format of User Posted-Interrupt Descriptor - UPID
Bit Position(s)
Name
Description
Outstanding notifi-
If this bit is set, there is a notification outstanding for one or more user interrupts in
0
cation
PIR.
If this bit is set, agents (including SENDUIPI) should not send notifications when
1
Suppress notification
posting user interrupts in this descriptor.
User-interrupt notification processing ignores these bits; must be zero for
15:2
Reserved
SENDUIPI.
23:16
Notification vector
Used by agents sending user-interrupt notifications (including SENDUIPI).
User-interrupt notification processing ignores these bits; must be zero for
31:24
Reserved
SENDUIPI.
Target physical APIC ID - used by SENDUIPI.
63:32
Notification destination
In xAPIC mode, bits 47:40 are the 8-bit APIC ID.
In x2APIC mode, the entire field forms the 32-bit APIC ID.
Posted-interrupt
One bit for each user-interrupt vector. There is a user-interrupt request for a vector
127:64
requests (PIR)
if the corresponding bit is 1.
The notation PIR (posted-interrupt requests) refers to the 64 posted-interrupt requests in a UPID.
If an ordinary interrupt arrives while CR4.UINTR = IA32_EFER.LMA = 1, the logical processor determines whether
the interrupt is a user-interrupt notification. This process is called user-interrupt notification identification
and is described in Section 7.5.1.
Once a logical processor has identified a user-interrupt notification, it copies user interrupts in the UPID’s PIR into
UIRR. This process is called user-interrupt notification processing and is described in Section 7.5.2.
Vol. 3A
7-5
USER INTERRUPTS
A logical processor is not interruptible during either user-interrupt notification identification or user-interrupt noti-
fication processing or between those operations (when they occur in succession).
7.5.1
User-Interrupt Notification Identification
If CR4.UINTR = IA32_EFER.LMA = 1, a logical processor performs user-interrupt notification identification when it
receives an ordinary interrupt. The following algorithm describes the response by the processor to an ordinary
maskable interrupt when CR4.UINTR = IA32_EFER.LMA = 11:
1. The local APIC is acknowledged; this provides the processor core with an interrupt vector, V.
2. If V = UINV, the logical processor continues to the next step. Otherwise, an interrupt with vector V is delivered
normally through the IDT; the remainder of this algorithm does not apply and user-interrupt notification
processing does not occur.
3. The processor writes zero to the EOI register in the local APIC; this dismisses the interrupt with vector V = UINV
from the local APIC.
User-interrupt notification identification involves acknowledgment of the local APIC and thus occurs only when
ordinary interrupts are not masked.
If user-interrupt notification identification completes step #3, the logical processor then performs user-interrupt
notification processing as described in Section 7.5.2.
An ordinary interrupt that occurs during transactional execution causes the transactional execution to abort and
transition to a non-transactional execution. This occurs before user-interrupt notification identification.
An ordinary interrupt that occurs while software is executing inside an enclave causes an asynchronous enclave
exit (AEX). This AEX occurs before user-interrupt notification identification.
7.5.2
User-Interrupt Notification Processing
Once a logical processor has identified a user-interrupt notification, it performs user-interrupt notification
processing using the UPID at the linear address in the IA32_UINTR_PD MSR.
The following algorithm describes user-interrupt notification processing:
1. The logical processor clears the outstanding-notification bit (bit 0) in the UPID. This is done atomically so as to
leave the remainder of the descriptor unmodified.
2. The logical processor reads PIR (bits 127:64 of the UPID) into a temporary register and writes all zeros to PIR.
This is done atomically so as to ensure that each bit cleared in PIR is set in the temporary register.
3. If any bit is set in the temporary register, the logical processor sets in UIRR each bit corresponding to a bit set
in the temporary register (e.g., with a logical OR) and recognizes a pending user interrupt (if it has not already
done so).
The logical processor performs the steps above in an uninterruptible manner. Steps #1 and #2 may be combined
into a single atomic step. If step #3 leads to recognition of a user interrupt, the processor may deliver that user
interrupt on the following instruction boundary (see Section 7.4.2).
Although user-interrupt notification processing may occur at any privilege level, all of the memory accesses in
steps #1 and #2 are performed with supervisor privilege.
Step #1 and step #2 each access the UPID using a linear address and may therefore incur faults (page faults, or
general-protection faults due to canonicality violations). If such a fault produces an error code that uses the EXT
bit, that bit will be set to 1.
If a fault occurs during user-interrupt notification processing, updates to architectural state performed by the
earlier user-interrupt notification identification (Section 7.5.1) remain committed and are not undone; if such a
fault occurs at step #2 (if it is not performed atomically with step #1), any update to architectural state performed
by step #1 also remains committed. System software is advised to prevent such faults (e.g., by ensuring that no
1. If the interrupt arrives between iterations of a REP-prefixed string instruction, the processor first updates state as follows: RIP is
loaded to reference the string instruction; RCX, RSI, and RDI are updated as appropriate to reflect the iterations completed; and
RFLAGS.RF is set to 1.
7-6
Vol. 3A
USER INTERRUPTS
page fault occurs and that the linear address in the IA32_UINTR_PD MSR is canonical with respect to the paging
mode in use).
If the user-interrupt notification identification that precedes user-interrupt notification processing occurred due to
an ordinary interrupt that arrived while the logical processor was in the HLT state, the logical processor returns to
the HLT state following user-interrupt notification processing.
7.6
USER-INTERRUPT INSTRUCTIONS
The user-interrupt feature defines instructions for control-flow transfer and access to new state. UIRET is an
instruction to effect a return from a user-interrupt handler. CLUI, STUI, and TESTUI allow software to access UIF.
SENDUIPI sends a user IPI. See Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volumes 2A, 2B,
2C, & 2D for details on the instructions’ operation.
The following items provide high-level overviews of the instructions:
• UIRET pops from the stack the state saved by user-interrupt delivery (see Section 7.4.2) and loads those
values into the corresponding registers (software should pop the user-interrupt vector from the stack before
executing UIRET). Because RIP is one of those registers, UIRET effect a return to the that point from which the
user interrupt was delivered.
• CLUI clears UIF.
• STUI sets UIF.
• TESTUI copies UIF to RFLAGS.CF.
• SENDUIPI is discussed in Section 7.7.
7.7
USER IPIS
The SENDUIPI instruction sends a user interprocessor interrupt (IPI). The instruction uses a data structure called
the user-interrupt target table (UITT). This table is located at the linear address UITTADDR and it comprises
UITTSZ+1 16-byte entries (the values UITTADDR and UITTSZ are defined in Section 7.3.1). SENDUIPI uses the
UITT entry (UITTE) indexed by the instruction’s register operand. Each UITTE has the following format:
• Bit 0: V, a valid bit.
• Bits 7:1 are reserved and must be 0.
• Bits 15:8: UV, the user-interrupt vector (in the range 0-63, so bits 15:14 must be 0).
• Bits 63:16 are reserved.
• Bits 127:64: UPIDADDR, the linear address of a UPID (64-byte aligned, so bits 69:64 must be 0).
SENDUIPI sends a user interrupt by posting a user interrupt with vector V in the UPID referenced by UPIDADDR
and then sending, as an ordinary IPI, any notification interrupt specified in that UPID. Details appear in Intel® 64
and IA-32 Architectures Software Developer’s Manual, Volumes 2A, 2B, 2C, & 2D.
Vol. 3A
7-7
USER INTERRUPTS
7-8
Vol. 3A
CHAPTER 8
TASK MANAGEMENT
This chapter describes the IA-32 architecture’s task management facilities. These facilities are only available when
the processor is running in protected mode.
This chapter focuses on 32-bit tasks and the 32-bit TSS structure. For information on 16-bit tasks and the 16-bit
TSS structure, see Section 8.6, “16-Bit Task-State Segment (TSS).” For information specific to task management in
64-bit mode, see Section 8.7, “Task Management in 64-bit Mode.”
8.1
TASK MANAGEMENT OVERVIEW
A task is a unit of work that a processor can dispatch, execute, and suspend. It can be used to execute a program,
a task or process, an operating-system service utility, an interrupt or exception handler, or a kernel or executive
utility.
The IA-32 architecture provides a mechanism for saving the state of a task, for dispatching tasks for execution, and
for switching from one task to another. When operating in protected mode, all processor execution takes place from
within a task. Even simple systems must define at least one task. More complex systems can use the processor’s
task management facilities to support multitasking applications.
8.1.1
Task Structure
A task is made up of two parts: a task execution space and a task-state segment (TSS). The task execution space
consists of a code segment, a stack segment, and one or more data segments (see Figure 8-1). If an operating
system or executive uses the processor’s privilege-level protection mechanism, the task execution space also
provides a separate stack for each privilege level.
The TSS specifies the segments that make up the task execution space and provides a storage place for task state
information. In multitasking systems, the TSS also provides a mechanism for linking tasks.
A task is identified by the segment selector for its TSS. When a task is loaded into the processor for execution, the
segment selector, base address, limit, and segment descriptor attributes for the TSS are loaded into the task
register (see Section 2.4.4, “Task Register (TR)”).
If paging is implemented for the task, the base address of the page directory used by the task is loaded into control
register CR3.
Vol. 3A
8-1
TASK MANAGEMENT
Code
Segment
Task-State
Data
Segment
Segment
(TSS)
Stack
Segment
(Current Priv.
Level)
Stack Seg.
Priv. Level 0
Stack Seg.
Priv. Level 1
Task Register
Stack
Segment
(Priv. Level 2)
CR3
Figure 8-1. Structure of a Task
8.1.2
Task State
The following items define the state of the currently executing task:
• The task’s current execution space, defined by the segment selectors in the segment registers (CS, DS, SS, ES,
FS, and GS).
• The state of the general-purpose registers.
• The state of the EFLAGS register.
• The state of the EIP register.
• The state of control register CR3.
• The state of the task register.
• The state of the LDTR register.
• The I/O map base address and I/O map (contained in the TSS).
• Stack pointers to the privilege 0, 1, and 2 stacks (contained in the TSS).
• Link to previously executed task (contained in the TSS).
• The state of the shadow stack pointer (SSP).
Prior to dispatching a task, all of these items are contained in the task’s TSS, except the state of the task register.
Also, the complete contents of the LDTR register are not contained in the TSS, only the segment selector for the
LDT.
8.1.3
Executing a Task
Software or the processor can dispatch a task for execution in one of the following ways:
• A explicit call to a task with the CALL instruction.
• A explicit jump to a task with the JMP instruction.
• An implicit call (by the processor) to an interrupt-handler task.
• An implicit call to an exception-handler task.
• A return (initiated with an IRET instruction) when the NT flag in the EFLAGS register is set.
All of these methods for dispatching a task identify the task to be dispatched with a segment selector that points to
a task gate or the TSS for the task. When dispatching a task with a CALL or JMP instruction, the selector in the
instruction may select the TSS directly or a task gate that holds the selector for the TSS. When dispatching a task
8-2
Vol. 3A
TASK MANAGEMENT
to handle an interrupt or exception, the IDT entry for the interrupt or exception must contain a task gate that holds
the selector for the interrupt- or exception-handler TSS.
When a task is dispatched for execution, a task switch occurs between the currently running task and the
dispatched task. During a task switch, the execution environment of the currently executing task (called the task’s
state or context) is saved in its TSS and execution of the task is suspended. The context for the dispatched task is
then loaded into the processor and execution of that task begins with the instruction pointed to by the newly loaded
EIP register. If the task has not been run since the system was last initialized, the EIP will point to the first instruc-
tion of the task’s code; otherwise, it will point to the next instruction after the last instruction that the task
executed when it was last active.
If the currently executing task (the calling task) called the task being dispatched (the called task), the TSS
segment selector for the calling task is stored in the TSS of the called task to provide a link back to the calling task.
For all IA-32 processors, tasks are not recursive. A task cannot call or jump to itself.
Interrupts and exceptions can be handled with a task switch to a handler task. Here, the processor performs a task
switch to handle the interrupt or exception and automatically switches back to the interrupted task upon returning
from the interrupt-handler task or exception-handler task. This mechanism can also handle interrupts that occur
during interrupt tasks.
As part of a task switch, the processor can also switch to another LDT, allowing each task to have a different logical-
to-physical address mapping for LDT-based segments. The page-directory base register (CR3) also is reloaded on a
task switch, allowing each task to have its own set of page tables. These protection facilities help isolate tasks and
prevent them from interfering with one another.
If protection mechanisms are not used, the processor provides no protection between tasks. This is true even with
operating systems that use multiple privilege levels for protection. A task running at privilege level 3 that uses the
same LDT and page tables as other privilege-level-3 tasks can access code and corrupt data and the stack of other
tasks.
Use of task management facilities for handling multitasking applications is optional. Multitasking can be handled in
software, with each software defined task executed in the context of a single IA-32 architecture task.
If shadow stack is enabled, then the SSP of the task is located at the 4 bytes at offset 104 in the 32-bit TSS and is
used by the processor to establish the SSP when a task switch occurs from a task associated with this TSS. Note
that the processor does not write the SSP of the task initiating the task switch to the TSS of that task, and instead
the SSP of the previous task is pushed onto the shadow stack of the new task.
8.2
TASK MANAGEMENT DATA STRUCTURES
The processor defines five data structures for handling task-related activities:
• Task-state segment (TSS).
• Task-gate descriptor.
• TSS descriptor.
• Task register.
• NT flag in the EFLAGS register.
When operating in protected mode, a TSS and TSS descriptor must be created for at least one task, and the
segment selector for the TSS must be loaded into the task register (using the LTR instruction).
8.2.1
Task-State Segment (TSS)
The processor state information needed to restore a task is saved in a system segment called the task-state
segment (TSS). Figure 8-2 shows the format of a TSS for tasks designed for 32-bit CPUs. The fields of a TSS are
divided into two main categories: dynamic fields and static fields.
For information about 16-bit Intel 286 processor task structures, see Section 8.6, “16-Bit Task-State Segment
(TSS).” For information about 64-bit mode task structures, see Section 8.7, “Task Management in 64-bit Mode.”
Vol. 3A
8-3
TASK MANAGEMENT
31
15
0
SSP
104
I/
O Map Base Address
Reserved
T
100
Reserved
LDT Segment Selector
96
Reserved
GS
98
Reserved
FS
88
Reserved
DS
84
Reserved
SS
80
Reserved
CS
76
Reserved
ES
72
EDI
68
ESI
64
EBP
60
ESP
56
EBX
52
EDX
48
ECX
44
EAX
40
EFLAGS
36
EIP
32
CR3 (PDBR)
28
Reserved
SS2
24
ESP2
20
Reserved
SS1
16
ESP1
12
Reserved
SS0
8
ESP0
4
Reserved
Previous Task Link
0
Reserved bits. Set to 0.
Figure 8-2. 32-Bit Task-State Segment (TSS)
The processor updates dynamic fields when a task is suspended during a task switch. The following are dynamic
fields:
• General-purpose register fields - State of the EAX, ECX, EDX, EBX, ESP, EBP, ESI, and EDI registers prior
to the task switch.
• Segment selector fields - Segment selectors stored in the ES, CS, SS, DS, FS, and GS registers prior to the
task switch.
• EFLAGS register field - State of the EFLAGS register prior to the task switch.
8-4
Vol. 3A
TASK MANAGEMENT
• EIP (instruction pointer) field - State of the EIP register prior to the task switch.
• Previous task link field - Contains the segment selector for the TSS of the previous task (updated on a task
switch that was initiated by a call, interrupt, or exception). This field (which is sometimes called the back link
field) permits a task switch back to the previous task by using the IRET instruction.
The processor reads the static fields, but does not normally change them. These fields are set up when a task is
created. The following are static fields:
• LDT segment selector field - Contains the segment selector for the task's LDT.
• CR3 control register field - Contains the base physical address of the page directory to be used by the task.
Control register CR3 is also known as the page-directory base register (PDBR).
• Privilege level-0, -1, and -2 stack pointer fields - These stack pointers consist of a logical address made
up of the segment selector for the stack segment (SS0, SS1, and SS2) and an offset into the stack (ESP0,
ESP1, and ESP2). Note that the values in these fields are static for a particular task; whereas, the SS and ESP
values will change if stack switching occurs within the task.
• T (debug trap) flag (byte 100, bit 0) - When set, the T flag causes the processor to raise a debug exception
when a task switch to this task occurs (see Section 18.3.1.5, “Task-Switch Exception Condition”).
• I/O map base address field - Contains a 16-bit offset from the base of the TSS to the I/O permission bit
map and interrupt redirection bitmap. When present, these maps are stored in the TSS at higher addresses.
The I/O map base address points to the beginning of the I/O permission bit map and the end of the interrupt
redirection bit map. See Chapter 19, “Input/Output,” in the Intel® 64 and IA-32 Architectures Software
Developer’s Manual, Volume 1, for more information about the I/O permission bit map. See Section 21.3,
“Interrupt and Exception Handling in Virtual-8086 Mode,” for a detailed description of the interrupt redirection
bit map.
• Shadow Stack Pointer (SSP) - Contains task's shadow stack pointer. The shadow stack of the task should
have a supervisor shadow stack token at the address pointed to by the task SSP (offset 104). This token will be
verified and made busy when switching to that shadow stack using a CALL/JMP instruction, and made free
when switching out of that task using an IRET instruction.
If paging is used:
• Pages corresponding to the previous task’s TSS, the current task’s TSS, and the descriptor table entries for
each all should be marked as read/write.
• Task switches are carried out faster if the pages containing these structures are present in memory before the
task switch is initiated.
8.2.2
TSS Descriptor
The TSS, like all other segments, is defined by a segment descriptor. Figure 8-3 shows the format of a TSS
descriptor. TSS descriptors may only be placed in the GDT; they cannot be placed in an LDT or the IDT.
An attempt to access a TSS using a segment selector with its TI flag set (which indicates the current LDT) causes
a general-protection exception (#GP) to be generated during CALLs and JMPs; it causes an invalid TSS exception
(#TS) during IRETs. A general-protection exception is also generated if an attempt is made to load a segment
selector for a TSS into a segment register.
The busy flag (B) in the type field indicates whether the task is busy. A busy task is currently running or suspended.
A type field with a value of 1001B indicates an inactive task; a value of 1011B indicates a busy task. Tasks are not
recursive. The processor uses the busy flag to detect an attempt to call a task whose execution has been inter-
rupted. To ensure that there is only one busy flag is associated with a task, each TSS should have only one TSS
descriptor that points to it.
Vol. 3A
8-5
TASK MANAGEMENT
TSS Descriptor
31
24 23 22 2120 19
16 15 14 13 12 11
8
7
0
A
D
Type
Base 31:24
G
0
0
V
Limit
P
P
Base 23:16
4
19:16
L
L
0
1
0
B
1
31
16 15
0
Base Address 15:00
Segment Limit 15:00
0
AVL
Available for use by system software
B
Busy flag
BASE
Segment Base Address
DPL
Descriptor Privilege Level
G
Granularity
LIMIT
Segment Limit
P
Segment Present
TYPE
Segment Type
Figure 8-3. TSS Descriptor
The base, limit, and DPL fields and the granularity and present flags have functions similar to their use in data-
segment descriptors (see Section 3.4.5, “Segment Descriptors”). When the G flag is 0 in a TSS descriptor for a 32-
bit TSS, the limit field must have a value equal to or greater than 67H, one byte less than the minimum size of a
TSS. Attempting to switch to a task whose TSS descriptor has a limit less than 67H generates an invalid-TSS excep-
tion (#TS). A larger limit is required if an I/O permission bit map is included or if the operating system stores addi-
tional data. The processor does not check for a limit greater than 67H on a task switch; however, it does check
when accessing the I/O permission bit map or interrupt redirection bit map.
Any program or procedure with access to a TSS descriptor (that is, whose CPL is numerically equal to or less than
the DPL of the TSS descriptor) can dispatch the task with a call or a jump.
In most systems, the DPLs of TSS descriptors are set to values less than 3, so that only privileged software can
perform task switching. However, in multitasking applications, DPLs for some TSS descriptors may be set to 3 to
allow task switching at the application (or user) privilege level.
8.2.3
TSS Descriptor in 64-bit mode
In 64-bit mode, task switching is not supported, but TSS descriptors still exist. The format of a 64-bit TSS is
described in Section 8.7.
In 64-bit mode, the TSS descriptor is expanded to 16 bytes (see Figure 8-4). This expansion also applies to an LDT
descriptor in 64-bit mode. Table 3-2 provides the encoding information for the segment type field.
8-6
Vol. 3A
TASK MANAGEMENT
TSS (or LDT) Descriptor
31
13 12
8
7
0
Reserved
0
Reserved
12
31
0
Base Address 63:32
8
31
24 23 22 2120 19
16 15 14 13 12 11
8
7
0
A
D
Type
Base 31:24
G
0
0
V
Limit
P
P
Base 23:16
4
19:16
L
L
0
31
16 15
0
Base Address 15:00
Segment Limit 15:00
0
AVL
Available for use by system software
B
Busy flag
BASE
Segment Base Address
DPL
Descriptor Privilege Level
G
Granularity
LIMIT
Segment Limit
P
Segment Present
TYPE
Segment Type
Figure 8-4. Format of TSS and LDT Descriptors in 64-bit Mode
8.2.4
Task Register
The task register holds the 16-bit segment selector and the entire segment descriptor (32-bit base address (64 bits
in IA-32e mode), 16-bit segment limit, and descriptor attributes) for the TSS of the current task (see Figure 2-6).
This information is copied from the TSS descriptor in the GDT for the current task. Figure 8-5 shows the path the
processor uses to access the TSS (using the information in the task register).
The task register has a visible part (that can be read and changed by software) and an invisible part (maintained
by the processor and is inaccessible by software). The segment selector in the visible portion points to a TSS
descriptor in the GDT. The processor uses the invisible portion of the task register to cache the segment descriptor
for the TSS. Caching these values in a register makes execution of the task more efficient. The LTR (load task
register) and STR (store task register) instructions load and read the visible portion of the task register:
The LTR instruction loads a segment selector (source operand) into the task register that points to a TSS descriptor
in the GDT. It then loads the invisible portion of the task register with information from the TSS descriptor. LTR is a
privileged instruction that may be executed only when the CPL is 0. It’s used during system initialization to put an
initial value in the task register. Afterwards, the contents of the task register are changed implicitly when a task
switch occurs.
The STR (store task register) instruction stores the visible portion of the task register in a general-purpose register
or memory. This instruction can be executed by code running at any privilege level in order to identify the currently
running task. However, it is normally used only by operating system software. (If CR4.UMIP = 1, STR can be
executed only when CPL = 0.)
On power up or reset of the processor, segment selector and base address are set to the default value of 0; the limit
is set to FFFFH.
Vol. 3A
8-7
TASK MANAGEMENT
TSS
+
Visible Part
Invisible Part
Task
Selector
Base Address
Segment Limit
Register
GDT
TSS Descriptor
0
Figure 8-5. Task Register
8.2.5
Task-Gate Descriptor
A task-gate descriptor provides an indirect, protected reference to a task (see Figure 8-6). It can be placed in the
GDT, an LDT, or the IDT. The TSS segment selector field in a task-gate descriptor points to a TSS descriptor in the
GDT. The RPL in this segment selector is not used.
The DPL of a task-gate descriptor controls access to the TSS descriptor during a task switch. When a program or
procedure makes a call or jump to a task through a task gate, the CPL and the RPL field of the gate selector pointing
to the task gate must be less than or equal to the DPL of the task-gate descriptor. Note that when a task gate is
used, the DPL of the destination TSS descriptor is not used.
31
16 15 14 13 12 11
8
7
0
D
Type
Reserved
P
P
Reserved
4
L
0
0
1
0
1
31
16 15
0
TSS Segment Selector
Reserved
0
DPL
Descriptor Privilege Level
P
Segment Present
TYPE
Segment Type
Figure 8-6. Task-Gate Descriptor
8-8
Vol. 3A
TASK MANAGEMENT
A task can be accessed either through a task-gate descriptor or a TSS descriptor. Both of these structures satisfy
the following needs:
• Need for a task to have only one busy flag - Because the busy flag for a task is stored in the TSS
descriptor, each task should have only one TSS descriptor. There may, however, be several task gates that
reference the same TSS descriptor.
• Need to provide selective access to tasks - Task gates fill this need, because they can reside in an LDT and
can have a DPL that is different from the TSS descriptor's DPL. A program or procedure that does not have
sufficient privilege to access the TSS descriptor for a task in the GDT (which usually has a DPL of 0) may be
allowed access to the task through a task gate with a higher DPL. Task gates give the operating system greater
latitude for limiting access to specific tasks.
• Need for an interrupt or exception to be handled by an independent task - Task gates may also reside
in the IDT, which allows interrupts and exceptions to be handled by handler tasks. When an interrupt or
exception vector points to a task gate, the processor switches to the specified task.
Figure 8-7 illustrates how a task gate in an LDT, a task gate in the GDT, and a task gate in the IDT can all point to
the same task.
LDT
GDT
TSS
Task Gate
Task Gate
TSS Descriptor
IDT
Task Gate
Figure 8-7. Task Gates Referencing the Same Task
8.3
TASK SWITCHING
The processor transfers execution to another task in one of four cases:
• The current program, task, or procedure executes a JMP or CALL instruction to a TSS descriptor in the GDT.
• The current program, task, or procedure executes a JMP or CALL instruction to a task-gate descriptor in the
GDT or the current LDT.
Vol. 3A
8-9
TASK MANAGEMENT
• An interrupt or exception vector points to a task-gate descriptor in the IDT.
• The current task executes an IRET when the NT flag in the EFLAGS register is set.
JMP, CALL, and IRET instructions, as well as interrupts and exceptions, are all mechanisms for redirecting a
program. The referencing of a TSS descriptor or a task gate (when calling or jumping to a task) or the state of the
NT flag (when executing an IRET instruction) determines whether a task switch occurs.
The processor performs the following operations when switching to a new task:
1.
Obtains the TSS segment selector for the new task as the operand of the JMP or CALL instruction, from a task
gate, or from the previous task link field (for a task switch initiated with an IRET instruction).
2.
Checks that the current (old) task is allowed to switch to the new task. Data-access privilege rules apply to JMP
and CALL instructions. The CPL of the current (old) task and the RPL of the segment selector for the new task
must be less than or equal to the DPL of the TSS descriptor or task gate being referenced. Exceptions,
interrupts (except for those identified in the next sentence), and the IRET and INT1 instructions are permitted
to switch tasks regardless of the DPL of the destination task-gate or TSS descriptor. For interrupts generated by
the INT n, INT3, and INTO instructions, the DPL is checked and a general-protection exception (#GP) results if
it is less than the CPL.1
3.
Checks that the TSS descriptor of the new task is marked present and has a valid limit (greater than or equal
to 67H). If the task switch was initiated by IRET and shadow stacks are enabled at the current CPL, then the
SSP must be aligned to 8 bytes, else a #TS(current task TSS) fault is generated. If CR4.CET is 1, then the TSS
must be a 32 bit TSS and the limit of the new task’s TSS must be greater than or equal to 107 bytes, else a
#TS(new task TSS) fault is generated.
4.
Checks that the new task is available (call, jump, exception, or interrupt) or busy (IRET return).
5.
Checks that the current (old) TSS, new TSS, and all segment descriptors used in the task switch are paged into
system memory.
6.
Saves the state of the current (old) task in the current task’s TSS. The processor finds the base address of the
current TSS in the task register and then copies the states of the following registers into the current TSS: all the
general-purpose registers, segment selectors from the segment registers, the temporarily saved image of the
EFLAGS register, and the instruction pointer register (EIP).
7.
Loads the task register with the segment selector and descriptor for the new task's TSS.
8.
If CET is enabled, the processor performs following shadow stack actions:
Read CS of new task from new task TSS
Read EFLAGS of new task from new task TSS
IF EFLAGS.VM = 1
THEN
new task CPL = 3;
ELSE
new task CPL = CS.RPL;
FI;
pushCsLipSsp = 0
IF task switch was initiated by CALL instruction, exception or interrupt
IF shadow stack enabled at current CPL
IF new task CPL < CPL and current task CPL = 3
THEN
IA32_PL3_SSP = SSP (* user → supervisor *)
ELSE
pushCsLipSsp = 1 (* no privilege change; supv → supv; supv → user *) tempSSP = SSP
1.
The INT1 has opcode F1; the INT n instruction with n=1 has opcode CD 01.
8-10
Vol. 3A
TASK MANAGEMENT
tempSsLIP =CSBASE + EIP
tempSsCS = CS
FI;
FI;
FI;
verifyCsLIP = 0
IF task switch was initiated by IRET
IF shadow stacks enabled at current CPL
IF (CPL of new Task = CPL of current Task) OR
(CPL of new Task < 3 AND CPL of current Task < 3) OR
(CPL or new Task < 3 AND CPL of current task = 3)
(* no privilege change or supervisor → supervisor or user → supervisor IRET *)
tempSsCS = shadow_stack_load 8 bytes from SSP+16;
tempSsLIP = shadow_stack_load 8 bytes from SSP+8;
tempSSP = shadow_stack_load 8 bytes from SSP;
SSP = SSP + 24;
verifyCsLIP = 1
FI;
// Clear busy flag on current shadow stack
IF ( SSP & 0x07 == 0 )
(* SSP must be aligned to 8B *)
THEN
expected_token_value = (SSP & ~0x07) | BUSY_BIT; (* busy - bit 0 - must be set*)
new_token_value
= SSP
(* clear the busy bit *)
shadow_stack_lock_cmpxchg8b(SSP, new_token_value, expected_token_value)
FI;
SSP = 0
FI;
FI;
9.
The TSS state is loaded into the processor. This includes the LDTR register, the PDBR (control register CR3), the
EFLAGS register, the EIP register, the general-purpose registers, and the segment selectors. A fault during the
load of this state may corrupt architectural state. (If paging is not enabled, a PDBR value is read from the new
task's TSS, but it is not loaded into CR3.)
10. If the task switch was initiated with a JMP or IRET instruction, the processor clears the busy (B) flag in the
current (old) task’s TSS descriptor; if initiated with a CALL instruction, an exception, or an interrupt: the busy
(B) flag is left set. (See Table 8-2.)
11. If the task switch was initiated with an IRET instruction, the processor clears the NT flag in a temporarily saved
image of the EFLAGS register; if initiated with a CALL or JMP instruction, an exception, or an interrupt, the NT
flag is left unchanged in the saved EFLAGS image.
12. If the task switch was initiated with a CALL instruction, an exception, or an interrupt, the processor will set the
NT flag in the EFLAGS loaded from the new task. If initiated with an IRET instruction or JMP instruction, the NT
flag will reflect the state of NT in the EFLAGS loaded from the new task (see Table 8-2).
13. If the task switch was initiated with a CALL instruction, JMP instruction, an exception, or an interrupt, the
processor sets the busy (B) flag in the new task’s TSS descriptor; if initiated with an IRET instruction, the busy
(B) flag is left set.
14. The descriptors associated with the segment selectors are loaded and qualified. Any errors associated with this
loading and qualification occur in the context of the new task and may corrupt architectural state.
Vol. 3A
8-11
TASK MANAGEMENT
15. If CET is enabled, the processor performs following shadow stack actions:
IF shadow stack enabled at current CPL OR indirect branch tracking at current CPL
THEN
IF EFLAGS.VM = 1
THEN #TSS(new-Task-TSS);FI;
FI;
IF shadow stack enabled at current CPL
IF task switch initiated by CALL instruction, JMP instruction, interrupt or exception (* switch stack *)
new_SSP ← Load the 4 byte from offset 104 in the TSS
// Verify new SSP to be legal
IF new_SSP & 0x07 != 0
THEN #TSS(New-Task-TSS); FI;
expected_token_value = SSP;
(* busy - bit 0 - must be clear *)
new_token_value
= SSP | BUSY_BIT (* set the busy bit - bit 0*)
IF shadow_stack_lock_cmpxchg8b(SSP, new_token_value,
expected_token_value) != expected_token_value
THEN #TSS(New-Task-TSS); FI;
SSP = new_SSP
IF pushCsLipSsp = 1 (* call, int, exception from user → user or supv → supv or supv → user *)
Push tempSsCS, tempSsLip, tempSsSSP on shadow stack using 8B pushes1
FI;
FI;
FI;
IF task switch initiated by IRET
IF verifyCsLIP = 1
(* do 64 bit comparisons; CS zero padded to 64 bit; CSBASE+EIP zero padded to 64 bit *)
IF tempSsCS and tempSsLIP do not match CS and CSBASE+EIP
THEN #CP(FAR-RET/IRET); FI;
FI;
IF ShadowStackEnabled(CPL)
THEN
IF (verifyCsLIP == 0) tempSSP = IA32_PL3_SSP;
IF tempSSP & 0x03 != 0 THEN #CP(FAR-RET/IRET) // verify aligned to 4 bytes
IF tempSSP[63:32] != 0 THEN # CP(FAR-RET/IRET)
SSP = tempSSP
FI;
FI;
IF EndbranchEnabled(CPL)
IF task switch initiated by CALL instruction, JMP instruction, interrupt or exception
IF CPL = 3
THEN
IA32_U_CET.TRACKER = WAIT_FOR_ENDBRANCH
1. If any of these pushes leads to an exception or a VM exit, the supervisor shadow-stack token remains busy.
8-12
Vol. 3A
TASK MANAGEMENT
IA32_U_CET.SUPPRESS = 0
ELSE
IA32_S_CET.TRACKER = WAIT_FOR_ENDBRANCH
IA32_S_CET.SUPPRESS = 0
FI;
FI;
FI;
16. Begins executing the new task. (To an exception handler, the first instruction of the new task appears not to
have been executed.)
NOTES
If all checks and saves have been carried out successfully, the processor commits to the task
switch. If an unrecoverable error occurs in steps 1 through 8, the processor does not complete the
task switch and ensures that the processor is returned to its state prior to the execution of the
instruction that initiated the task switch.
If an unrecoverable error occurs in step 9, architectural state may be corrupted, but an attempt will
be made to handle the error in the prior execution environment. If an unrecoverable error occurs
after the commit point (in step 13), the processor completes the task switch (without performing
additional access and segment availability checks) and generates the appropriate exception prior to
beginning execution of the new task.
If exceptions occur after the commit point, the exception handler must finish the task switch itself
before allowing the processor to begin executing the new task. See Chapter 6, “Interrupt
10-Invalid TSS Exception (#TS),” for more information about the affect of exceptions on a task
when they occur after the commit point of a task switch.
The state of the currently executing task is always saved when a successful task switch occurs. If the task is
resumed, execution starts with the instruction pointed to by the saved EIP value, and the registers are restored to
the values they held when the task was suspended.
When switching tasks, the privilege level of the new task does not inherit its privilege level from the suspended
task. The new task begins executing at the privilege level specified in the CPL field of the CS register, which is
loaded from the TSS. Because tasks are isolated by their separate address spaces and TSSs and because privilege
rules control access to a TSS, software does not need to perform explicit privilege checks on a task switch.
Table 8-1 shows the exception conditions that the processor checks for when switching tasks. It also shows the
exception that is generated for each check if an error is detected and the segment that the error code references.
(The order of the checks in the table is the order used in the P6 family processors. The exact order is model specific
and may be different for other IA-32 processors.) Exception handlers designed to handle these exceptions may be
subject to recursive calls if they attempt to reload the segment selector that generated the exception. The cause of
the exception (or the first of multiple causes) should be fixed before reloading the selector.
Table 8-1. Exception Conditions Checked During a Task Switch
Condition Checked
Exception1
Error Code Reference2
Segment selector for a TSS descriptor references
#GP
New Task’s TSS
the GDT and is within the limits of the table.
#TS (for IRET)
P bit is set in TSS descriptor.
#NP
New Task’s TSS
TSS descriptor is not busy (for task switch initiated by a call, interrupt, or
#GP (for JMP, CALL, INT)
Task’s back-link TSS
exception).
TSS descriptor is not busy (for task switch initiated by an IRET instruction).
#TS (for IRET)
New Task’s TSS
TSS segment limit greater than or equal to 108 (for 32-bit TSS) or 44 (for 16-bit
#TS
New Task’s TSS
TSS).
Vol. 3A
8-13
TASK MANAGEMENT
Table 8-1. Exception Conditions Checked During a Task Switch (Contd.)
Condition Checked
Exception1
Error Code Reference2
TSS segment limit greater than or equal to 108 (for 32-bit TSS) if CR4.CET = 1.3
#TS
New Task’s TSS
If shadow stack enabled and SSP not aligned to 8 bytes (for task switch initiated
#TS
Current Task’s TSS
by an IRET instruction).3
Registers are loaded from the values in the TSS.
LDT segment selector of new task is valid 4.
#TS
New Task’s LDT
If code segment is non-conforming, its DPL should equal its RPL.
#TS
New Code Segment
If code segment is conforming, its DPL should be less than or equal to its RPL.
#TS
New Code Segment
SS segment selector is valid 2.
#TS
New Stack Segment
P bit is set in stack segment descriptor.
#SS
New Stack Segment
Stack segment DPL should equal CPL.
#TS
New stack segment
P bit is set in new task's LDT descriptor.
#TS
New Task’s LDT
CS segment selector is valid 4.
#TS
New Code Segment
P bit is set in code segment descriptor.
#NP
New Code Segment
Stack segment DPL should equal its RPL.
#TS
New Stack Segment
DS, ES, FS, and GS segment selectors are valid 4.
#TS
New Data Segment
DS, ES, FS, and GS segments are readable.
#TS
New Data Segment
P bits are set in descriptors of DS, ES, FS, and GS segments.
#NP
New Data Segment
DS, ES, FS, and GS segment DPL greater than or equal to CPL (unless these are
#TS
New Data Segment
conforming segments).
Shadow Stack Pointer in a task not aligned to 8 bytes (for task switch initiated by
#TS
New Task’s TSS
a call, interrupt, or exception).3
If EFLAGS.VM=1 and shadow stacks are enabled.3
#TS
New Task’s TSS
Supervisor Shadow Stack Token verification failures (for task switch initiated by a
#TS
New Task’s TSS
call, interrupt, jump, or exception):3
- Busy bit already set.
- Address in Shadow stack token does not match SSP value from TSS.
If task switch initiated by IRET, CS and LIP stored on old task shadow stack does
#CP
FAR-RET/IRET
not match CS and LIP of new task.3
If task switch initiated by IRET and SSP of new task loaded from shadow stack of
#CP
FAR-RET/IRET
old task (if new task CPL is < 3) OR the SSP from IA32_PL3_SSP (if new task CPL
= 3) fails the following checks:3
- Not aligned to 4 bytes.
- Is beyond 4G.
NOTES:
1. #NP is segment-not-present exception, #GP is general-protection exception, #TS is invalid-TSS exception, and #SS is stack-fault
exception.
2. The error code contains an index to the segment descriptor referenced in this column.
3. Valid when CET is enabled.
4. A segment selector is valid if it is in a compatible type of table (GDT or LDT), occupies an address within the table's segment limit,
and refers to a compatible type of descriptor (for example, a segment selector in the CS register only is valid when it points to a
code-segment descriptor).
The TS (task switched) flag in the control register CR0 is set every time a task switch occurs. System software uses
the TS flag to coordinate the actions of floating-point unit when generating floating-point exceptions with the rest
of the processor. The TS flag indicates that the context of the floating-point unit may be different from that of the
current task. See Section 2.5, “Control Registers,” for a detailed description of the function and use of the TS flag.
8-14
Vol. 3A
TASK MANAGEMENT
8.4
TASK LINKING
The previous task link field of the TSS (sometimes called the “backlink”) and the NT flag in the EFLAGS register are
used to return execution to the previous task. EFLAGS.NT = 1 indicates that the currently executing task is nested
within the execution of another task.
When a CALL instruction, an interrupt, or an exception causes a task switch: the processor copies the segment
selector for the current TSS to the previous task link field of the TSS for the new task; it then sets EFLAGS.NT = 1.
If software uses an IRET instruction to suspend the new task, the processor checks for EFLAGS.NT = 1; it then
uses the value in the previous task link field to return to the previous task. See Figures 8-8.
When a JMP instruction causes a task switch, the new task is not nested. The previous task link field is not used and
EFLAGS.NT = 0. Use a JMP instruction to dispatch a new task when nesting is not desired.
Top Level
Nested
More Deeply
Currently Executing
Task
Task
Nested Task
Task
TSS
TSS
TSS
EFLAGS
NT=1
NT=0
NT=1
NT=1
Previous
Previous
Previous
Task Link
Task Link
Task Link
Task Register
Figure 8-8. Nested Tasks
Table 8-2 shows the busy flag (in the TSS segment descriptor), the NT flag, the previous task link field, and TS flag
(in control register CR0) during a task switch.
The NT flag may be modified by software executing at any privilege level. It is possible for a program to set the NT
flag and execute an IRET instruction. This might randomly invoke the task specified in the previous link field of the
current task's TSS. To keep such spurious task switches from succeeding, the operating system should initialize the
previous task link field in every TSS that it creates to 0.
Table 8-2. Effect of a Task Switch on Busy Flag, NT Flag, Previous Task Link Field, and TS Flag
Flag or Field
Effect of JMP instruction
Effect of CALL Instruction or
Effect of IRET
Interrupt
Instruction
Busy (B) flag of new task.
Flag is set. Must have been
Flag is set. Must have been
No change. Must have been set.
clear before.
clear before.
Busy flag of old task.
Flag is cleared.
No change. Flag is currently
Flag is cleared.
set.
NT flag of new task.
Set to value from TSS of new
Flag is set.
Set to value from TSS of new
task.
task.
NT flag of old task.
No change.
No change.
Flag is cleared.
Previous task link field of new
No change.
Loaded with selector
No change.
task.
for old task’s TSS.
Previous task link field of old
No change.
No change.
No change.
task.
TS flag in control register CR0.
Flag is set.
Flag is set.
Flag is set.
Vol. 3A
8-15
TASK MANAGEMENT
8.4.1
Use of Busy Flag To Prevent Recursive Task Switching
A TSS allows only one context to be saved for a task; therefore, once a task is called (dispatched), a recursive (or
re-entrant) call to the task would cause the current state of the task to be lost. The busy flag in the TSS segment
descriptor is provided to prevent re-entrant task switching and a subsequent loss of task state information. The
processor manages the busy flag as follows:
1. When dispatching a task, the processor sets the busy flag of the new task.
2. If during a task switch, the current task is placed in a nested chain (the task switch is being generated by a
CALL instruction, an interrupt, or an exception), the busy flag for the current task remains set.
3. When switching to the new task (initiated by a CALL instruction, interrupt, or exception), the processor
generates a general-protection exception (#GP) if the busy flag of the new task is already set. If the task switch
is initiated with an IRET instruction, the exception is not raised because the processor expects the busy flag to
be set.
4. When a task is terminated by a jump to a new task (initiated with a JMP instruction in the task code) or by an
IRET instruction in the task code, the processor clears the busy flag, returning the task to the “not busy” state.
The processor prevents recursive task switching by preventing a task from switching to itself or to any task in a
nested chain of tasks. The chain of nested suspended tasks may grow to any length, due to multiple calls, inter-
rupts, or exceptions. The busy flag prevents a task from being invoked if it is in this chain.
The busy flag may be used in multiprocessor configurations, because the processor follows a LOCK protocol (on the
bus or in the cache) when it sets or clears the busy flag. This lock keeps two processors from invoking the same
task at the same time. See Section 9.1.2.1, “Automatic Locking,” for more information about setting the busy flag
in a multiprocessor applications.
8.4.2
Modifying Task Linkages
In a uniprocessor system, in situations where it is necessary to remove a task from a chain of linked tasks, use the
following procedure to remove the task:
1. Disable interrupts.
2. Change the previous task link field in the TSS of the pre-empting task (the task that suspended the task to be
removed). It is assumed that the pre-empting task is the next task (newer task) in the chain from the task to
be removed. Change the previous task link field to point to the TSS of the next oldest task in the chain or to an
even older task in the chain.
3. Clear the busy (B) flag in the TSS segment descriptor for the task being removed from the chain. If more than
one task is being removed from the chain, the busy flag for each task being remove must be cleared.
4. Enable interrupts.
In a multiprocessing system, additional synchronization and serialization operations must be added to this proce-
dure to ensure that the TSS and its segment descriptor are both locked when the previous task link field is changed
and the busy flag is cleared.
8.5
TASK ADDRESS SPACE
The address space for a task consists of the segments that the task can access. These segments include the code,
data, stack, and system segments referenced in the TSS and any other segments accessed by the task code. The
segments are mapped into the processor’s linear address space, which is in turn mapped into the processor’s phys-
ical address space (either directly or through paging).
The LDT segment field in the TSS can be used to give each task its own LDT. Giving a task its own LDT allows the
task address space to be isolated from other tasks by placing the segment descriptors for all the segments associ-
ated with the task in the task’s LDT.
It also is possible for several tasks to use the same LDT. This is a memory-efficient way to allow specific tasks to
communicate with or control each other, without dropping the protection barriers for the entire system.
8-16
Vol. 3A
|
||
|
|
|