<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.friendos.dev/index.php?action=history&amp;feed=atom&amp;title=APIC</id>
	<title>APIC - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.friendos.dev/index.php?action=history&amp;feed=atom&amp;title=APIC"/>
	<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=APIC&amp;action=history"/>
	<updated>2026-05-12T03:13:40Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.38.4</generator>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=APIC&amp;diff=112&amp;oldid=prev</id>
		<title>TheCatgirls: TheCatgirls moved page Apic to APIC: Uppercase :)</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=APIC&amp;diff=112&amp;oldid=prev"/>
		<updated>2024-12-21T07:00:41Z</updated>

		<summary type="html">&lt;p&gt;TheCatgirls moved page &lt;a href=&quot;/index.php/Apic&quot; class=&quot;mw-redirect&quot; title=&quot;Apic&quot;&gt;Apic&lt;/a&gt; to &lt;a href=&quot;/index.php/APIC&quot; title=&quot;APIC&quot;&gt;APIC&lt;/a&gt;: Uppercase :)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 07:00, 21 December 2024&lt;/td&gt;
				&lt;/tr&gt;
&lt;!-- diff cache key friendos:diff::1.12:old-111:rev-112 --&gt;
&lt;/table&gt;</summary>
		<author><name>TheCatgirls</name></author>
	</entry>
	<entry>
		<id>https://wiki.friendos.dev/index.php?title=APIC&amp;diff=111&amp;oldid=prev</id>
		<title>Caitcatto: Added Starter for APIC page.</title>
		<link rel="alternate" type="text/html" href="https://wiki.friendos.dev/index.php?title=APIC&amp;diff=111&amp;oldid=prev"/>
		<updated>2024-12-19T20:40:15Z</updated>

		<summary type="html">&lt;p&gt;Added Starter for APIC page.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==LAPIC and IOAPIC==&lt;br /&gt;
