- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
Interrupts (Hardware)
展开查看详情
1 .Interrupts (Hardware)
2 .Interrupt Descriptor Table Slide # 2 IDT specified as a segment using the IDTR register
3 .Slide # 3
4 .Calling the IRQ handler
5 .Interrupt Context
6 .Exceptions First 32 IRQ vectors in IDT Correspond to events generated by the CPU Page fault, Divide by zero, invalid instruction, etc Full list in the CPU architecture manuals Generally its an “error” or “exception” encountered during CPU instruction execution IDT is referenced directly by the CPU Completely internalized
7 .External Interrupts Events triggered by devices connected to the system Network packet arrivals, disk operation completion, timer updates, etc Can be mapped to any IRQ vector above the exceptions (IRQs 32-255) External because they happen outside the CPU External logic signals CPU and notifies it which handler to execute Managed by Interrupt Controller Special device included in southbridge
8 .Interrupt Controllers Translate device IRQ signals to CPU IRQ vectors Each device has only a single pin High = IRQ pending, Low = no IRQ Interrupt controller maps devices to vectors Two x86 controller classes Legacy: 8259 PIC Connected to a set of default I/O ports on CPU Modern: APIC + IOAPIC Memory mapped into each CPUs physical memory (How?) Next generation APIC (x2PIC) accessed via MSRs Model specific registers – control registers accessed via special instructions WRMSR, RDMSR
9 .8259 PIC Allows the mapping of 8 IRQ pins (from devices) to 8 separate vectors (to CPU) Assumes continuous numbering Assign the PIC a vector offset, E ach pin index is added to that offset to calculate the vector
10 .8259 Cont’d 1 PIC only supports 8 device lines Often more than 8 devices in a system S olution: Add more PICs But x86 CPUs only have 1 INTR input pin X86 Solution: Chain the PICs together (master and slave) Slave PIC is attached to the 2 nd IRQ pin of the master CPU interfaces directly with master
11 .PC architecture defines common default devices to each PIC input pin Initially PIC vector offsets set to 32, just above exceptions
12 .IRQ Example IRQ INT Hardware Device 0 32 Timer 1 33 Keyboard 2 34 PIC Cascading 3 35 Second serial port 4 36 First serial port 6 38 Floppy Disk 8 40 System Clock 10 42 Network Interface 11 43 USB port, sound card 12 44 PS/2 Mouse 13 45 Math Coprocessor 14 46 EIDE first controller 15 47 EIDE second controller Slide # 12
13 .APIC Problem: PICs don’t support multiple CPUs Only one INT signal, so only one CPU can receive interrupts SMP required a new solution APIC + IOAPIC Idea: Separate the responsibility of the PIC into two components APIC = Interfaces with CPU IOAPIC = Interfaces with devices
14 .APIC Each CPU has its own local APIC In charge of keeping track of interrupts bound for its assigned CPU Since Pentium Pro, the APIC has been implemented in the CPU die APIC interfaces with CPUs interrupt pins to invoke correct IDT vector This is its primary responsibility But it does other things as well Timer – APIC has its own timer device per CPU Legacy PC had a separate timer device on the motherboard Allows each CPU to have its own timer Inter-Processor Interrupt – Allows cross CPU communication 1 CPU can send an interrupt to another one Why would you want to do this? How does the APIC do this?
15 .ICC bus APICs and IOAPICs share a common communication bus ICC bus: Interrupt Controller Communication Bus Handles routing of interrupts to the correct APIC
16 .IOAPIC Connects devices to ICC bus Must still translate IRQ pins from devices to vectors But now must also select destination APIC Typically has 24 I/O Redirection Table Registers Specifies vector # to send to APIC Specifies which APIC (or group of APICS) can accept the IRQ Several methods of specifying APIC addresses Allows masking of IRQ pins
17 .IO-APIC configuration Usually initialized to mirror the PIC configuration But as architecture diverge from legacy PC, this is becoming harder Generally speaking resource discovery is UGLY OS then can map IO-APIC entries to which ever vector on whichever CPU they want This means that IRQ vectors can be reused between CPUs
18 .Interrupt Vectors Vector Range Use 0-19 Nonmaskable interrupts and exceptions. 20-31 Intel-reserved 32-127 External interrupts (IRQs) 128 System Call exception 129-238 External interrupts (IRQs) 239 Local APIC timer interrupt 240 Local APIC thermal interrupt 241-250 Reserved by Linux for future use 251-253 Interprocessor interrupts 254 Local APIC error interrupt 255 Local APIC suprious interrupt Slide # 18
19 .IRQ Handling Monitor IRQ lines for raised signals. If multiple IRQs raised, select lowest # IRQ. If raised signal detected Converts raised signal into vector (0-255). Stores vector in I/O port, allowing CPU to read. Sends raised signal to CPU INTR pin. Waits for CPU to acknowledge interrupt. Kernel runs do_IRQ() . Clears INTR line. Goto step 1. Slide # 19
20 .do_IRQ Kernel jumps to entry point in entry.S . Entry point saves registers, calls do_IRQ() . Finds IRQ number in saved %EAX register. Looks up IRQ descriptor using IRQ #. Acknowledges receipt of interrupt. Disables interrupt delivery on line. Calls handle_IRQ_event() to run handlers. Cleans up and returns. Jumps to ret_from_intr(). Slide # 20
21 .handle_IRQ_event() fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, struct irqaction *action) { int ret, retval = 0, status = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { ret = action->handler(irq, action->dev_id, regs); if (ret == IRQ_HANDLED) status |= action->flags; retval |= ret; action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); return retval; } Slide # 21
22 .Interrupt Handlers Function kernel runs in response to interrupt. More than one handler can exist per IRQ. Must run quickly. Resume execution of interrupted code. How to deal with high work interrupts? Ex: network, hard disk Slide # 22
23 .Top and Bottom Halves Top Half The interrupt handler. Current interrupt disabled, possibly all disabled. Runs in interrupt context, not process context. Can ’ t sleep. Acknowledges receipt of interrupt. Schedules bottom half to run later. Bottom Half Runs in process context with interrupts enabled. Performs most work required. Can sleep. Ex: copies network data to memory buffers. Slide # 23
24 .Interrupt Context Not associated with a process. Cannot sleep: no task to reschedule. current macro points to interrupted process. Shares kernel stack of interrupted process. Be very frugal in stack usage. Slide # 24
25 .Registering a Handler request_irq() Register an interrupt handler on a given line. free_irq() Unregister a given interrupt handler. Disable interrupt line if all handlers unregistered. Slide # 25
26 .Registering a Handler int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) Slide # 26 irqflaqs = SA_INTERRUPT | SA_SAMPLE_RANDOM | SA_SHIRQ
27 .Writing an Interrupt Handler Differentiating between devices Pre-2.0: irq Current: dev_id Registers Pointer to registers before interrupt occurred. Return Values IRQ_NONE : Interrupt not for handler. IRQ_HANDLED : Interrupted handled. Slide # 27 irqreturn_t ih(int irq,void *devid,struct pt_regs *r)
28 .RTC Handler irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { spin_lock (&rtc_lock); rtc_irq_data += 0x100; rtc_irq_data &= ~0xff; if (rtc_status & RTC_TIMER_ON) mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100); spin_unlock (&rtc_lock); /* Now do the rest of the actions */ spin_lock(&rtc_task_lock); if (rtc_callback) rtc_callback->func(rtc_callback->private_data); spin_unlock(&rtc_task_lock); wake_up_interruptible(&rtc_wait); kill_fasync (&rtc_async_queue, SIGIO, POLL_IN); return IRQ_HANDLED; } Slide # 28
29 .Interrupt Control Disable/Enable Local Interrupts local_irq_disable(); /* interrupts are disabled */ local_irq_enable(); Saving and Restoring IRQ state Useful when don ’ t know prior IRQ state. unsigned long flags; local_irq_save(flags); /* interrupts are disabled */ local_irq_restore(flags); /* interrupts in original state */ Slide # 29