Required reading: Chapter 5 (Interrupt and Exception handling)
Sources of Exceptions/Interrupts
- hardware interrupts
+----------+ +--------+
| INTR|--------| PIC |---16 wires to devices
| NMI|--- | 8259A |
| CPU | +--------+
| |
+----------+
- NMI -- non-maskable -- signals hard failure
- INTR maskable -- eflags IF (one bit!!)
- IF 0 -- interrupts masked -- ie. ignored
- IF 1 -- interrupts "unmasked" -- ie. not ignored
- software exception
- ex. movl %ebx, (%eax)
- ex. divl %eax,%eax
- ex. "int $VECTOR" -- aka. programmed interrupt
- see insn set reference for each insn's possible expection
- Every exception/interrupt is given a number: it's VECTOR
PIC details
- mapping IRQ0-15 => into which vector
- vector = IRQ # +
- vector is signaled over the INTR line
IDT (pg 5-11)
- table of entries (8 byte)
- lidt - tells CPU where in memory the table resides
- 32 for processor exceptions
- any of the remaining 16 for hardware interrupts
- rest are for software interrupts (e.g., int $0x50)
IDT entry (pg 5-13)
- 8 bytes
- CS:EIP -- entry point of handler routine
- P -- 1 bit -- Does entry holds valid info?
- DPL -- 2 bits -- 0 for exception and external interrupts, 3 for software interrupts
- Type -- 4 bits -- task, trap, or interrupt gate
- Crazy format like GDT entries (recall SEG() macro)
- Interrupts gates -- clear IF bit of %eflags
- Trap gates -- don't change eflags
- Both
- clear TF, VM, RF, NT flags
- setgate (idt[IRQ_OFFSET + 0],
GD_KT, /* istrap */
&_clock_interrupt,
0); /* DPL */
TSS
- purpose: hardware supported multi-tasking => we don't use
- as a data structure:
- lots of irrelevant fields
- GS, FS, DS, SS, CS, ES
- EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX, EFLAGS, CR3
- SS0:ESP0, SS1:ESP1, SS2:ESP2 <-- recving calls from lower privileged level
- relevant to this class:
- only SS0:ESP0 -- stack that is switched to when a
interrupt/exeception happens in user mode.
- Resides in memory, must tell the CPU where:
- TSS descriptor goes in the GDT
- ltr (GD_TSS)
Exception Entry Mechanism
- pg 5-16
- Like a procedure call (arguments on the stack)
- USER => KERNEL
- stack layout
value reason pushed
- old SS [ switching
- old ESP stacks]
- old EFLAGS [ clearing bits ]
- old CS [ switch to
- old EIP entry point ]
- error code (optional) [ extra info ]
- new state
- SS:ESP <= TSS ss0:esp0
- CS:EIP <= IDT[vector].segment : IDT[vector].offset
- EFLAGS <= EFLAGS with bits cleared
- Class OS: kernel runs with device interrupts disabled
- interrupt gate
- KERNEL => KERNEL
- stack layout
value reason pushed
- old EFLAGS [ clearing bits ]
- old CS [ switch to
- old EIP entry point ]
- error code (optional) [ extra info ]
- new state
- SS:ESP **** unchanged!!
- CS:EIP <= IDT[vector].segment : IDT[vector].offset
- EFLAGS <= EFLAGS with bits cleared
- why switch stacks (USER => KERNEL)?
=> stack may be the cause of the fault
=> triple faults cause CPU reset
- Motivation: save on stack if the registers themselves are changed
- notice: Kernel=>Kernel fault doesn't save SS:ESP
why? because there is no stack switch (i.e., SS:ESP are not
overwritten)
- mention now or later??
- mode (user => kernel): CS -- bottom 2 bits are CPL
Exception Return Mechanism
- iret -- top of stack should be old EIP
- closer look at old EIP / Exception Types
- traps - old EIP -- points past instruction causing exception
- brkpt (i.e., int $3)
- faults - old EIP -- points to instruction causing exception
- page faults
- aborts - old EIP -- not certain -- serious problems - CPU is confused
Comparison to PDP11/40
- DEVICE INTERRUPTS
- x86: maskable by IF bit of EFLAGS; (and by the PIC)
- pdp: multiple priority levels
- DISPATCHING
- x86: IDT, which resides any where in memory
- pdp: dispatch table at fixed physical address
- DISPATCH ENTRY FORMAT
- x86: IDT entry -- contain CS:EIP
- pdp: trap;br7+0. -- entry point and new PSW
- MODE SWITCH
- x86: low two bits of CS hold CPL (11 -- kernel, 00 -- user)
- pdp: kernel vs user specified in PSW
- ADDRESSING SWITCH
- x86: no switch
paging is not changed because %cr3 is not reloaded
However, more of the VA space is accessible--notably the KERNEL only VA regions
(this ignores segmentation since our convention is to disable segmentation for the lab OS)
- pdp: complete switch
kernel mode -- implicitely selects new set of segementation registers
- STACK SWITCH
- x86: new stack is: TSS ss0:esp0
- pdp: kernel mode -- implicitely uses kernel sp register