PageSourceSearch

https://0xc0ffee.netlify.app/assets/25-interrupt-controller.html-DVN3VObb.js

js 0xc0ffee.netlify.app collected 2026-10-03 10:23:53 UTC 36,928 bytes, 148 lines download raw bytes

1import{_ as n,c as a,e,o as t}from"./app-CjUkjRdW.js";const i={};function p(l,s){return t(),a("div",null,s[0]||(s[0]=[e(`<h1 id="interrupt-controller" tabindex="-1"><a class="header-anchor" href="#interrupt-controller"><span>Interrupt Controller</span></a></h1><p>The legacy x86 architecture featured a single interrupt controller, the 8259A Programmable Interrupt Controller (PIC), responsible for managing hardware interrupts. The PIC is a simple device that is limited to 8 interrupts per controller (15 interrupts total when cascaded with another PIC, as one interrupt line is used for the cascade), and is limited in terms of interrupt priority, routing flexibility, and multiprocessor support.</p><p>The PIC is now considered obsolete, and modern x86 systems use the Advanced Programmable Interrupt Controller (APIC) architecture. The APIC architecture consists of two main components: the I/O APIC and the Local APIC. The I/O APIC is responsible for managing interrupts from external devices (usually there is only one in the system), while the Local APIC is integrated into each CPU core and is responsible for managing interrupts delivered to the CPU core (whether from the I/O APIC or from the Local APIC of other CPU cores), as well as interrupts from internal sources such as the Local APIC timer. For this reason, we will focus on the Local APIC in this section.</p><h2 id="local-apic" tabindex="-1"><a class="header-anchor" href="#local-apic"><span>Local APIC</span></a></h2><p>The Local APIC is responsible for managing interrupts delivered to its associated core. The interrupts it delivers can originate from internal sources, such as its timer, thermal sensors, and performance monitoring counters, or from external sources, such as the I/O APIC and Inter-Processor Interrupts (IPIs).</p><p>The following is a simplified diagram of the relevant components of the Local APIC (there are more components, but we won&#39;t need them for now):</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">┌─────────────────────────────┐</span>
2<span class="line">│      Version Register       │</span>
3<span class="line">└─────────────────────────────┘</span>
4<span class="line"></span>
5<span class="line">┌──────────────────────────────┐ ◄──┐</span>
6<span class="line">│    Current Count Register    │    │</span>
7<span class="line">├──────────────────────────────┤    │</span>
8<span class="line">│    Initial Count Register    │    ├── Timer Registers</span>
9<span class="line">├──────────────────────────────┤    │</span>
10<span class="line">│     Divide Configuration     │    │</span>
11<span class="line">└──────────────────────────────┘ ◄──┘</span>
12<span class="line"></span>
13<span class="line">┌──────────────────────────────┐ ◄──┐</span>
14<span class="line">│            Timer             │    │</span>
15<span class="line">├──────────────────────────────┤    │</span>
16<span class="line">│          Local INT0          │    │</span>
17<span class="line">├──────────────────────────────┤    │</span>
18<span class="line">│          Local INT1          │    │</span>
19<span class="line">├──────────────────────────────┤    ├── Local Vector Table (LVT)</span>
20<span class="line">│  Perf. Monitoring Counters   │    │</span>
21<span class="line">├──────────────────────────────┤    │</span>
22<span class="line">│        Thermal Sensors       │    │</span>
23<span class="line">├──────────────────────────────┤    │</span>
24<span class="line">│        Error Register        │    │</span>
25<span class="line">└──────────────────────────────┘ ◄──┘</span>
26<span class="line"></span>
27<span class="line">┌──────────────────────────────┐</span>
28<span class="line">┆       Other registers...     ┆</span>
29<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The Local APIC is memory-mapped, typically at physical address <code>0xFEE00000</code>; the actual address should be read from the <code>IA32_APIC_BASE</code>
29 MSR. Although the address is the same for all cores, they operate independently and can be programmed separately. Here&#39;s a diagram of this MSR:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">                                IA32_APIC_BASE MSR</span>
30<span class="line"> </span>
31<span class="line"> 63             MAX_PHYS_ADDR                          12 11 10  9  8 7         0</span>
32<span class="line">┌────────────────────────────┬───────────────────────────┬──┬─────┬──┬───────────┐</span>
33<span class="line">│░░░░░░░░░░░░░░░░░░░░░░░░░░░░│         APIC Base         │  │░░░░░│  │░░░░░░░░░░░│</span>
34<span class="line">└────────────────────────────┴───────────────────────────┴──┴─────┴──┴───────────┘</span>
35<span class="line">                                           ▲               ▲        ▲</span>
36<span class="line">              Physical base address ───────┘               │        │</span>
37<span class="line">         APIC global enable/disable ───────────────────────┘        │</span>
38<span class="line">             BSP - Processor is BSP ────────────────────────────────┘</span>
39<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The APIC is programmed by writing to its registers, which are 32 bits wide and located at fixed offsets from the base address. The registers occupy a 4KB page of physical memory address space, from <code>0xFEE00000</code> to <code>0xFEE00FFF</code>, with each register aligned on a 16-byte boundary.</p><p>Since the base address we get from the <code>IA32_APIC_BASE</code> MSR is a physical address, we can&#39;t use it directly; we need to map a page of virtual memory to it first, and then use that virtual memory region to access the APIC registers. Also note this description from the Intel manual:</p><blockquote><p><strong>APIC Base field, bits 12 through 35</strong>: Specifies the base address of the APIC registers. This 24-bit value is extended by 12 bits at the low end to form the base address. This automatically aligns the address on a 4-KByte boundary.</p></blockquote><p>So we&#39;ll need to shift the base address left by 12 bits to get the physical address of the APIC. Since the address is already aligned to a page boundary, we can use it directly when mapping it to virtual memory.</p><p>Let&#39;s start by creating a new module <code>lapic.nim</code> and defining a type for the <code>IA32_APIC_BASE</code> MSR so that we can read it and get the physical address of the Local APIC.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/lapic.nim</span></span>
40<span class="line"></span>
41<span class="line"><span class="token keyword">type</span></span>
42<span class="line">  IA32ApicBaseMsr <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
43<span class="line">    reserved1   <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">8.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint64</span>
44<span class="line">
44    isBsp       <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint64  <span class="token comment"># Is Bootstrap Processor?</span></span>
45<span class="line">    reserved2   <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">2.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint64</span>
46<span class="line">    enabled     <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint64  <span class="token comment"># APIC Enabled?</span></span>
47<span class="line">    baseAddress <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">24.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint64  <span class="token comment"># Physical Base Address (bits 12-35)</span></span>
48<span class="line">    reserved3   <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">28.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint64</span>
49<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let&#39;s import our <code>vmm</code> module so that we can map the APIC region, and let&#39;s define a proc to initialize the base virtual address of the APIC.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token keyword">import</span> vmm</span>
50<span class="line"></span>
51<span class="line"><span class="token keyword">var</span></span>
52<span class="line">  apicBaseAddress<span class="token operator">:</span> uint64</span>
53<span class="line"></span>
54<span class="line"><span class="token keyword">proc</span> <span class="token function">initBaseAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span></span>
55<span class="line">  <span class="token keyword">let</span> apicBaseMsr <span class="token operator">=</span> <span class="token function">cast[IA32ApicBaseMsr]</span><span class="token punctuation">(</span><span class="token function">readMSR</span><span class="token punctuation">(</span>IA32_APIC_BASE<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
56<span class="line">  <span class="token keyword">let</span> apicPhysAddr <span class="token operator">=</span> <span class="token punctuation">(</span>apicBaseMsr<span class="token operator">.</span>baseAddress <span class="token operator">shl</span> <span class="token number">12</span><span class="token punctuation">)</span><span class="token operator">.</span>PhysAddr</span>
57<span class="line">  <span class="token comment"># by definition, apicPhysAddr is aligned to a page boundary, so we map it directly</span></span>
58<span class="line">  <span class="token keyword">let</span> apicVMRegion <span class="token operator">=</span> <span class="token function">vmalloc</span><span class="token punctuation">(</span>kspace<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
59<span class="line">  <span class="token function">mapRegion</span><span class="token punctuation">(</span></span>
60<span class="line">    pml4 <span class="token operator">=</span> kpml4<span class="token punctuation">,</span></span>
61<span class="line">
61    virtAddr <span class="token operator">=</span> apicVMRegion<span class="token operator">.</span>start<span class="token punctuation">,</span></span>
62<span class="line">    physAddr <span class="token operator">=</span> apicPhysAddr<span class="token punctuation">,</span></span>
63<span class="line">    pageCount <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span></span>
64<span class="line">    pageAccess <span class="token operator">=</span> paReadWrite<span class="token punctuation">,</span></span>
65<span class="line">    pageMode <span class="token operator">=</span> pmSupervisor<span class="token punctuation">,</span></span>
66<span class="line">    noExec <span class="token operator">=</span> true</span>
67<span class="line">  <span class="token punctuation">)</span></span>
68<span class="line">  apicBaseAddress <span class="token operator">=</span> apicVMRegion<span class="token operator">.</span>start<span class="token operator">.</span>uint64</span>
69<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The APIC has many registers at different offsets from the base address, each register is 32 bits wide. Let&#39;s define the offsets of those registers. The registers we are interested in are pointed out with comments, as we&#39;ll use them later to initialize the APIC and program the timer. And while we&#39;re at it, let&#39;s also add a couple of procs to read from and write to the APIC registers.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token keyword">type</span></span>
70<span class="line">  LapicOffset <span class="token operator">=</span> <span class="token keyword">enum</span></span>
71<span class="line">    LapicId            <span class="token operator">=</span> <span class="token number">0x020</span></span>
72<span class="line">    LapicVersion       <span class="token operator">=</span> <span class="token number">0x030</span></span>
73<span class="line">    TaskPriority       <span class="token operator">=</span> <span class="token number">0x080</span></span>
74<span class="line">    ProcessorPriority  <span class="token operator">=</span> <span class="token number">0x0a0</span></span>
75<span class="line">    Eoi                <span class="token operator">=</span> <span class="token number">0x0b0</span> <span class="token comment"># ◄────── End Of Interrupt Register</span></span>
76<span class="line">    LogicalDestination <span class="token operator">=</span> <span class="token number">0x0d0</span></span>
77<span class="line">    DestinationFormat  <span class="token operator">=</span> <span class="token number">0x0e0</span></span>
78<span class="line">    SpuriousInterrupt  <span class="token operator">=</span> <span class="token number">0x0f0</span> <span class="token comment"># ◄────── Spurious Interrupt Vector Register</span></span>
79<span class="line">    InService          <span class="token operator">=</span> <span class="token number">0x100</span></span>
80<span class="line">    TriggerMode        <span class="token operator">=</span> <span class="token number">0x180</span></span>
81<span class="line">    InterruptRequest   <span class="token operator">=</span> <span class="token number">0x200</span></span>
82<span class="line">
82    ErrorStatus        <span class="token operator">=</span> <span class="token number">0x280</span></span>
83<span class="line">    LvtCmci            <span class="token operator">=</span> <span class="token number">0x2f0</span></span>
84<span class="line">    InterruptCommandLo <span class="token operator">=</span> <span class="token number">0x300</span></span>
85<span class="line">    InterruptCommandHi <span class="token operator">=</span> <span class="token number">0x310</span></span>
86<span class="line">    LvtTimer           <span class="token operator">=</span> <span class="token number">0x320</span> <span class="token comment"># ◄────── LVT Timer Register</span></span>
87<span class="line">    LvtThermalSensor   <span class="token operator">=</span> <span class="token number">0x330</span></span>
88<span class="line">    LvtPerfMonCounters <span class="token operator">=</span> <span class="token number">0x340</span></span>
89<span class="line">    LvtLint0           <span class="token operator">=</span> <span class="token number">0x350</span></span>
90<span class="line">    LvtLint1           <span class="token operator">=</span> <span class="token number">0x360</span></span>
91<span class="line">    LvtError           <span class="token operator">=</span> <span class="token number">0x370</span></span>
92<span class="line">    TimerInitialCount  <span class="token operator">=</span> <span class="token number">0x380</span>  <span class="token comment"># ◄──┐</span></span>
93<span class="line">    TimerCurrentCount  <span class="token operator">=</span> <span class="token number">0x390</span>  <span class="token comment">#    ├── Timer Config Registers</span></span>
94<span class="line">    TimerDivideConfig  <span class="token operator">=</span> <span class="token number">0x3e0</span>  <span class="token comment"># ◄──┘</span></span>
95<span class="line"></span>
96<span class="line"><span class="token keyword">proc</span> <span class="token function">readRegister</span><span class="token punctuation">(</span>offset<span class="token operator">:</span> LapicOffset<span class="token punctuation">)</span><span class="token operator">:</span> uint32 <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
97<span class="line">  result <span class="token operator">=</span> <span class="token function">cast[ptr uint32]</span><span class="token punctuation">(</span>apicBaseAddress <span class="token operator">+</span> offset<span class="token operator">.</span>uint16<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span></span>
98<span class="line"></span>
99<span class="line"><span class="token keyword">proc</span> <span class="token function">writeRegister</span><span class="token punctuation">(</span>offset<span class="token operator">:</span> LapicOffset<span class="token punctuation">,</span> value<span class="token operator">:</span> uint32<span class="token punctuation">)</span> <span class="token punctuation">{.</span>inline<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
100<span class="line">  <span class="token function">cast[ptr uint32]</span><span class="token punctuation">(</span>apicBaseAddress <span class="token operator">+</span> offset<span class="token operator">.</span>uint16<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> value</span>
101<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="initializing-the-apic" tabindex="-1"><a class="header-anchor" href="#initializing-the-apic"><span>Initializing the APIC</span></a></h2><p>There are two places that control whether the APIC is enabled or not: the <code>IA32_APIC_BASE</code> MSR APIC global enable/disable flag (bit 11), and the APIC software enable/disable flag in the spurious-interrupt vector register.</p><div class="hint-container note"><p class="hint-container-title">Note</p><p>Spurious interrupts can occur in rare situations when the processor receives an interrupt at a lower priority than the current interrupt being processed, causing it to become pending. While the ISR for the current interrupt is executing, it may mask the pending interrupt. The APIC will then deliver a spurious interrupt to the processor, which will cause the processor to execute the ISR configured for spurious interrupts. In this case the spurious interrupt handler should just ignore the interrupt and return without an EOI.</p></div><p>The APIC global enable/disable flag is enabled by default, so we don&#39;t need to worry about it. This is not the case for the enable/disable bit in the spurious-interrupt vector register, so we need to set it to enable the APIC. Let&#39;s first look at a diagram of the spurious-interrupt vector register.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">                       Spurious Interrupt Vector Register</span>
102<span class="line"> </span>
103<span class="line"> 31                                               12 11 10  9  8 7             0</span>
104<span class="line">┌────────────────────────────────────────────────┬──┬─────┬──┬──┬───────────────┐</span>
105<span class="line">│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│  │░░░░░│  │  │               │</span>
106<span class="line">└────────────────────────────────────────────────┴──┴─────┴──┴──┴───────────────┘</span>
107<span class="line">                                                  ▲         ▲  ▲       ▲</span>
108<span class="line">                 EOI Broadcast Suppression ───────┘         │  │       │</span>
109<span class="line">                  Focus Processor Checking ─────────────────┘  │       │</span>
110<span class="line">              APIC Software Enable/Disable ────────────────────┘       │</span>
111<span class="line">                 Spurious Interrupt Vector ────────────────────────────┘</span>
112<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The bits we are interested in are the APIC software enable/disable bit (bit 8) and the spurious interrupt vector (bits 7-0). The vector is set to <code>0xFF</code> by the CPU by default, which we will keep as is, and will add a new interrupt handler for. Let&#39;s create a type for the spurious interrupt vector register so we can easily access its fields.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token keyword">type</span></span>
113<span class="line">  SpuriousInterruptVectorRegister <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
114<span class="line">
114    vector                  <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">8.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint32</span>
115<span class="line">    apicEnabled             <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint32</span>
116<span class="line">    focusProcessorChecking  <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint32</span>
117<span class="line">    reserved0               <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">2.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint32</span>
118<span class="line">    eoiBroadcastSuppression <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span>  <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint32</span>
119<span class="line">    reserved1               <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">19.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint32</span>
120<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let&#39;s create the spurious interrupt handler, which ignores those interrupts.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token keyword">import</span> idt</span>
121<span class="line"><span class="token operator">...</span></span>
122<span class="line"></span>
123<span class="line"><span class="token keyword">proc</span> <span class="token function">spuriousInterruptHandler<span class="token operator">*</span></span><span class="token punctuation">(</span>frame<span class="token operator">:</span> <span class="token keyword">ptr</span> InterruptFrame<span class="token punctuation">)</span></span>
124<span class="line">  <span class="token punctuation">{.</span>cdecl<span class="token punctuation">,</span> codegenDecl<span class="token operator">:</span> <span class="token string">&quot;__attribute__ ((interrupt)) $# $#$#&quot;</span><span class="token punctuation">.}</span> <span class="token operator">=</span></span>
125<span class="line">  <span class="token comment"># Ignore spurious interrupts; do not send an EOI</span></span>
126<span class="line">  <span class="token keyword">return</span></span>
127<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Now let&#39;s create a proc to initialize the APIC. This proc will first call <code>initBaseAddress</code> to initialize the base address of the APIC, write the spurious interrupt vector register to enable the APIC, and finally install the spurious interrupt handler in the IDT.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token keyword">proc</span> <span class="token function">lapicInit<span class="token operator">*</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span></span>
128<span class="line">  <span class="token function">initBaseAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
129<span class="line">  <span class="token comment"># enable APIC</span></span>
130<span class="line">  <span class="token keyword">let</span> sivr <span class="token operator">=</span> <span class="token function">SpuriousInterruptVectorRegister</span><span class="token punctuation">(</span>vector<span class="token operator">:</span> <span class="token number">0xff</span><span class="token punctuation">,</span> apicEnabled<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">)</span></span>
131<span class="line">  <span class="token function">writeRegister</span><span class="token punctuation">(</span>LapicOffset<span class="token operator">.</span>SpuriousInterrupt<span class="token punctuation">,</span> <span class="token function">cast[uint32]</span><span class="token punctuation">(</span>sivr<span class="token punctuation">)</span><span class="token punctuation">)</span></span>
132<span class="line">  <span class="token comment"># install spurious interrupt handler</span></span>
133<span class="line">  <span class="token function">installHandler</span><span class="token punctuation">(</span><span class="token number">0xff</span><span class="token punctuation">,</span> spuriousInterruptHandler<span class="token punctuation">)</span></span>
134<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Finally, we need to call <code>lapicInit</code> from the kernel&#39;s <code>main</code> proc to initialize the APIC.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span>
135<span class="line"></span>
136<span class="line highlighted"><span class="token keyword">
136import</span> lapic</span>
137<span class="line"><span class="token operator">...</span></span>
138<span class="line"></span>
139<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token operator">=</span></span>
140<span class="line">  <span class="token operator">...</span></span>
141<span class="line"></span>
142<span class="line">  logger<span class="token operator">.</span>info <span class="token string">&quot;init idt&quot;</span></span>
143<span class="line">  <span class="token function">idtInit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
144<span class="line"></span>
145<span class="line highlighted">  logger<span class="token operator">.</span>info <span class="token string">&quot;init lapic&quot;</span></span>
146<span class="line highlighted">  <span class="token function">lapicInit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
147<span class="line">  <span class="token operator">...</span></span>
148<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The Local APIC should now be initialized and ready to receive interrupts. In the next section, we&#39;ll look at how to program the Local APIC timer to generate periodic interrupts.</p>`,33)]))}const o=n(i,[["render",p],["__file","25-interrupt-controller.html.vue"]]),c=JSON.parse('{"path":"/osdev/25-interrupt-controller.html","title":"Interrupt Controller","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Local APIC","slug":"local-apic","link":"#local-apic","children":[]},{"level":2,"title":"Initializing the APIC","slug":"initializing-the-apic","link":"#initializing-the-apic","children":[]}],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/25-interrupt-controller.md","excerpt":"\\n<p>The legacy x86 architecture featured a single interrupt controller, the 8259A Programmable\\nInterrupt Controller (PIC), responsible for managing hardware interrupts. The PIC is a\\nsimple device that is limited to 8 interrupts per controller (15 interrupts total when\\ncascaded with another PIC, as one interrupt line is used for the cascade), and is limited\\nin terms of interrupt priority, routing flexibility, and multiprocessor support.</p>"}');export{o as comp,c as data};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.