&lt;br /&gt;
The Advanced Programmable Interrupter Controller(APIC) is a interrupt controller designed to replace the 8529 Intel programmable interrupt controller(PIC) that had been standard up until this point. The reason for this replacement was two fold. Multiprocessor systems where becoming more common and the old PIC was unable to control which CPU cores would be sent interrupts, Along with the APIC being capable of sending Inter-Processor-Interrupts(IPI).&lt;br /&gt;
&lt;br /&gt;
This allowed for OS's to have more fine grained control over their interrupts and allowed for better hardware delegation of interrupts allowing certain CPU cores to handle certain interrupts. The design of the APIC is simple really it's split into two pieces the Local APIC(LAPIC) and the IOAPIC. With each LAPIC and IOAPIC having an ID number on their dedicated APIC bus.&lt;br /&gt;
&lt;br /&gt;
The Local APIC is a CPU core local interrupt controller, each CPU core has it's own LAPIC, these can handle their own timer interrupts and external Hardware Interrupts that are sent via the IOAPIC. The IOAPIC on the other hand is connected to external devices([[PIT]],[[HPET]],[[PS/2]] Controller, etc...) and through the use of redirection tables it can be programmed with a LAPIC ID in each Interrupt redirection table entry. This ID controls which LAPIC and thus which core will service this hardware interrupt. It is quite common for a system to have one IOAPIC however plenty of systems may two or more IOAPICs you should parse the MP tables or the [[ACPI]] [[MADT]] table to ensure all IOAPICs are found.&lt;br /&gt;
&lt;br /&gt;
===Please Note===&lt;br /&gt;
The MP specification is an old spec and though it will contain the information needed for the IOAPIC and LAPIC. It may not be present on newer systems and the ACPI tables should be preferred over the MP spec wherever possible.&lt;br /&gt;
&lt;br /&gt;
==LAPIC==&lt;br /&gt;
Support for the local APIC can be queried using two different methods. One would be using CPUID &amp;lt;code&amp;gt;EDX=0x00000001&amp;lt;/code&amp;gt;. Or you could parse the [[MP Tables]] or the [[ACPI]] [[MADT]] table(Which you would likely want to do anyway for SMP). You could also check the APIC Base MSR and assume if those exist that the LAPIC is present at the &amp;quot;default&amp;quot; physical address of &amp;lt;code&amp;gt;0xfee00000&amp;lt;/code&amp;gt;. However the best way would be to check the CPUID, then parse the [[MP Tables|MP]] or the ACPI [[MADT]] table to determine both the if APIC is supported and get the LAPIC Physical address from the [[MP Tables|MP]]/[[MADT]] Table. If you wish to double check this base address you can also check the APIC Base MSR(`0x1b`). &lt;br /&gt;
&lt;br /&gt;
===Register Layout===&lt;br /&gt;
&lt;br /&gt;
TODO:&lt;br /&gt;
&lt;br /&gt;
==IOAPIC==&lt;br /&gt;
The IOAPIC can be queried in multiple different ways one is to assume that if the LAPIC exists that at least one IOAPIC exists at the &amp;quot;default&amp;quot; physical address of &amp;lt;code&amp;gt;0xfec00000&amp;lt;/code&amp;gt;. However again this isn't ideal and you should attempt to parse either the [[MP Tables]] or the [[ACPI]] [[MADT]] Tables. To Ensure you have the correct physical addresses and have found all IOAPICs in this system.&lt;br /&gt;
&lt;br /&gt;
===Register Layout===&lt;br /&gt;
todo:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Programming LAPIC/IOAPIC ==&lt;br /&gt;
When Programming these devices their memory addresses should always be marked as non-cacheable to ensure proper operation of the devices as caching them could produce strange and undesired results due to cached values being read rather than the actual true values of the MMIO registers. In the below code we are also going to assume that everything is at it's &amp;quot;default&amp;quot; standard physical address in memory and that if paging is active it's just a simple identity map paging i.e. Virtual Address = Physical Address. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In your kernel you are going to want to parse ACPI structures and map these physical addresses in a way that makes sense for your [[VMM]].&lt;br /&gt;
&lt;br /&gt;
=== IOAPIC: ===&lt;br /&gt;
Below is an example of programming the IOAPIC to route GSI 2 typically ISA IRQ 0(PIT Timer) to CPU 0 with the interrupt vector set to &amp;lt;code&amp;gt;0x20&amp;lt;/code&amp;gt; this is because the IOAPIC operates on register select and window model of programming meaning that &amp;lt;code&amp;gt;base + 0&amp;lt;/code&amp;gt; = the register to select. and &amp;lt;code&amp;gt;base + 0x10&amp;lt;/code&amp;gt; = the selected register. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Each Interrupt redirection entry is split into two 32bit registers. The lower bits contains data such as which IDT vector will be called for this interrupt, polarity, delivery mode, edge or level triggered, masked, etc... &lt;br /&gt;
&lt;br /&gt;
While the upper 32bits contain the the LAPIC ID that this interrupt will be sent to. Depending on the setting of bit 11 of the lower 32bit. See &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void ioapic_init() {&lt;br /&gt;
    volatile uint32_t *ioapic = (uint32_t*)0xfec00000;&lt;br /&gt;
    /*Timer Interrupt for QEMU*/&lt;br /&gt;
    base[0] = 0x14; /*GSI Interrupt 2 Most commonly PIT/HPET timer*/&lt;br /&gt;
    base[4] = 0x20; /*Interrupt Vector i.e. IDT vector 0x20 will be called for this*/&lt;br /&gt;
    base[0] = 0x14; /*GSI Interrupt 2 upper 32bit*/&lt;br /&gt;
    base[4] = 0x00; &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
[https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf IOAPIC datasheet from MIT.edu]&lt;br /&gt;
&lt;br /&gt;
[https://uefi.org/sites/default/files/resources/ACPI%20Spec%206%205%20Aug29.pdf ACPI Spec]&lt;br /&gt;
&lt;br /&gt;
[https://pdos.csail.mit.edu/6.828/2018/readings/ia32/MPspec.pdf MPspec Datasheet from MIT.edu]&lt;br /&gt;
&lt;br /&gt;
[https://cdrdv2.intel.com/v1/dl/getContent/671200 Intel SDM Full(Volume 3 chapter 12 for APIC Documentation)]&lt;br /&gt;
&lt;br /&gt;
[https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/40332.pdf AMD SDM(Volume 2 chapter 16 for APIC Documentation)]&lt;/div&gt;</summary>
		<author><name>Caitcatto</name></author>
	</entry>
</feed>