Exceptions: Difference between revisions

m
Discovered this the hard way
[unchecked revision][unchecked revision]
m (General Protection Fault: Typofix)
m (Discovered this the hard way)
 
(11 intermediate revisions by 9 users not shown)
Line 3:
|}
 
'''Exceptions''', as described in this article, are a type of [[interrupt]] generated by the CPU when an 'error' occurs. Some exceptions are not really errors in most cases, such as [[#Page Fault|page faults]]. Exceptions are a type of [[interrupt]].
 
Exceptions are classified as:
Line 10:
* '''Aborts''': Some severe unrecoverable error.
 
Some exceptions will push a 32-bit "error code" on to the top of the stack, which provides additional information about the error. This value must be pulled from the stack before returning control back to the currently running program. (i.e. before calling IRET). In [[Long Mode]], the error code is padded with zeros to form a 64-bit push, so that it can be popped like any other value.
 
{| {{wikitable}}
Line 19:
! Error code?
|-
! [[#Divide-by-zeroDivision Error|Divide-by-zeroDivision Error]]
| 0 (0x0)
| Fault
Line 144:
| #VE
| No
|-
! [[#Control Protection Exception|Control Protection Exception]]
| 21 (0x15)
| Fault
| #CP
| Yes
|-
! Reserved
| 2122-2927 (0x150x16-0x1D0x1B)
| -
| -
| No
|-
! [[#Hypervisor Injection Exception|Hypervisor Injection Exception]]
| 28 (0x1C)
| Fault
| #HV
| No
|-
! [[#VMM Communication Exception|VMM Communication Exception]]
| 29 (0x1D)
| Fault
| #VC
| Yes
|-
! [[#Security Exception|Security Exception]]
| 30 (0x1E)
| -Fault
| #SX
| Yes
Line 180 ⟶ 198:
=== Faults ===
 
==== Divide-by-zeroDivision Error ====
The '''Divide-by-zeroDivision Error''' occurs when dividing any number by 0 using the DIV or IDIV instruction., Manyor OSwhen developersthe usedivision thisresult exceptionis totoo testlarge whetherto theirbe exceptionrepresented handlingin codethe worksdestination. ThisSince exceptiona mayfaulting alsoDIV occuror whenIDIV the resultinstruction is toovery largeeasy to beinsert representedanywhere in the destinationcode, many OS developers use this exception to test whether their exception handling code works.
 
The saved instruction pointer points to the DIV or IDIV instruction which caused the exception.
Line 191 ⟶ 209:
 
==== Invalid Opcode ====
The Invalid Opcode exception occurs when the processor tries to execute an invalid or undefined opcode, or an instruction with invalid prefixes. It also occurs whenin another instruction exceeds 15 bytescases, but this only occurs with redundantsuch prefixes.as:
* The instruction length exceeds 15 bytes, but this only occurs with redundant prefixes.
* TryingThe instruction tries to access ana unimplementednon-existent control register (like:for example, <code>mov cr6, eax</code>).
* The UD instruction is executed.
 
The saved instruction pointer points to the instruction which caused the exception.
Line 201 ⟶ 222:
 
==== Invalid TSS ====
An Invalid TSS exception occurs when an invalid segment selector is referenced as part of a task whichswitch, or as a result of a control transfer through a gate descriptor, which results in an invalid stack-segment reference using an SS selector in the TSS.
 
When the exception occurred before loading the segment selectors from the TSS, the saved instruction pointer points to the instruction which caused the exception. Otherwise, and this is more common, it points to the first instruction in the new task.
Line 208 ⟶ 229:
 
==== Segment Not Present ====
The Segment Not Present exception occurs when trying to load a segment or gate which has it'sits `Present-` bit set to 0.
However when loading a stack-segment selector which references a descriptor which is not present, a [[#Stack-Segment Fault|Stack-Segment Fault]] occurs.
 
If the exception happens during a hardware task switch, the segment values should not be relied upon by the handler. That is, the handler should check them before trying to resume the new task. There are three ways to do this, according to the Intel documentation.
 
The saved instruction pointer points to the instruction which caused the exception.
Line 221 ⟶ 244:
* When the stack-limit check fails.
 
If the exception happens during a hardware task switch, the segment values should not be relied upon by the handler. That is, the handler should check them before trying to resume the new task. There are three ways to do this, according to the Intel documentation.
This exeption is not part of segment not present exeption because of the need to push eip,cs,eflags,esp,ss to the stack is no longer valid becuase of the ss's gdt entry (or the ss itself) had to be buggy in the first place for this exeption to occur , so one must declare this exeption as a task switch interrupt and setting up tss for it.
The saved instruction pointer points to the instruction which caused the exception.
 
The saved instruction pointer points to the instruction which caused the exception, unless the fault occurred because of loading a non-present stack segment during a hardware task switch, in which case it points to the next instruction of the new task.
 
'''Error code:''' The Stack-Segment Fault sets an error code, which is the stack [[#Selector Error Code|segment selector index]] when a non-present segment descriptor was referenced or a limit check failed during a hardware task switch. Otherwise (for present segments and already in use), the error code is 0.
 
==== General Protection Fault ====
Line 231 ⟶ 254:
* Segment error (privilege, type, limit, read/write rights).
* Executing a privileged instruction while CPL != 0.
* Writing a 1 in a reserved register field or writing invalid value combinations (e.g. CR0 with PE=0 and PG=1).
* Referencing or accessing a null-descriptor.
* Accessing a memory address with bits 48-63 not matching bit 47 (e.g. 0x_0000_8000_0000_0000 instead of 0x_ffff_8000_0000_0000) in 64 bit mode.
* Trying to access an unimplemented register (like: <code>mov cr6, eax</code>)
 
The saved instruction pointer points to the instruction which caused the exception.
Line 240 ⟶ 263:
 
==== Page Fault ====
{{main|Page fault}}
A Page Fault occurs when:
* A [[Paging|page directory or table]] entry is not present in physical memory.
Line 253 ⟶ 275:
 
<pre>
31 15 4 0
+---+-- --+---+-----+---+-- --+---+----+----+---+---+---+---+---+
| Reserved | SGX | Reserved | SS | PK | I | R | U | W | P |
+---+-- --+---+-----+---+-- --+---+----+----+---+---+---+---+---+
</pre>
 
Line 273 ⟶ 295:
| 1 bit
| Write
| When set, the page fault was caused by a page write access. When not set, it was caused by a page read access.
|-valign="top"
!align="left"| U
Line 283 ⟶ 305:
| 1 bit
| Reserved write
| When set, one or more page directory entries contain reserved bits which are set to 1. This only applies when the PSE or PAE flags in CR4 are set to 1.
| When set, the page fault was caused by writing a 1 in a reserved field.
|-valign="top"
!align="left"| I
| 1 bit
| Instruction Fetch
| When set, the page fault was caused by an instruction fetch. This only applies when the No-Execute bit is supported and enabled.
|-valign="top"
!align="left"| PK
| 1 bit
| Protection key
| When set, the page fault was caused by a protection-key violation. The PKRU register (for user-mode accesses) or PKRS MSR (for supervisor-mode accesses) specifies the protection key rights.
|-valign="top"
!align="left"| SS
| 1 bit
| Shadow stack
| When set, the page fault was caused by writing a 1 in ashadow reservedstack fieldaccess.
|-valign="top"
!align="left | SGX
| 1 bit
| Software Guard Extensions
| When set, the fault was due to an [https://en.wikipedia.org/wiki/Software_Guard_Extensions SGX violation]. The fault is unrelated to ordinary paging.
|}
 
Line 337 ⟶ 374:
 
==== Overflow ====
An Overflow exception is raised when the INTO instruction is executed while the overflow bit in RFLAGS is set to 1, or when the result of div/idiv insructions is bigger than 64 bit /32 bit / 16 bit /8bit depending on the instruction operand size .( only if bigger than the operand size.)
 
The saved instruction pointer points to the instruction after the INTO instruction, or when an div/idiv is the cuase of the exeption , the insruction pointer that pushed points to the faulty insruction.
 
=== Aborts ===
Line 413 ⟶ 450:
 
====FPU Error Interrupt====
In the old days, the floating point unit was a dedicated chip that could be attached to the processor. It lacked direct wiring of FPU errors to the processor, so instead it used [[PIC|IRQ 13]], allowing the CPU to deal with errors at it'sits own leasure. When the 486 was developed and multiprocessor support was added, the [[FPU]] was embedded on die and a global interrupt for FPUs became undesirable, instead getting an option for direct error handling. By default, this method is not enabled at boot for backwards compatibility, but an OS should update the settings accordingly.
 
====Coprocessor Segment Overrun====
Line 423 ⟶ 460:
* [http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf Intel® 64 and IA-32 Architectures Software Developer's Manual], Volume 3 (System Programming Guide), Chapter 6 (Interrupt and exception handling)
 
[[Category:X86]]
[[Category:Interrupts]]
[[de:Exception]]
Anonymous user