The saved CS:EIP value points to the byte following the breakpoint. If a debugger replaces a planted breakpoint with a valid opcode, it must subtract one from the saved EIP value before returning . Refer also to Chapter 12 for more information on debugging.
This exception also occurs when the type of operand is invalid for the given opcode. Examples include an intersegment JMP referencing a register operand, or an LES instruction with a register source operand.
Table 9-4 shows which combinations of exceptions cause a double fault and which do not.
The processor always pushes an error code onto the stack of the
double-fault handler; however, the error code is always zero. The faulting
instruction may not be restarted. If any other exception occurs while
attempting to invoke the double-fault handler, the processor shuts down.
Table 9-3. Double-Fault Detection Classes
Class ID Description
1 Debug exceptions
2 NMI
3 Breakpoint
Benign 4 Overflow
Exceptions 5 Bounds check
6 Invalid opcode
7 Coprocessor not available
16 Coprocessor error
0 Divide error
9 Coprocessor Segment Overrun
Contributory 10 Invalid TSS
Exceptions 11 Segment not present
12 Stack exception
13 General protection
Page Faults 14 Page fault
Table 9-4. Double-Fault Definition SECOND EXCEPTION Benign Contributory Page Exception Exception Fault Benign OK OK OK Exception FIRST Contributory OK DOUBLE OK EXCEPTION Exception Page Fault OK DOUBLE DOUBLE
This fault can occur either in the context of the original task or in the context of the new task. Until the processor has completely verified the presence of the new TSS, the exception occurs in the context of the original task. Once the existence of the new TSS is verified, the task switch is considered complete; i.e., TR is updated and, if the switch is due to a CALL or interrupt, the backlink of the new TSS is set to the old TSS. Any errors discovered by the processor after this point are handled in the context of the new task.
To insure a proper TSS to process it, the handler for exception 10 must be
a task invoked via a task gate.
Table 9-5. Conditions That Invalidate the TSS
Error Code Condition
TSS id + EXT The limit in the TSS descriptor is less than 103
LTD id + EXT Invalid LDT selector or LDT not present
SS id + EXT Stack segment selector is outside table limit
SS id + EXT Stack segment is not a writable segment
SS id + EXT Stack segment DPL does not match new CPL
SS id + EXT Stack segment selector RPL < > CPL
CS id + EXT Code segment selector is outside table limit
CS id + EXT Code segment selector does not refer to code
segment
CS id + EXT DPL of non-conforming code segment < > new CPL
CS id + EXT DPL of conforming code segment > new CPL
DS/ES/FS/GS id + EXT DS, ES, FS, or GS segment selector is outside
table limits
DS/ES/FS/GS id + EXT DS, ES, FS, or GS is not readable segment
If a not-present exception occurs during a task switch, not all the steps of the task switch are complete. During a task switch, the processor first loads all the segment registers, then checks their contents for validity. If a not-present exception is discovered, the remaining segment registers have not been checked and therefore may not be usable for referencing memory. The not-present handler should not rely on being able to use the values found in CS, SS, DS, ES, FS, and GS without causing another exception. The exception handler should check all segment registers before trying to resume the new task; otherwise, general protection faults may result later under conditions that make diagnosis more difficult. There are three ways to handle this case:
An operating system typically uses the "segment not present" exception to implement virtual memory at the segment level. A not-present indication in a gate descriptor, however, usually does not indicate that a segment is not present (because gates do not necessarily correspond to segments). Not-present gates may be used by an operating system to trigger exceptions of special significance to the operating system.
An instruction that causes this fault is restartable in all cases. The return pointer pushed onto the exception handler's stack points to the instruction that needs to be restarted. This instruction is usually the one that caused the exception; however, in the case of a stack exception due to loading of a not-present stack-segment descriptor during a task switch, the indicated instruction is the first instruction of the new task.
When a stack fault occurs during a task switch, the segment registers may not be usable for referencing memory. During a task switch, the selector values are loaded before the descriptors are checked. If a stack fault is discovered, the remaining segment registers have not been checked and therefore may not be usable for referencing memory. The stack fault handler should not rely on being able to use the values found in CS, SS, DS, ES, FS, and GS without causing another exception. The exception handler should check all segment registers before trying to resume the new task; otherwise, general protection faults may result later under conditions that make diagnosis more difficult.
The processor does not use the inconsistent stack pointer if the handling
of the page fault causes a stack switch to a well defined stack (i.e., the
handler is a task or a more privileged procedure). However, if the page
fault handler is invoked by a trap or interrupt gate and the page fault
occurs at the same privilege level as the page fault handler, the processor
will attempt to use the stack indicated by the current (invalid) stack
pointer.
In systems that implement paging and that handle page faults within the
faulting task (with trap or interrupt gates), software that executes at the
same privilege level as the page fault handler should initialize a new stack
by using the new
LSS instruction rather than an instruction pair shown
above. When the page fault handler executes at privilege level zero (the
normal case), the scope of the problem is limited to privilege-level zero
code, typically the kernel of the operating system.
up:
Chapter 9 -- Exceptions and InterruptsFigure 9-8. Page-Fault Error Code Format
+-----+-----+------------------------------------------------------------+
|Field|Value| Description |
|-----+-----+------------------------------------------------------------|
| U/S | 0 | The access causing the fault originated when the processor |
| | | was executing in supervisor mode. |
| | | |
| | 1 | The access causing the fault originated when the processor |
| | | was executing in user mode. |
| | | |
| W/R | 0 | The access causing the fault was a read. |
| | | |
| | 1 | The access causing the fault was a write. |
| | | |
| P | 0 | The fault was caused by a not-present page. |
| | | |
| | 1 | The fault was caused by a page-level protection violation. |
+-----+-----+------------------------------------------------------------+
31 15 7 3 2 1 0
+--------------------------------+-------------------------+-+-+-+
|##########################################################|U|W| |
|##########################UNDEFINED#######################|/|/|P|
|##########################################################|S|R| |
+--------------------------------+-------------------------+-+-+-+
9.8.14.1 Page Fault During Task Switch
The processor may access any of four segments during a task switch:
A page fault can result from accessing any of these segments. In the latter
two cases the exception occurs in the context of the new task. The
instruction pointer refers to the next instruction of the new task, not to
the instruction that caused the task switch. If the design of the operating
system permits page faults to occur during task-switches, the page-fault
handler should be invoked via a task gate.
Figure 9-9. CR2 Format
31 23 15 7 0
+----------------+----------------+----------------+----------------+
| |
| PAGE FAULT LINEAR ADDRESS |
| |
+----------------+----------------+----------------+----------------+
9.8.14.2 Page Fault with Inconsistent Stack Pointer
Special care should be taken to ensure that a page fault does not cause the
processor to use an invalid stack pointer (SS:ESP). Software written for
earlier processors in the 8086 family often uses a pair of instructions to
change to a new stack; for example:
MOV SS, AX
MOV SP, StackTop
With the 80386, because the second instruction accesses memory, it is
possible to get a page fault after SS has been changed but before SP has
received the corresponding change. At this point, the two parts of the stack
pointer SS:SP (or, for 32-bit programs, SS:ESP) are inconsistent.
9.8.15 Interrupt 16 -- Coprocessor Error
The 80386 reports this exception when it detects a signal from the 80287 or
80387 on the 80386's ERROR# input pin. The 80386 tests this pin only at the
beginning of certain ESC instructions and when it encounters a
WAIT
instruction while the EM bit of the MSW is zero (no emulation). Refer to
Chapter 11
for more information on the coprocessor interface.
prev: 9.7 Error Code
next: 9.9 Exception Summary