interrupts and system
play

Interrupts and System if (y) { //... y = 2 / x; Calls } - PDF document

2/18/13 Background: Control Flow pc // x = 2, y = true void printf(va_args) { Interrupts and System if (y) { //... y = 2 / x; Calls } printf(x); Don Porter } //... CSE 306 Regular control flow: branches and calls (logically


  1. 2/18/13 ¡ Background: Control Flow pc // x = 2, y = true void printf(va_args) { Interrupts and System if (y) { //... y = 2 / x; Calls } printf(x); Don Porter } //... CSE 306 Regular control flow: branches and calls (logically follows source code) Background: Control Flow Lecture goal ò Understand the hardware tools available for irregular pc // x = 0, y = true void handle_divzero() Divide by zero! control flow. { Program can’t make if (y) { progress! ò I.e., things other than a branch in a running program y = 2; y = 2 / x; ò Building blocks for context switching, device } management, etc. printf(x); } //... Irregular control flow: exceptions, system calls, etc. Two types of interrupts Asynchronous Example Stack Stack ò Synchronous: will happen every time an instruction executes (with a given program state) Disk ESP ESP Interrupt! ò Divide by zero ò System call ò Bad pointer dereference ò Asynchronous: caused by an external event EIP EIP if (x) { Disk_handler (){ printf(“Boo”); ò Usually device I/O ... ... } ò Timer ticks (well, clocks can be considered a device) printf(va_args…){ ... User Kernel 1 ¡

  2. 2/18/13 ¡ Intel nomenclature Lecture outline ò Interrupt – only refers to asynchronous interrupts ò Overview ò Exception – synchronous control transfer ò How interrupts work in hardware ò How interrupt handlers work in software ò Note: from the programmer’s perspective, these are ò How system calls work handled with the same abstractions ò New system call hardware on x86 Interrupt overview x86 interrupt table Device IRQs 128 = Linux ò Each interrupt or exception includes a number indicating System Call its type ò E.g., 14 is a page fault, 3 is a debug breakpoint … … … ò This number is the index into an interrupt table 0 31 47 255 Software Configurable Reserved for the CPU x86 interrupt overview Software interrupts ò Each type of interrupt is assigned an index from 0—255. ò The int <num> instruction allows software to raise an interrupt ò 0—31 are for processor interrupts; generally fixed by Intel ò 0x80 is just a Linux convention. ò E.g., 14 is always for page faults ò You could change it to use 0x81! ò 32—255 are software configured ò There are a lot of spare indices ò 32—47 are often for device interrupts (IRQs) ò You could have multiple system call tables for different Most device’s IRQ line can be configured ò purposes or types of processes! ò Look up APICs for more info (Ch 4 of Bovet and Cesati) ò Windows does: one for the kernel and one for win32k ò 0x80 issues system call in Linux (more on this later) 2 ¡

  3. 2/18/13 ¡ Software interrupts, cont What happens (generally): ò Control jumps to the kernel ò OS sets ring level required to raise an interrupt ò At a prescribed address (the interrupt handler) ò Generally, user programs can’t issue an int 14 (page ò The register state of the program is dumped on the kernel’s fault manually) stack ò An unauthorized int instruction causes a general protection fault ò Sometimes, extra info is loaded into CPU registers ò E.g., page faults store the address that caused the fault in the ò Interrupt 13 cr2 register ò Kernel code runs and handles the interrupt ò When handler completes, resume program (see iret instr.) How it works (HW) How is this configured? ò How does HW know what to execute? ò Kernel creates an array of Interrupt descriptors in memory, called Interrupt Descriptor Table, or IDT ò Where does the HW dump the registers; what does it use as the interrupt handler’s stack? ò Can be anywhere in physical memory ò Pointed to by special register ( idtr ) ò c.f., segment registers and gdtr and ldtr � ò Entry 0 configures interrupt 0, and so on x86 interrupt table x86 interrupt table idtr idtr … … … … … … 0 31 47 255 0 31 47 255 14 Code Segment: Kernel Code Segment Offset: &page_fault_handler //linear addr Ring: 0 // kernel Address of Interrupt Table Present: 1 Gate Type: Exception 3 ¡

  4. 2/18/13 ¡ Interrupt Descriptor x86 interrupt table idtr ò Code segment selector ò Almost always the same (kernel code segment) … … … ò Recall, this was designed before paging on x86! ò Segment offset of the code to run 0 3 31 47 255 ò Kernel segment is “flat”, so this is just the linear address ò Privilege Level (ring) ò Interrupts can be sent directly to user code. Why? Code Segment: Kernel Code Segment Offset: &breakpoint_handler //linear addr ò Present bit – disable unused interrupts Ring: 3 // user ò Gate type (interrupt or trap/exception) – more in a bit Present: 1 Gate Type: Exception Interrupt Descriptors, ctd. How it works (HW) ò In-memory layout is a bit confusing ò How does HW know what to execute? ò Like a lot of the x86 architecture, many interfaces were ò Interrupt descriptor table specifies what code to run and at later deprecated what privilege ò This can be set up once during boot for the whole system ò Where does the HW dump the registers; what does it use as the interrupt handler’s stack? ò Specified in the Task State Segment Task State Segment (TSS) TSS, cont. ò Another magic control block ò Simple model: specify a TSS for each process ò Pointed to by special task register (tr) ò Optimization (for a simple uniprocessor OS): ò Actually stored in the segment table (more on segmentation later) ò Why not just share one TSS and kernel stack per-process? ò Hardware-specified layout ò Linux generalization: ò Lots of fields for rarely-used features ò One TSS per CPU ò Two features we care about in a modern OS: ò Modify TSS fields as part of context switching ò 1) Location of kernel stack (fields ss0/esp0) ò 2) I/O Port privileges (more in a later lecture) 4 ¡

  5. 2/18/13 ¡ Summary Lecture outline ò Most interrupt handling hardware state set during boot ò Overview ò Each interrupt has an IDT entry specifying: ò How interrupts work in hardware ò What code to execute, privilege level to raise the interrupt ò How interrupt handlers work in software ò Stack to use specified in the TSS ò How system calls work ò New system call hardware on x86 Interrupt handlers Lecture outline ò Just plain old code in the kernel ò Overview ò Sort of like exception handlers in Java ò How interrupts work in hardware ò But separated from the control flow of the program ò How interrupt handlers work in software ò The IDT stores a pointer to the right handler routine ò How system calls work ò New system call hardware on x86 What is a system call? System call “interrupt” ò Originally, system calls issued using int instruction ò A function provided to applications by the OS kernel ò Dispatch routine was just an interrupt handler ò Generally to use a hardware abstraction (file, socket) ò Or OS-provided software abstraction (IPC, scheduling) ò Like interrupts, system calls are arranged in a table ò Why not put these directly in the application? ò See arch/x86/kernel/syscall_table*.S in Linux source ò Program selects the one it wants by placing index in eax ò Protection of the OS/hardware from buggy/malicious programs register ò Applications are not allowed to directly interact with ò Arguments go in the other registers by calling convention hardware, or access kernel data structures ò Return value goes in eax � 5 ¡

  6. 2/18/13 ¡ How many system calls? But why use interrupts? ò Also protection ò Linux exports about 350 system calls ò Forces applications to call well-defined “public” functions ò Windows exports about 400 system calls for core APIs, and another 800 for GUI methods ò Rather than calling arbitrary internal kernel functions ò Example: public foo() { if (!permission_ok()) return –EPERM; Calling _foo() directly would return _foo(); // no permission check circumvent } permission check Summary Lecture outline ò System calls are the “public” OS APIs ò Overview ò Kernel leverages interrupts to restrict applications to ò How interrupts work in hardware specific functions ò How interrupt handlers work in software ò Lab 1 hint: How to issue a Linux system call? ò How system calls work ò int $0x80 , with system call number in eax register ò New system call hardware on x86 Around P4 era… Idea ò Processors got very deeply pipelined ò What if we cache the IDT entry for a system call in a special CPU register? ò Pipeline stalls/flushes became very expensive ò No more cache misses for the IDT! ò Cache misses can cause pipeline stalls ò Maybe we can also do more optimizations ò System calls took twice as long from P3 to P4 ò Assumption: system calls are frequent enough to be ò Why? worth the transistor budget to implement this ò IDT entry may not be in the cache ò What else could you do with extra transistors that helps ò Different permissions constrain instruction reordering performance? 6 ¡

Recommend


More recommend