APIC: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
(Rough import from osfaq)
 
(1st try at cleaning up the APIC converted page)
Line 1: Line 1:
{{Convert}}
{{Convert}}


APIC ("Advanced Programmable Interrupt Controller") is the updated Intel standard for the older [[PIC]]. It is used in multiprocessor systems and is an integral part of all Intel (and compatible) processors from the P6 (Pentium III) and onwards. The APIC is used for sophisticated interrupt redirection, and for sending interrupts between processors. These things weren't possible using the older PIC specification.
== What's the APIC ? ==


== Detection ==
APIC (''Advanced Programmable Interrupt Controller'') is the Intel standard for the "new" PIC. Its used in multiprocessor systems and is an integral part of all Intel (and compatible) processors from the P6 (Pentium III) and onwards.


The Intel APIC specification is used in modern processors, and there's a bit (bit 9) in the [[CPUID]] standard information flags that let you see whether a CPU has an APIC. The APIC itself is used for more up to date interrupt redirection, and for sending interrupts between processors. These things weren't possible using the older PIC specification.
Bit 9 in the [[CPUID]] standard information flags specifies whether a CPU has a built-in local APIC.


== Local APIC and IO-APIC ==
== Local APIC and IO-APIC ==


In APIC-based system, each CPU is made of a ''core'' and a ''local APIC''. The local apic is responsible for handling cpu-specific interrupt configuration. Among other things, it contains the ''Local Vector Table (LVT)'' that translate events such as "internal clock" and other "local" interrupt sources into a interrupt vector (e.g. LocalINT1 pin could be raising an NMI exception by storing "2" in the corresponding entry of the LVT).
In an APIC-based system, each CPU is made of a "core" and a "local APIC". The local APIC is responsible for handling cpu-specific interrupt configuration. Among other things, it contains the ''Local Vector Table (LVT)'' that translates events such as "internal clock" and other "local" interrupt sources into a interrupt vector (e.g. LocalINT1 pin could be raising an NMI exception by storing "2" in the corresponding entry of the LVT).


''information about the local APIC can be found in "system programming guide" of intel processors)''
More information about the local APIC can be found in the "System Programming Guide" of current intel processors.


In addition, the I/O APIC (e.g. intel 82093AA) is part of the chipset and provides multi-processor interrupt management, incorporating both static and dynamic symmetric interrupt distribution across all processors. In systems with multiple I/O subsystems, each subsystem can have its own set of interrupts.
In addition, there is an I/O APIC (e.g. intel 82093AA) that is part of the chipset and provides multi-processor interrupt management, incorporating both static and dynamic symmetric interrupt distribution across all processors. In systems with multiple I/O subsystems, each subsystem can have its own set of interrupts.


Each interrupt pin is individually programmable as either edge or level triggered. The interrupt vector and interrupt steering information can be specified per interrupt. An indirect register accessing scheme optimizes the memory space needed to access the I/O APIC's internal registers. To increase system flexibility when assigning memory space usage, the I/O APIC's two-register memory space is re-locatable, but defaults to 0xFEC00000.
Each interrupt pin is individually programmable as either edge or level triggered. The interrupt vector and interrupt steering information can be specified per interrupt. An indirect register accessing scheme optimizes the memory space needed to access the I/O APIC's internal registers. To increase system flexibility when assigning memory space usage, the I/O APIC's two-register memory space is relocatable, but defaults to 0xFEC00000.


