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