Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Interrupts Sources: * Intel CPU manuals * OSFaqWiki (osdev.org) * osdever.net 1 Background ● Interrupts – – What they are What devices cause them ● ● Hardware CPU itself! 2 CPU Interrupts ● "Internal" – – – Caused by program faults or hardware errors Bad memory address User program executed privileged instruction ● – – – ● User mode vs. Supervisor mode Illegal/invalid instruction opcode Math error (division by zero) INT instruction (create on-demand) Numbered 0-31 3 CPU Interrupts ● ● ● ● ● ● ● ● ● ● ● 0=div by zero 1=debug 2=nmi 3=int3 4=overflow 5=bound 6=illegal opcode 7=no fpu 8=fault handler fault 9=fpu overrun 10=bad tss ● ● ● ● ● ● ● ● ● ● 11=segment absent 12=stack fault 13=illegal address 14=page fault 15=reserved 16=fpu error 17=unaligned data 18=machine check 19=sse error 20-31=reserved 4 External Interrupts ● Source: Hardware – – – Also called IRQ's PIC Re-mappable to any range of 16 interrupts CPU PIC 5 Interrupt Handling ● CPU procedures when interrupt pin asserted: – – – – PUSH %eflags PUSH %cs PUSH %eip PUSH errorcode (optional; depends on interrupt) ● – ● These are underlined in list of interrupts given before jmp int_table[ interrupt_index ] That's all it does! – You must do the rest! 6 Interrupt Table ● Associates code addresses with interrupt numbers – Just an array of 32 bit addresses CPU RAM 7 Interrupt Table ● Divide into three parts: – Lowest level: stub: One per interrupt ● ● ● – Middle level ● ● – Pushes all registers to stack Calls top-level handler Top level ● ● Pushes dummy error code if needed Pushes interrupt number to stack Jumps to mid-level handler Examines interrupt type, takes action Lowest and Middle must be written in assembly! 8 Lowest Level ● Basic format: for each stub interrupt_xx: pushl $0 //if cpu didn't push errcode pushl $xx //interrupt number jmp midlevel_handler 9 Middle Level ● ● midlevel_handler: push %ds push %es ...etc for fs, gs, ss... push %eax push %ebx ...etc... for ecx,edx,esi,edi,ebp,esp call highlevel_interrupt_handler//c code pop reg's in reverse order add $8,%esp //discard errcode, int # iret //return from interrupt iret pops %eip, %cs, and %eflags 10 High Level ● void highlevel_interrupt_handler(void) { ...do something... } 11 Problem! ● How does the handler know what to do? – – Needs to be told what the interrupt was Consider stack layout just before we call C code... 12 Stack ● Grows down! top of stack ... previous contents ... eflags cs eip errcode int # ds es fs gs ss eax ebx ecx edx esi edi ebp esp 13 C Calling Convention ● Consider code; void foo(int a, int b, int c){ ...do something... } int main(int argc, char* argv[]) { foo( 1 , 3 , 5 ); return 0; } Push from right to left: ●push 5 ●push 3 ●push 1 14 Send Pointer In! ● pushl %esp call highlevel_interrupt_handler add $4, %esp top of stack ... previous contents ... eflags cs eip errcode int # ds es fs gs ss eax ebx ecx edx esi edi ebp esp ptr 15 C Code ● ● ● ● void highlevel_interrupt_handler( StateBlock* sb ); typedef struct _StateBlock{ unsigned esp, ebp, edi, esi, edx, ... } __attribute__((packed)) StateBlock; C function can read the StateBlock, get info from stack C function can change StateBlock and this changes info when returning from interrupt! 16 Building Interrupt Table ● Interrupt table entry: 16 bits addr high 8 bits 8 bits 16 bits 16 bits 0x8e (flags) 0 selector addr low msb ● lsb Easy way: build in assembly – – – Really! Use script, create list of functions (array) Then use from C 17 Loading Interrupt Register ● Tell CPU where the table is: typedef struct _IDTLoc{ unsigned short size; unsigned location; }__attribute__((packed)) IDTLoc; IDTLoc loc; loc.size = 256*8; loc.location = (unsigned) &(my_table); asm volatile ( “lidt (%%eax)” : : “a” (&loc)); 18 Assignment ● ● ● ● Implement interrupt handler In C code: just print interrupt number, then halt Test with forced division by zero: int a = 5; int b = 0; int c = 5/0; This should trigger interrupt zero. 19