The original I/O APIC specification/datasheet is available from Intel at [http://www.intel.com/design/chipsets/datashts/290566.htm] and an updated version can be found at [http://developer.intel.com/design/chipsets/specupdt/290710.htm].
The Intel standards for the APIC can be found on the Intel site under the category "Multiprocessor Specification" at [http://developer.intel.com/design/pentium/datashts/24201606.pdf].

The Intel Standards for the APIC can be found on the Intel site under the name of Multiprocessor Specification at [http://developer.intel.com/design/pentium/datashts/24201606.pdf].


== Inter-Procesor Interrupts ==
== Inter-Procesor Interrupts ==


Inter-Processor Interrupts (IPIs) are generated by local APIC and can be used as basic signalling for scheduling coordination, multi-processors bootstrapping, etc.
Inter-Processor Interrupts (IPIs) are generated by a local APIC and can be used as basic signalling for scheduling coordination, multi-processor bootstrapping, etc.


== APIC configuration ==
== Local APIC configuration ==


The local APIC is enabled at boot-time and can be disabled by clearing bit 11 of =IA32_APIC_BASE_MSR= (the CPU then receives its interrupts directly from a 8259-compatible PIC, which is usually used prior a reboot) and the I/O APIC can be programmed in legacy mode (so that it reacts as a 8259 device).
The local APIC is enabled at boot-time and can be disabled by clearing bit 11 of the "IA32_APIC_BASE_MSR" (see example below). The CPU then receives its interrupts directly from a 8259-compatible PIC.


the I/O APIC can also be set to legacy mode (so that it emulates an 8259 device).
The local APIC registers are memory-mapped in physical page FEE00xxx (as seen in table 8-1 of intel P4 SPG). Note that there's a ModelSpecificRegister that specifies the actual APIC base.


The local APIC registers are memory-mapped in physical page FEE00xxx (as seen in table 8-1 of intel P4 SPG). Note that there is a MSR that specifies the actual APIC base.
Make sure you enable the APIC, by OR-ing the Spurious Interrupt Register (0x00F0) with 0x100, before you try to configure anything else ;)


<pre>
<verbatim>
#define IA32_APIC_BASE_MSR 0x1B
#define IA32_APIC_BASE_MSR 0x1B
#define IA32_APIC_BASE_MSR_ENABLE 0x800
#define IA32_APIC_BASE_MSR_ENABLE 0x800
Line 75: Line 73:
#endif
#endif
}
}
</verbatim>
</pre>


== IO APIC Configuration ==
== IO APIC Configuration ==


The IO APIC, like the VGA controller and the CMOS, has a two-register address space - an address register at IOAPICBASE+0 and a data register at IOAPICBASE+0x10. All accesses _must_ be done on dword boundaries. Here's some example code that illustrates this:
The IO APIC, like the VGA controller and the CMOS, has a two-register address space - an address register at IOAPICBASE+0 and a data register at
IOAPICBASE+0x10. All accesses _must_ be done on dword boundaries. Here is some example code that illustrates this:


<pre>
<verbatim>
dword cpuReadIoApic(void *ioapicaddr, dword reg)
dword cpuReadIoApic(void *ioapicaddr, dword reg)
{
{
Line 95: Line 94:
ioapic[4] = value;
ioapic[4] = value;
}
}
</verbatim>
</pre>


Note the strange usage of the _volatile_ keyword. It means in this case that the value _pointed to_, not the _pointer_, is volatile. It prevents the compiler, as [Visual C] does, from reordering the memory accesses, which is a Bad Thing.
Note the strange usage of the <u>volatile</u> keyword. It means in this case that the value ''pointed to'', not the ''pointer'', is volatile. This prevents a compiler like [Visual C] from reordering the memory accesses, which is a Bad Thing.


== Important Helpful Hints ==
----

Categories: CollectedKnowledge, HardWareIrq
Make sure you enable the APIC, by OR-ing the Spurious Interrupt Register (0x00F0) with 0x100, before you try to configure anything else ;)

== See Also ==


== Related threads ==
[APIC timer|Forum:8031]
[APIC timer|Forum:8031]
["mapping IO APIC"|Forum:9311]
["mapping IO APIC"|Forum:9311]

== External Links ==

