2011$BG/(B02$B7n(B08$BF|(B
$B>pJs2J3XN`(B $B%*%Z%l!<%F%#%s%0%7%9%F%`(B II
$BC^GHBg3X(B $B%7%9%F%`>pJs9)3X8&5f2J(B
$B%3%s%T%e!<%?%5%$%(%s%9@l96(B, $BEE;R!&>pJs9)3X7O(B
$B?7>k(B $BLw(B
<yas@is.tsukuba.ac.jp>
$B$3$N%Z!<%8$O!"
http://www.coins.tsukuba.ac.jp/~yas/coins/os2-2010/2011-02-08
$B$"$k$$$O!"
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
$B?^(B? x86 $B$N(B Intel 8259
$B?^(B? x86 $B$N(B APIC
APIC $B$O!"
$ cat /proc/interrupts
CPU0 CPU1
0: 4208761 38584 IO-APIC-edge timer
1: 0 3 IO-APIC-edge i8042
7: 0 0 IO-APIC-edge parport0
8: 1 2 IO-APIC-edge rtc
9: 0 0 IO-APIC-level acpi
12: 3 1 IO-APIC-edge i8042
50: 5380 86508 PCI-MSI ahci
74: 346 0 PCI-MSI HDA Intel
98: 294 28232 PCI-MSI eth1
169: 130 57006 IO-APIC-level uhci_hcd:usb3
177: 0 0 IO-APIC-level uhci_hcd:usb4, uhci_hcd:usb7
217: 358 149530 IO-APIC-level ehci_hcd:usb1, uhci_hcd:usb5
225: 0 0 IO-APIC-level ehci_hcd:usb2, uhci_hcd:usb6
233: 0 0 IO-APIC-level uhci_hcd:usb8
NMI: 0 0
LOC: 4246864 4246863
ERR: 0
MIS: 0
$
$BNc(B:
include/linux/interrupt.h
typedef irqreturn_t (*irq_handler_t)(int, void *);
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
drivers/char/rtc.c
96: static unsigned long rtc_port;
97: static int rtc_irq;
...
191: static unsigned long rtc_status; /* bitmapped status byte. */
192: static unsigned long rtc_freq; /* Current periodic IRQ rate */
193: static unsigned long rtc_irq_data; /* our output to the world */
...
953: static int __init rtc_init(void)
954: {
...
1000: if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc",
1001: (void *)&rtc_port)) {
1002: rtc_has_irq = 0;
1003: printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
1004: return -EIO;
1005: }
...
790: }
239: static irqreturn_t rtc_interrupt(int irq, void *dev_id)
240: {
...
248: spin_lock(&rtc_lock);
249: rtc_irq_data += 0x100;
250: rtc_irq_data &= ~0xff;
...
259: rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
...
262: if (rtc_status & RTC_TIMER_ON)
263: mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
264:
265: spin_unlock(&rtc_lock);
266:
267: /* Now do the rest of the actions */
268: spin_lock(&rtc_task_lock);
269: if (rtc_callback)
270: rtc_callback->func(rtc_callback->private_data);
271: spin_unlock(&rtc_task_lock);
272: wake_up_interruptible(&rtc_wait);
273:
274: kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
275:
276: return IRQ_HANDLED;
277: }
$B%W%m%;%9!&%3%s%F%-%9%H$G$G$-$k$3$H!#(B
$B3d$j9~$_%3%s%F%-%9%H$G$O!"$3$N$&$h$&$J$3$H$O$G$-$J$$!#(B
$BB.$d$+$K=*N;$9$Y$-$G$"$k!#(Bbusy loop $B$O$G$-$k$,!"$"$^$j(B
$B$d$i$J$$J}$,$h$$!#B>$N3d$j9~$_$O!"
$B"!(Bx86 Interrupt Descriptor Table (IDT)
x86 IDT $B$O!"%O!<%I%&%'%"!&%l%Y%k$N3d$j9~$_%O%s%I%i$N0lMwI=$rJ];}$9$k!#(B
$B$=$N@hF,HVCO$O!"(BIDTR $B%l%8%9%?$KJ]B8$5$l$k!#(B
arch/x86/include/asm/irq_vectors.h
131: #define NR_VECTORS 256
arch/x86/kernel/traps.c
78: gate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, };
...
837: void __init trap_init(void)
838: {
...
849: set_intr_gate(0, ÷_error);
850: set_intr_gate_ist(2, &nmi, NMI_STACK);
...
896: set_system_trap_gate(SYSCALL_VECTOR, &system_call);
897: set_bit(SYSCALL_VECTOR, used_vectors);
arch/x86/include/asm/irq_vectors.h:
50: # define SYSCALL_VECTOR 0x80
$B"!(Bdo_IRQ
x86 Linux $B$G$O!"(BInterrupt Descriptor Table $B$K=>$$!"(Bdo_IRQ() $B$,8F$P$l$k!#(B
$B0z?t$K$O!"(Bx86 $B$N%l%8%9%?$rI=8=$7$?9=B$BN$X$N%]%$%s%?$,EO$5$l$k!#$3$l$K(B
$B$h$j!"3d$j9~$_$,H/@8$7$?;~$N%l%8%9%?$NCM$,$o$+$k!#3d$j9~$_%O%s%I%i$,M-(B
$B8z$G!"3d$j9~$_@~$KEPO?$5$l$F$$$l$P!":G=*E*$K$O!"(Bhandle_IRQ_event()$B!!$H(B
$B$$$&!"(BCPU $B$H$OFHN)$N3d$j9~$_%O%s%I%i$,8F$P$l$k!#(B
$B"!(Bhandle_IRQ_event()
kernel/irq/handle.c
368: irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
369: {
370: irqreturn_t ret, retval = IRQ_NONE;
371: unsigned int status = 0;
372:
373: do {
...
375: ret = action->handler(irq, action->dev_id);
...
378: switch (ret) {
...
410: case IRQ_HANDLED:
411: status |= action->flags;
412: break;
413:
414: default:
415: break;
416: }
417:
418: retval |= ret;
419: action = action->next;
420: } while (action);
421:
422: if (status & IRQF_SAMPLE_RANDOM)
423: add_interrupt_randomness(irq);
424: local_irq_disable();
425:
426: return retval;
427: }
$B"!3d$j9~$_$N5v2D!&6X;_(B
$B%^%/%m$r$D$+$C$FJ]B8$7$?$j2sI|$7$?$j$9$k!#(B
unsigned long flags;
local_irq_save(flags); /* $B3d$j9~$_6X;_(B */
...
local_irq_restore(flags); /* $B3d$j9~$_5v2D(B (save $B$N;~$N>uBV$K$b$I$k(B) */
$BC10l(BCPU$B$N(B x86 $B$G$O!"(Bcli() $B$H(B sti() $B$G3d$j9~$_$N6X;_$H5v2D$r@_Dj$9$kJ}K!(B
$B$,$"$C$?!#$=$l$=$lF1L>$N(B CPU $B$NL?Na$r
$BFCDj$N3d$j9~$_HV9f$N3d$j9~$_$r6X;_$9$kJ}K!$b$"$k!#(B
void disable_irq(unsigned ing irq);
// $BA4(BCPU$B$N3d$j9~$_$r6X;_$9$k(B
void disable_irq_nosync(unsigned ing irq);
// $BF1>e!#$?$@$7!"3d$j9~$_%O%s%I%i$N=*N;$rBT$?$J$$!#(B
void enable_irq(unsigned ing irq);
// $B3d$j9~$_$r5v2D$9$k!#(B
void synchronize_irq(unsigned ing irq);
// $B3d$j9~$_%O%s%I%i$N=*N;$rBT$D!#(B