{"id":449,"date":"2020-08-18T19:23:47","date_gmt":"2020-08-18T20:23:47","guid":{"rendered":"http:\/\/www.linux-tutorial.info\/?page_id=77"},"modified":"2020-08-22T19:26:02","modified_gmt":"2020-08-22T20:26:02","slug":"this-is-the-page-title-toplevel-282","status":"publish","type":"page","link":"http:\/\/www.linux-tutorial.info\/?page_id=449","title":{"rendered":"Interrupts and Interrupt Handling"},"content":{"rendered":"\n<title>Interrupts and Interrupt Handling<\/title>\n<p>\nThis chapter looks at how interrupts are handled by the Linux kernel.\nWhilst the kernel has generic mechanisms and interfaces for handling\ninterrupts, most of the interrupt handling details are architecture specific.\n<img decoding=\"async\" src=\"interrupts.gif\">\n<p>\n<icaption>Figure 7.1: A Logical Diagram of Interrupt Routing<icaption>\n<p>\nLinux uses a lot of different pieces of hardware to perform many different tasks.\nThe video device drives the monitor, the <glossary>IDE<\/glossary> device drives the disks and\nso on.You could drive these devices synchronously, that is you could send a\nrequest for some operation (say writing a block of memory out to disk) and\nthen wait for the operation to complete.\nThat method, although it would work, is very inefficient and the operating\nsystem would spend a lot of time &#8220;busy doing nothing&#8221; as it waited for\neach operation to complete.\nA better, more efficient, way is to make the request and then do other, more\nuseful work and later be interrupted by the device when it has finished the\nrequest.\nWith this scheme, there may be many outstanding requests to the devices\nin the system all happening at the same time.\n<p>\nThere has to be some hardware support for the devices to interrupt whatever\nthe <glossary>CPU<\/glossary> is doing.\nMost, if not all, general purpose processors such as the Alpha AXP&nbsp;\nuse a similar method.\nSome of the physical pins of the CPU are wired such that changing the\nvoltage (for example changing it from +5v to -5v) causes the <glossary>CPU<\/glossary> to\nstop what it is doing and to start executing special code to handle the\ninterruption; the <glossary>interrupt<\/glossary> handling code.\nOne of these pins might be connected to an interval timer and receive an\ninterrupt every 1000th of a second, others may be connected to the\nother devices in the system, such as the <glossary>SCSI<\/glossary> controller.\n<p>\nSystems often use an interrupt controller to group the device interrupts together before\npassing on the signal to a single interrupt pin on the <glossary>CPU<\/glossary>.\nThis saves interrupt pins on the C<glossary>PU<\/glossary> and also gives flexibility when designing systems.\nThe interrupt controller has mask and status registers that control the interrupts.\nSetting the bits in the mask register enables and disables interrupts and the status\nregister returns the currently active interrupts in the system.\n<p>\nSome of the interrupts in the system may be hard-wired, for example, the real time clock&#8217;s\ninterval timer may be permanently  connected to pin 3 on the interrupt controller.\nHowever, what some of the pins are connected to may be determined by\nwhat controller card is plugged into a particular <glossary>ISA<\/glossary> or\n<glossary>PCI<\/glossary> slot. For example, pin 4 on the interrupt controller may be\nconnected to PCI slot number 0 which might one day have an ethernet card in it but the next have\na <glossary>SCSI<\/glossary> controller in it.  The bottom line is that each system has its own\ninterrupt routing mechanisms and the operating system must be flexible\nenough to cope.\n<p>\nMost modern general purpose microprocessors handle the interrupts the same way. When a hardware\ninterrupt occurs the <glossary>CPU<\/glossary> stops executing the instructions that\nit was executing and jumps to a location in memory that either contains the\n<glossary>interrupt<\/glossary> handling code or an instruction branching to the interrupt\nhandling code.\nThis code usually operates in a special mode for the <glossary>CPU<\/glossary>,\n<em>interrupt mode<\/em>, and, normally, no other interrupts can happen in this mode.\nThere are exceptions though; some <glossary>CPU<\/glossary>s rank the interrupts in priority and higher level\ninterrupts may happen.\nThis means that the first level <glossary>interrupt<\/glossary> handling code must be very\ncarefully written and it often has its own stack, which it uses to store the CPU&#8217;s execution\nstate (all of the CPU&#8217;s normal <glossary>register<\/glossary>s and context) before it goes off and\nhandles the interrupt. Some CPUs have a special set of registers that only exist in\n<glossary>interrupt<\/glossary> mode, and the interrupt code can use these registers to do most\nof the context saving it needs to do.\n<p>\nWhen the interrupt has been handled, the <glossary>CPU<\/glossary>&#8216;s state is restored and the\ninterrupt is dismissed. The CPU will then continue to doing whatever it was doing before being\ninterrupted. It is important that the interrupt processing code is as efficient as\npossible and that the operating system does not block interrupts too often\nor for too long.\n<p>\n<h2>Programmable Interrupt Controllers<\/h2>\n<p>\nSystems designers are free to use whatever interrupt architecture they wish but\nIBM PCs use the Intel 82C59A-2 <glossary>CMOS<\/glossary> Programmable Interrupt Controller\nor its derivatives.\nThis controller has been around since the dawn of the PC and it is programmable with its registers being at well\nknown locations in the <glossary>ISA<\/glossary> address space.\nEven very modern support logic chip sets keep equivalent registers in the\nsame place in <glossary>ISA<\/glossary> memory.\nNon-Intel based systems such as Alpha AXP&nbsp;based PCs are free from these architectural\nconstraints and so often use different interrupt controllers.\n<p>\nThe figure above shows that there are two 8 bit controllers chained together; each having a mask and\nan <glossary>interrupt<\/glossary> status\n<glossary>register<\/glossary>, PIC1 and PIC2.\nThe mask registers are at addresses <em>0x21<\/em> and <em>0xA1<\/em> and the status registers\nare at <em>0x20<\/em> and <em>0xA0<\/em>\nWriting a one to a particular bit of the mask register enables an interrupt, writing\na zero disables it. So, writing one to bit 3 would enable <glossary>interrupt<\/glossary> 3,\nwriting zero would disable it. Unfortunately (and irritatingly), the\n<glossary>interrupt<\/glossary> mask registers are write only, you cannot read back the value\nthat you wrote.\nThis means that Linux must keep a local copy of what it has set the mask registers to.\nIt modifies these saved masks in the interrupt enable and disable routines and writes\nthe full masks to the registers every time.\n<p>\nWhen an <glossary>interrupt<\/glossary> is signalled, the interrupt handling code reads the two\ninterrupt status registers (ISRs).\nIt treats the ISR at <em>0x20<\/em> as the bottom eight bits of a sixteen bit\ninterrupt register and the ISR at <em>0xA0<\/em> as the top eight bits.\nSo, an <glossary>interrupt<\/glossary> on bit 1 of the ISR at <em>0xA0<\/em> would be treated as\nsystem interrupt 9.\nBit 2 of PIC1 is not available as this is used to chain interrupts from PIC2,\nany <glossary>interrupt<\/glossary> on PIC2 results in bit 2 of PIC1 being set.\n<p>\n<h2>Initializing the Interrupt Handling Data Structures<\/h2>\nThe <glossary>kernel<\/glossary>&#8216;s\n<glossary>interrupt<\/glossary> handling data structures are set up by the device drivers as they\nrequest control of the system&#8217;s interrupts. To do this the device driver uses a set of Linux\nkernel services that are used to request an <glossary>interrupt<\/glossary>, enable it and to disable it.\n<p>\nThe individual <glossary>device driver<\/glossary>s call these routines to register their\ninterrupt handling routine addresses.\n<p>\nSome interrupts are fixed by convention for the PC architecture and so the\ndriver simply requests its interrupt when it is initialized.\nThis is what the floppy disk device driver does; it always requests IRQ 6.\nThere may be occassions when a device driver does not know which interrupt the device will use.\nThis is not a problem for <glossary>PCI<\/glossary> device drivers as they always know what\ntheir interrupt number is. Unfortunately there is no easy way for <glossary>ISA<\/glossary>\ndevice drivers to find their <glossary>interrupt<\/glossary> number.\nLinux solves this problem by allowing device drivers to probe for their interrupts.\n<p>\nFirst, the <glossary>device driver<\/glossary> does something to the device that causes it to\ninterrupt. Then all of the unassigned interrupts in the system are enabled.\nThis means that the device&#8217;s pending <glossary>interrupt<\/glossary> will now be delivered via the programmable\ninterrupt controller.\nLinux reads the interrupt status register and returns its contents to the device driver.\nA non-zero result means that one or more interrupts occured during the probe.\nThe driver now turns probing off and the unassigned interrupts are all disabled.\n<p>\nIf the <glossary>ISA<\/glossary> device driver has successfully found its IRQ number then it can\nnow request control of it as normal.\n<p>\nPCI based systems are much more dynamic than <glossary>ISA<\/glossary> based systems.\nThe interrupt pin that an ISA device uses is often set using jumpers on the hardware device and\nfixed in the device driver.\nOn the other hand, <glossary>PCI<\/glossary> devices have their interrupts allocated by the\nPCI <glossary>BIOS<\/glossary> or the PCI subsystem as PCI is initialized when the system boots.\nEach PCI device may use one of four interrupt pins, A, B, C or D.\nThis was fixed when the device was built and most devices default to interrupt on pin A.\nThe PCI <glossary>interrupt<\/glossary> lines A, B, C and D for each PCI slot are routed to the interrupt controller.\nSo, Pin A from PCI slot 4 might be routed to pin 6 of the interrupt controller, pin B of PCI slot\n4 to pin 7 of the interrupt controller and so on.\n<p>\nHow the <glossary>PCI<\/glossary> interrupts are routed is entirely system specific and there must be some\nset up code which understands this PCI <glossary>interrupt<\/glossary> routing topology.\nOn Intel based PCs this is the system <glossary>BIOS<\/glossary> code that runs at boot time but\nfor system&#8217;s without BIOS (for example Alpha AXP&nbsp;based systems) the Linux kernel does this\nsetup.\n<p>\nThe <glossary>PCI<\/glossary> setup code writes the pin number of the interrupt controller into\nthe PCI configuration header for each device. It determines the interrupt pin (or IRQ) number\nusing its knowledge of the PCI interrupt routing topology\ntogether with the devices <glossary>PCI<\/glossary> slot number and which PCI interrupt pin that\nit is using. The <glossary>interrupt<\/glossary> pin that a device uses is fixed and is kept in a\nfield in the PCI configuration header for this device. It writes this information into the\n<em>interrupt line<\/em> field that is reserved for this purpose. When the device driver runs,\nit reads this information and uses it to request control of the interrupt\nfrom the Linux <glossary>kernel<\/glossary>.\n<p>\nThere may be many <glossary>PCI<\/glossary> interrupt sources in the system, for example when\nPCI-PCI bridges are used. The number of interrupt sources may exceed the number of pins on the\nsystem&#8217;s programmable <glossary>interrupt<\/glossary> controllers. In this case, PCI devices may\nshare interrupts, one pin on the interrupt controller taking interrupts from more than one\n<glossary>PCI<\/glossary> device.\nLinux supports this by allowing the first requestor of an interrupt source to declare whether it may be shared.\nSharing interrupts results in several <tt>irqaction<\/tt> data structures being pointed at by one entry in the\n<tt>irq_action vector<\/tt> vector.\nWhen a shared interrupt happens, Linux will call all of the <glossary>interrupt<\/glossary>\nhandlers for that source.\nAny device driver that can share interrupts (which should be all PCI device drivers) must be prepared to\nhave its interrupt handler called when there is no interrupt to be serviced.\n<p>\n<h2>Interrupt Handling<\/h2>\n<img decoding=\"async\" src=\"interrupt-handling.gif\">\n<p>\nFigure: Linux Interrupt Handling Data Structures\n<p>\nOne of the principal tasks of Linux&#8217;s interrupt handling subsystem is to\nroute the interrupts to the right pieces of <glossary>interrupt<\/glossary> handling code.\nThis code must understand the interrupt topology of the system.\nIf, for example, the floppy controller interrupts on pin 6\n<a href=\"#tthFtNtAAB\" name=tthFrefAAB><sup>1<\/sup><\/a>\nof the interrupt controller then it must recognize the interrupt as\nfrom the floppy and route it to the floppy device driver&#8217;s interrupt handling code.\nLinux uses a set of pointers to data structures\ncontaining the addresses of the routines that handle the system&#8217;s interrupts.\nThese routines belong to the device drivers for the devices in the system\nand it is the responsibility of each device driver to request the interrupt that it wants\nwhen the driver is initialized.\nFigure&nbsp;<a href=\"#interrupt-data-structures\"\n> 7.2<\/a> shows that\n<tt>irq_action<\/tt> is a vector of pointers to  the <tt>irqaction<\/tt> data\nstructure.\nEach <tt>irqaction<\/tt> data structure contains information about the handler\nfor this interrupt, including the address of the interrupt handling routine.\nAs the number of interrupts and how they are handled varies between architectures and, sometimes, between\nsystems, the Linux <glossary>interrupt<\/glossary> handling code is architecture specific.\nThis means that the size of the <tt>irq_action vector<\/tt> vector varies depending on the\nnumber of interrupt sources that there are.\n<p>\nWhen the <glossary>interrupt<\/glossary> happens, Linux must first determine its source\nby reading the interrupt status <glossary>register<\/glossary> of the system&#8217;s programmable\ninterrupt controllers. It then translates that source into an offset into the <tt>irq_action\nvector<\/tt> vector. So, for example, an <glossary>interrupt<\/glossary> on pin 6\nof the interrupt controller from the floppy controller would\nbe translated into the seventh pointer in the vector of interrupt handlers.\nIf there is not an <glossary>interrupt<\/glossary> handler for the interrupt that occurred then\nthe Linux kernel will log an error, otherwise it will call into the\ninterrupt handling routines for all of the <tt>irqaction<\/tt> data structures for this\ninterrupt source.\n<p>\nWhen the <glossary>device driver<\/glossary>&#8216;s\n<glossary>interrupt<\/glossary> handling routine is called by the\nLinux <glossary>kernel<\/glossary> it\nmust efficiently work out why it was interrupted and respond.\nTo find the cause of the interrupt the device driver would read the status register of\nthe device that interrupted.\nThe device may be reporting an error or that a requested operation has completed.\nFor example the floppy controller may be reporting that it has completed the positioning\nof the floppy&#8217;s read head over the correct sector on the floppy disk.\nOnce the reason for the interrupt has been determined, the device driver may need to\ndo more work. If it does, the Linux <glossary>kernel<\/glossary> has mechanisms that allow it to\npostpone that  work until later.\nThis avoids the CPU spending too much time in interrupt mode.\nSee the <site id=\"262\">section on device drivers<\/site> for more details.\n","protected":false},"excerpt":{"rendered":"<p>Interrupts and Interrupt Handling This chapter looks at how interrupts are handled by the Linux kernel. Whilst the kernel has generic mechanisms and interfaces for handling interrupts, most of the interrupt handling details are architecture specific. Figure 7.1: A Logical &hellip; <a href=\"http:\/\/www.linux-tutorial.info\/?page_id=449\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-449","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/449","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=449"}],"version-history":[{"count":1,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/449\/revisions"}],"predecessor-version":[{"id":591,"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=\/wp\/v2\/pages\/449\/revisions\/591"}],"wp:attachment":[{"href":"http:\/\/www.linux-tutorial.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=449"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}