Processor Exceptions A survey of the x86 exceptions and mechanism for handling

advertisement
Processor Exceptions
A survey of the x86 exceptions
and mechanism for handling
faults, traps, and aborts
‘Before-the-fact’ errors
• The CPU may fetch an instruction which it
cannot correctly execute (due to an invalid
operand or insufficient privilege-level, or to
the instruction’s opcode not being defined)
• A few examples are:
– Attempting to perform division by zero
– Attempting to exceed memory-segment limits
– Attempting to modify a ‘read-only’ segment
‘After-the-fact’ errors
• Also the cpu may perform some operation
that results in an incorrect or illegal value
(due to limits on the CPU register-sizes or
to limits on the supported data-formats)
• A few examples:
– Add positive numbers, but get a negative total
– Store an array-entry beyond the array-bounds
– Take square-root of a real value less than 0.0
“privileged” instructions
• In Protected-Mode the instructions below
can only be executed at ring0 (i.e., if the
CPU’s Current Privilege Level is zero):
– ‘MOV’ to/from a control-register (e.g., CR0)
– ‘MOV’ to/from a debug-register (e.g., DR7)
– Modifying a system segment-register (i.e.,
‘LGDT’ / ’LIDT’ / ’LLDT’ / ’LTR’ / ’LMSW’ )
– Cache-invalidates: ‘INVD’/‘INVLPG’/ WBINVD’
– ‘CLTS’ or ‘HLT’
What happens if…?
• If protection rules are violated, or if errors
result from computations, the processor
will generate an ‘exception’ (i.e., it will
save some information on the stack and
transfer control to an ‘exception-handler’)
• Different kinds of exceptions will trigger
different exception-handling procedures
• Gates in the IDT define the ‘entry-points’
Faults, traps, and aborts
• Intel classifies exceptions into categories,
(according to whether or not it may be
possible to ‘recover’ from the ‘error’):
– ‘Faults’ are detected ‘before-the-fact’ (and
generally indicate ‘recoverable’ errors)
– ‘Traps’ are detected ‘after-the-fact’ (and
indicate some corrective action is needed)
– ‘Aborts’ are unrecoverable error-conditions
A ‘fault’ example
• Suppose an instruction tries to read from a
‘not-present’ data-segment: mov ax, [si]
• The CPU generate exception-number 0xB
• In case the corresponding IDT-descriptor
is a 32-bit interrupt-gate (or trap-gate), the
CPU will push at least four 32-bit values:
– Current contents of the EFLAGS register
– Current contents of registers CS and EIP
– An ‘error-code’ (with info about DS register)
‘Fault’ example (continued)
• If it is necessary to switch stacks (due to a
change in the exception-handler’s code-segment
privilege-level), the ‘old’ stack’s address (i.e.,
registers SS and ESP) will also get pushed onto
the ‘new’ stack
• The fault-handler can take whatever actions are
necessary to resolve the ‘not-present’ condition,
then mark the data-segment as being ‘present’
and ‘restart’ execution of the prior instruction
What about ‘not-present’ gates?
• If an exception is generated, but the IDT’s
gate-descriptor for that type of exception
isn’t ‘present’, then the CPU generates a
General Protection exception (INT-0x0D)
• So by supplying one exception-handler for
this ‘catch all’ exception, we can ‘service’
nearly all of the various error-conditions
Error-Code Formats
• The format of the error-code that the CPU
pushes onto its stack depends upon which
type of exception has been encountered
• For General Protection exceptions, the
error-code format looks like this:
3 2 1 0
15
segment selector index
I E
T
N X
I
T T
TI=Table Indicator (0=GDT, 1=LDT)
INT=Interrupt (1=yes, 0=no)
EXT=External-to-CPU event was cause of the exception (1=yes, 0=no)
Stack Frame Layout (32bit)
SS
ESP
points to the old stack’s top
EFLAGS
CS
EIP
Error Code
points to the faulting instruction
SS:ESP = the new stack’s top
When the ‘fault’ exception uses a 32-bit Interrupt-Gate (or Trap-Gate)
Stack Frame Layout (16bit)
SS
SP
points to the old stack’s top
FLAGS
CS
IP
Error Code
points to the faulting instruction
SS:SP = the new stack’s top
When the ‘fault’ exception uses a 16-bit Interrupt-Gate (or Trap-Gate)
Catalog of x86 exceptions
•
•
•
•
•
•
•
•
0x00: divide-overflow fault
0x01: single-step trap or debug fault
0x02: non-maskable interrupt (NMI) trap
0x03: breakpoint trap
0x04: integer overflow trap
0x05: array bounds fault
0x06: invalid opcode fault
0x07: coprocessor unavailable fault
Catalog (continue)
•
•
•
•
•
•
•
•
0x08: double-fault abort
0x09: (reserved)
0x0A: invalid TSS fault/abort
0x0B: segment not present fault
0x0C: stack fault
0x0D: general protection exception fault
0x0E: page fault
0x0F: (reserved)
Catalog (continued again)
•
•
•
•
•
•
•
0x10: FPU floating-point error fault
0x11: operand alignment-check fault
0x12: machine-check exception abort
0x13: SIMD floating-point exception fault
0x14-0x1F: (reserved)
0x20-0xFF: (user-defined interrupts)
NOTE: Only the following exceptions have
error-codes: 0x8, 0xA, 0xB, 0xC, 0xD, 0xE
Demo program: ‘whycrash.s’
• To illustrate the processor’s response to
exceptions, we created this short demo
• It displays some diagnostic information
(including the ‘error-code’) when the CPU
triggers any exception-condition (all get
routed through the IDT-gate for General
Protection exceptions in this demo)
• Can help us identify causes for a ‘crash’
In-class exercise #1
• Try experimenting with your own examples
of impermissible instructions
• What if you try to store a value to the vram
memory-segment using an address-offset
larger than the 32KB segment-limit?
• What if you try to load a segment-register
with a selector-value that exceeds the size
of your descriptor-table?
• What if you try to ‘call’ to ring3 from ring0?
In-class exercise #2
• If your ‘solution’ to midterm Question V
caused a system-crash, can you find out
why, by adding this exception-handler to
your program’s source-text?
• Some useful programming techniques:
– Using the as86 ‘INCLUDE’ directive (to
include a separate source-text file
– Using the as86 ‘-l’ command-line option (to
generate an assembler ‘listing’ file)
Download