参考资料:
[url]http://www.linuxlaptop.cn/index.php/archives/150[/url]
[url]http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/index.html[/url]
《Windows Internal》
    参考了以上资料。
   
    中断控制器分为IO APIC和本地APIC。其中IO APIC为一个,本地APIC各个CPU各一个,每个本地APIC级联到IO APIC上,并且还有两个引脚直接和一个8259A等价的PIC连接(向下兼容)。IO APIC连接到总线上。
    中断发生时,IO APIC在连接总线的引脚上得到中断号IRQ,然后IO APIC通过内部的重定向表找到中断向量,其中还经过了选择CPU的过程,因为重定向表中有CPU亲和力的信息。《Windows Internal》中管这个叫做中断转送算法,而且算法可以由软件(主要是Hal)作出选择。然后利用中断向量在IDT中找到中断处理程序ISR。中断就算是处理完成了。
    至于IRQL是另一回事。在每个CPU的本地APIC上有一个TPR寄存器,用来处理优先级的。
以下下为引用:
    在HAL里虽然HalBeginSystemInterrupt仍然是IRQL机制的发动引擎,但是因为有APIC的支持,它和其它共同实现 IRQL的函数要比PIC HAL里对应的函数功能简单得多。HalBeginSystemInterrupt通过用IRQL做索引在HalpIRQLtoTPR数组中获取该 IRQL对应的任务优先级,用该优先级设置任务优先级寄存器TPR,并把TPR中原先的任务优先级/16做为索引在HalpVectorToIRQL数组中获取对应的原先的IRQL然后返回。若IRQL是从低于DISPATCH_LEVEL提升到高于DISPATCH_LEVEL,还需要设置KPCR+ 0x95(0xffdff095)为DISPATCH_LEVEL(0x2),表示是从DISPATCH_LEVEL以下的级别提升IRQL。 HalEndSystemInterrupt向本地APIC的EOI寄存发送0,表示中断结束,可以接收新中断。并还要判断要降到的IRQL是否小于 DISPATCH_LEVEL,若小于则进一步判断KPCR+0x96(0xffdff096)是否置位,若置位则表示有DPC中断在等待(在IRQL高于DISPATCH_LEVEL被引发,然后等待直到IRQL降到低于DISPATCH_LEVEL),则将KPCR+0x95和KPCR+0x96清0 后调用KiDispatchInterrupt响应DPC软中断。否则做的工作就是和HalBeginSystemInterrupt一样的过程:把要降到的IRQL转换成任务优先级设置TRP,并把久的任务优先级转成IRQL返回。KfRaiseIrql、KfLowerIrql之类的函数也是这么一回事,把当前IRQL转成任务优先级修改TPR,并把原先TPR的值转成原先的IRQL并返回。而现在软中断的产生也有了APIC支持,APIC通过产生一个发向自己的处理器间中断,就可以产生一个软中断,因为可以指定该中断的向量,所以软中断就可以区分优先级别,如APC_LEVEL、 DISPATCH_LEVEL。产生软中断的函数一样还是HalRequestSoftwareInterrupt,该函数会先判断KPCR+0x95是否和要产生的软中断IRQL一样,若是的话则置位KPCR+0x96并返回,表示现在IRQL大于DISPATCH_LEVEL所以不处理DPC中断。否则以要产生的软中断的IRQL为索引从HalpIRQLtoTPRHAL取出对应任务优先级,并或上0x4000,表示是发向自身的固定处理间中断,并用该值设置中断命令寄存器ICW的低32位,然后读取中断命令寄存器ICW的低32位是否为0x1000,确定中断消息已经发送后就返回,这时候软中断已经产生。值得注意的是APIC HAL里没有HalEndSoftwareInterrupt这个函数。