* [http://www.intel.com/design/chipsets/datashts/290566.htm] - original I/O APIC specification/datasheet
* [http://developer.intel.com/design/chipsets/specupdt/290710.htm] - updated I/O APIC specification/datasheet


[[Category:Common Devices]]

Revision as of 06:48, 19 March 2007

Template:Convert

APIC ("Advanced Programmable Interrupt Controller") is the updated Intel standard for the older PIC. It is used in multiprocessor systems and is an integral part of all Intel (and compatible) processors from the P6 (Pentium III) and onwards. The APIC is used for sophisticated interrupt redirection, and for sending interrupts between processors. These things weren't possible using the older PIC specification.

Detection

Bit 9 in the CPUID standard information flags specifies whether a CPU has a built-in local APIC.

Local APIC and IO-APIC

In an APIC-based system, each CPU is made of a "core" and a "local APIC". The local APIC is responsible for handling cpu-specific interrupt configuration. Among other things, it contains the Local Vector Table (LVT) that translates events such as "internal clock" and other "local" interrupt sources into a interrupt vector (e.g. LocalINT1 pin could be raising an NMI exception by storing "2" in the corresponding entry of the LVT).

More information about the local APIC can be found in the "System Programming Guide" of current intel processors.

In addition, there is an I/O APIC (e.g. intel 82093AA) that is part of the chipset and provides multi-processor interrupt management, incorporating both static and dynamic symmetric interrupt distribution across all processors. In systems with multiple I/O subsystems, each subsystem can have its own set of interrupts.

Each interrupt pin is individually programmable as either edge or level triggered. The interrupt vector and interrupt steering information can be specified per interrupt. An indirect register accessing scheme optimizes the memory space needed to access the I/O APIC's internal registers. To increase system flexibility when assigning memory space usage, the I/O APIC's two-register memory space is relocatable, but defaults to 0xFEC00000.

The Intel standards for the APIC can be found on the Intel site under the category "Multiprocessor Specification" at [1].

Inter-Procesor Interrupts

Inter-Processor Interrupts (IPIs) are generated by a local APIC and can be used as basic signalling for scheduling coordination, multi-processor bootstrapping, etc.

Local APIC configuration

The local APIC is enabled at boot-time and can be disabled by clearing bit 11 of the "IA32_APIC_BASE_MSR" (see example below). The CPU then receives its interrupts directly from a 8259-compatible PIC.

the I/O APIC can also be set to legacy mode (so that it emulates an 8259 device).

The local APIC registers are memory-mapped in physical page FEE00xxx (as seen in table 8-1 of intel P4 SPG). Note that there is a MSR that specifies the actual APIC base.

#define IA32_APIC_BASE_MSR 0x1B
#define IA32_APIC_BASE_MSR_ENABLE 0x800

/** returns a 'true' value if the CPU supports APIC
 *  and if the local APIC hasn't been disabled in MSRs
 *  note that this requires CPUID to be supported.
 */
boolean cpuHasAPIC()
{
   dword a,d;
   cpuid(1,&a,&d);
   return d&CPUID_FLAG_APIC;
}

/** defines the physical address for local APIC registers
 */
void cpuSetAPICBase(phys_addr apic)
{
   dword a=(apic&0xfffff000) | IA32_APIC_BASE_MSR_ENABLE;
#ifdef __PHYSICAL_MEMORY_EXTENSION__
   dword d=(apic>>32) & 0x0f;
#else
   dword d=0;
#endif

   cpuSetMSR(IA32_APIC_BASE_MSR, a,d);
}

/** determines the physical address of the APIC registers page
 *  make sure you map it to virtual memory ;)
 */
phys_addr cpuGetAPICBase()
{
   dword a,d;
   cpuGetMSR(IA32_APIC_BASE_MSR,&a,&d);
#ifdef __PHYSICAL_MEMORY_EXTENSION__
   return (a&0xfffff000)|((d&0x0f)<<32);
#else
   return (a&0xfffff000);
#endif
}

IO APIC Configuration

The IO APIC, like the VGA controller and the CMOS, has a two-register address space - an address register at IOAPICBASE+0 and a data register at IOAPICBASE+0x10. All accesses _must_ be done on dword boundaries. Here is some example code that illustrates this:

dword cpuReadIoApic(void *ioapicaddr, dword reg)
{
   dword * volatile ioapic = (dword*)ioapicaddr;
   ioapic[0] = reg;
   return ioapic[4];
}

void cpuWriteIoApic(void *ioapicaddr, dword reg, dword value)
{
   dword * volatile ioapic = (dword*)ioapicaddr;
   ioapic[0] = reg;
   ioapic[4] = value;
}

Note the strange usage of the volatile keyword. It means in this case that the value pointed to, not the pointer, is volatile. This prevents a compiler like [Visual C] from reordering the memory accesses, which is a Bad Thing.

Important Helpful Hints

Make sure you enable the APIC, by OR-ing the Spurious Interrupt Register (0x00F0) with 0x100, before you try to configure anything else ;)

See Also

[APIC timer|Forum:8031] ["mapping IO APIC"|Forum:9311]

External Links

  • [2] - original I/O APIC specification/datasheet
  • [3] - updated I/O APIC specification/datasheet