本文主要源自 Chapter 9 Exceptions and Interrupts(80386 Programmer's Manual)
注意:文中有的地方 trap 是看做 Exception,特别是在与 Interrupt平行出现时。
Interrupts and exceptions are special kinds of control transfer; they work somewhat like unprogrammedCALLs.
The difference between interrupts and exceptions is that interrupts are used to handle asynchronous events external to the processor, but exceptions handle conditions detected by the processor itself in the course of executing instructions.
There are two sources for external interrupts and two sources for exceptions:
1、Interrupts
1) Maskable interrupts, which are signalled via the INTR pin.
2) Nonmaskable interrupts, which are signalled via the NMI (Non-Maskable Interrupt) pin.
2、Exceptions
1) Processor detected. These are further classified as faults, traps, and aborts.
2) Programmed. The instructions INTO, INT 3, INT n, and BOUND can trigger exceptions. These instructions are often called "software interrupts", but the processor handles them as exceptions.
1 Identifying Interrupts
The processor associates an identifying number with each different type of interrupt or exception.
The NMI and the exceptions recognized by the processor are assigned predetermined identifiers in the range 0 through 31. Not all of these numbers are currently used by the 80386; unassigned identifiers in this range are reserved by Intel for possible future expansion.
The identifiers of the maskable interrupts are determined by external interrupt controllers and communicated to the processor during the processor's interrupt-acknowledge sequence.
Faults
Faults are exceptions that are reported "before" the instruction causing the exception. Faults are either detected before the instruction begins to execute, or during execution of the instruction. If detected during the instruction, the fault is reported with the machine restored to a state that permits the instruction to be restarted.
Traps
A trap is an exception that is reported at the instruction boundary immediately after the instruction in which the exception was detected.
Aborts
An abort is an exception that permits neither precise location of the instruction causing the exception nor restart of the program that caused the exception. Aborts are used to report severe errors, such as hardware errors and inconsistent or illegal values in system tables.
2 Enabling and Disabling Interrupts
The processor services interrupts and exceptions only between the end of one instruction and the beginning of the next.
2.1 NMI Masks Further NMIs
While an NMI handler is executing, the processor ignores further interrupt signals at the NMI pin until the next IRET instruction is executed.
2.2 IF Masks INTR
The IF (interrupt-enable flag) controls the acceptance of external interrupts signalled via the INTR pin. When IF=0, INTR interrupts are inhibited; when IF=1, INTR interrupts are enabled.
As with the other flag bits, the processor clears IF in response to a RESET signal.
The instructions CLI(Clear Interrupt-Enable Flag) and STI (Set Interrupt-Enable Flag) alter the setting of IF.(CLI and STI may be executed only if CPL <= IOPL)
The IF is also affected implicitly by other operations.
2.3 RF Masks Debug Faults
The RF bit in EFLAGS controls the recognition of debug faults.
2.4 MOV or POP to SS Masks Some Interrupts and Exceptions
Software that needs to change stack segments often uses a pair of instructions; for example:
MOV SS, AX
MOV ESP, StackTop
If an interrupt or exception is processed after SS has been changed but before ESP has received the corresponding change, the two parts of the stack pointer SS:ESP are inconsistent for the duration of the interrupt handler or exception handler.
To prevent this situation, the 80386, after both a MOV to SS and a POP to SS instruction, inhibits NMI, INTR, debug exceptions, and single-step traps at the instruction boundary following the instruction that changes SS. Some exceptions may still occur; namely, page fault and general protection fault. Always use the 80386 LSS instruction, and the problem will not occur.
3 Priority Among Simultaneous Interrupts and Exceptions
If more than one interrupt or exception is pending at an instruction boundary, the processor services one of them at a time.The processor first services a pending interrupt or exception from the class that has the highest priority, transferring control to the first instruction of the interrupt handler. Lower priority exceptions are discarded; lower priority interrupts are held pending. Discarded exceptions will be rediscovered when the interrupt handler returns control to the point of interruption.
4 Interrupt Descriptor Table
The interrupt descriptor table (IDT) associates each interrupt or exception identifier with a descriptor for the instructions that service the associated event. Like the GDT and LDTs, the IDT is an array of 8-byte descriptors. Unlike the GDT and LDTs, the first entry of the IDT may contain a descriptor. To form an index into the IDT, the processor multiplies the interrupt or exception identifier by eight. Because there are only 256 identifiers, the IDT need not contain more than 256 descriptors. It can contain fewer than 256 entries; entries are required only for interrupt identifiers that are actually used.
The IDT may reside anywhere in physical memory. As Figure 9-1 shows, the processor locates the IDT by means of the IDT register (IDTR).
The instructions LIDT(Load IDT register) and SIDT(Store IDT register) operate on the IDTR. Both instructions have one explicit operand: the address in memory of a 6-byte area. Figure 9-2 shows the format of this area.
5 IDT Descriptors
The IDT may contain any of three kinds of descriptor:
1) Task gates
2) Interrupt gates
3) Trap gates
6 Interrupt Tasks and Interrupt Procedures
When responding to an interrupt or exception, the processor uses the interrupt or exception identifier to index a descriptor in the IDT. If the processor indexes to an interrupt gate or trap gate, it invokes the handler in a manner similar to a CALL to a call gate. If the processor finds a task gate, it causes a task switch in a manner similar to a CALL to a task gate.
6.1 Interrupt Procedures
An interrupt gate or trap gate points indirectly to a procedure which will execute in the context of the currently executing task as illustrated by Figure 9-4 . The selector of the gate points to an executable-segment descriptor in either the GDT or the current LDT. The offset field of the gate points to the beginning of the interrupt or exception handling procedure.
6.1.1 Stack of Interrupt Procedure
Just as with a control transfer due to a CALL instruction, a control transfer to an interrupt or exception handling procedure uses the stack to store the information needed for returning to the original procedure. As Figure 9-5 shows, an interrupt pushes the EFLAGS register onto the stack before the pointer to the interrupted instruction.
Certain types of exceptions also cause an error code to be pushed on the stack. An exception handler can use the error code to help diagnose the exception.
6.1.2 Returning from an Interrupt Procedure
An interrupt procedure also differs from a normal procedure in the method of leaving the procedure. The IRET instruction is used to exit from an interrupt procedure. IRET is similar to RET except that IRET increments ESP by an extra four bytes (because of the flags on the stack) and moves the saved flags into the EFLAGS register. The IOPL field of EFLAGS is changed only if the CPL is zero. The IF flag is changed only if CPL <= IOPL.
6.1.3 Flags Usage by Interrupt Procedure
Interrupts that vector through either interrupt gates or trap gates cause TF (the trap flag) to be reset after the current value of TF is saved on the stack as part of EFLAGS.
The difference between an interrupt gate and a trap gate is in the effect on IF (the interrupt-enable flag). An interrupt that vectors through an interrupt gate resets IF, thereby preventing other interrupts from interfering with the current interrupt handler. A subsequent IRET instruction restores IF to the value in the EFLAGS image on the stack. An interrupt through a trap gate does not change IF.
6.1.4 Protection in Interrupt Procedures
The CPU does not permit an interrupt to transfer control to a procedure in a segment of lesser privilege (numerically greater privilege level) than the current privilege level. An attempt to violate this rule results in a general protection exception.Because occurrence of interrupts is not generally predictable, this privilege rule effectively imposes restrictions on the privilege levels at which interrupt and exception handling procedures can execute. Either of the following strategies can be employed to ensure that the privilege rule is never violated:
6.2 Interrupt Tasks
A task gate in the IDT points indirectly to a task, as Figure 9-6 illustrates. The selector of the gate points to a TSS descriptor in the GDT.
7 Error Code
With exceptions that relate to a specific segment, the processor pushes an error code onto the stack of the exception handler (whether procedure or task). The error code has the format shown in Figure 9-7 . The format of the error code resembles that of a selector; however, instead of an RPL field, the error code contains two one-bit items:
If the I-bit is not set, the TI bit indicates whether the error code refers to the GDT (value 0) or to the LDT (value 1). The remaining 14 bits are the upper 14 bits of the segment selector involved. In some cases the error code on the stack is null, i.e., all bits in the low-order word are zero.(原文是这样的,还不知道对不)
8 Exception Conditions
Faults
The CS and EIP values saved when a fault is reported point to the instruction causing the fault.An abort is an exception that permits neither precise location of the instruction causing the exception nor restart of the program that caused the exception. Aborts are used to report severe errors, such as hardware errors and inconsistent or illegal values in system tables.
8.1 Interrupt 0 -- Divide Error
The divide-error fault occurs during a DIV or an IDIV instruction when the divisor is zero.
8.2 Interrupt 1 -- Debug Exceptions
The processor triggers this interrupt for any of a number of conditions; whether the exception is a fault or a trap depends on the condition:
8.3 Interrupt 3 -- Breakpoint
The INT 3 instruction causes this trap.Debuggers typically use breakpoints as a way of displaying registers, variables, etc., at crucial points in a task.The saved CS:EIP value points to the byte following the breakpoint.
8.4 Interrupt 4 -- Overflow
This trap occurs when the processor encounters an INTO instruction and the OF (overflow) flag is set.
8.5 Interrupt 5 -- Bounds Check
This fault occurs when the processor, while executing a BOUND instruction, finds that the operand exceeds the specified limits.
8.6 Interrupt 6 -- Invalid Opcode
This fault occurs when an invalid opcode is detected by the execution unit.(The exception is not detected until an attempt is made to execute the invalid opcode; i.e., prefetching an invalid opcode does not cause this exception.) No error code is pushed on the stack. The exception can be handled within the same task.
This exception also occurs when the type of operand is invalid for the given opcode.
8.7 Interrupt 7 -- Coprocessor Not Available
This exception occurs in either of two conditions:
8.8 Interrupt 8 -- Double Fault
Normally, when the processor detects an exception while trying to invoke the handler for a prior exception, the two exceptions can be handled serially. If, however, the processor cannot handle them serially, it signals the double-fault exception instead. To determine when two faults are to be signalled as a double fault, the 80386 divides the exceptions into three classes: benign exceptions, contributory exceptions, and page faults. Table 9-3 shows this classification.
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.
8.9 Interrupt 9 -- Coprocessor Segment Overrun
This exception is raised in protected mode if the 80386 detects a page or segment violation while transferring the middle portion of a coprocessor operand to the NPX . This exception is avoidable.
8.10 Interrupt 10 -- Invalid TSS
Interrupt 10 occurs if during a task switch the new TSS is invalid. A TSS is considered invalid in the cases shown in Table 9-5. An error code is pushed onto the stack to help identify the cause of the fault. The EXT bit indicates whether the exception was caused by a condition outside the control of the program。
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.
8.11 Interrupt 11 -- Segment Not Present
Exception 11 occurs when the processor detects that the present bit of a descriptor is zero. The processor can trigger this fault in any of these cases:
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.
This exception pushes an error code onto the stack. The EXT bit of the error code is set if an event external to the program caused an interrupt that subsequently referenced a not-present segment. The I-bit is set if the error code refers to an IDT entry.
8.12 Interrupt 12 -- Stack Exception
A stack fault occurs in either of two general conditions:
8.13 Interrupt 13 -- General Protection Exception
All protection violations that do not cause another exception cause a general protection exception.
The general protection exception is a fault. In response to a general protection exception, the processor pushes an error code onto the exception handler's stack. If loading a descriptor causes the exception, the error code contains a selector to the descriptor; otherwise, the error code is null. The source of the selector in an error code may be any of the following:
8.14 Interrupt 14 -- Page Fault
This exception occurs when paging is enabled (PG=1) and the processor detects one of the following conditions while translating a linear address to a physical address:
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.
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.
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.
9 Exception Summary
10 Error Code Summary