Intel从Pentium开始引入APIC(Advanced Programmable Interrupt Controller),以适应MP(Multiple processor)环境。
Local APIC,在处理器内部
I/O APIC 在PCI-to-ISA bridge(PCI-to-LPC bridge)的LPC控制器内
每个逻辑处理器(logical processor)有自己的local APIC,每个local APIC有一组APIC寄存器,用来控制local和external中断的产生、发送和接收等,也产生IPI(处理器间中断消息)
APIC,xAPIC中local APIC寄存器以内存映射形式映射到物理地址空间。x2APIC则是映射到MSR寄存器组。
简单浏览了下Intel手册中APIC的介绍,不是很好理解,决定一点点测试下,然后再尝试真正使用它来代替8259A做中断控制器。
1.test
1)版本
CPUID.01:EDX[9]表示是否支持APIC
CPUID.01:ECX[21]表示是否支持x2APIC
void local_apic_t::check()
{
uint32 edx = 0, ecx = 0;
__asm__ volatile("cpuid" : "=d" (edx), "=c" (ecx) : "a" (0x1) : "memory", "cc");
console()->kprintf(YELLOW, "**************** check apic **********************\n");
console()->kprintf(YELLOW, "local_apic check, ecx: %x, edx: %x\n", ecx, edx);
console()->kprintf(YELLOW, "support APIC: %s\n", (edx & (1 << 9)) ? "YES" : "NO");
console()->kprintf(YELLOW, "support x2APIC: %s\n", (ecx & (1 << 21)) ? "YES" : "NO");
}
2)global disable
Using the APIC global enable/disable flag in the IA32_APIC_BASE MSR (MSR address 1BH)
#define rdmsr(msr,val1,val2) \
__asm__ __volatile__("rdmsr" \
: "=a" (val1), "=d" (val2) \
: "c" (msr))
#define wrmsr(msr,val1,val2) \
__asm__ __volatile__("wrmsr" \
: /* no outputs */ \
: "c" (msr), "a" (val1), "d" (val2))
linux的读写msr的代码。
void local_apic_t::global_disable()
{
uint32 l, h;
rdmsr(MSR_IA32_APICBASE, l, h);
l &= ~MSR_IA32_APICBASE_ENABLE;
wrmsr(MSR_IA32_APICBASE, l, h);
}
3)Local APIC Register Address Map
void local_apic_t::check()
{
uint32 edx = 0, ecx = 0;
__asm__ volatile("cpuid" : "=d" (edx), "=c" (ecx) : "a" (0x1) : "memory",