IOAPIC

标题:【原创】【有码】键盘过滤中关于IOAPIC重定位表的学习笔记

作者:zouzhiyong

时间: 2011-06-10,18:09:17

链接: https://www.360docs.net/doc/df12237783.html,/showthread.php?t=135230

技术原理:

IOAPIC是可以用于多个核心CPU的新型中断控制器,可以通过编程来对其控制,可以理解为可编程硬件。根据《寒江独钓》的说明,目前不管是单核还是双核都拥有IOAPIC机制。

对于IOAPIC的简单处理过程,我的理解如下(如果有错误,请路过的大牛一定要指正啊!!):

其中,上面用黄色笔做了标记的就是这个技术的核心。

因为硬中断IRQ最终都会交给中断处理程序进行,而Windows会根据中断向量号来转移到相应的中断处理程序。因此,就必然存在IRQ与中断向量号的映射关系。其实,Windows在初始化系统服务的时候就在IOAPIC中描述好这种映射关系了,注意我在上面画的图中,橙色标注的部分。

所以,整个技术的核心就修改在IOAPIC中,已经填写好的中断向量号。这样也就要求我们事先应该在IDT中插入一个中断门。

如何访问IOAPIC:

IOAPIC是通过读写其一系列的寄存器来实现编程控制的。根据《寒江独钓》提供的关于IOAPIC的Intel 手册资料来看,要访问IOAPIC,不能直接使用它的内部寄存器,而是要通过2个内存映射寄存器来访问一个是IOREGSEL,一个是IOWIN。其中Intel手册的说明如下:

这两个内存映射寄存器的描述如下:

按照手册的说明是寄存器,但实际上是两个物理内存地址,而且是制定了格式的了,就是FEC0XY00H和FEC0XY10H,其中X,Y是自定义值,也指定了取值范围,就是X = 0-FH,Y = 0,4,8,CH。根据《寒江独钓》里的说明,Windows已经规定了,IOREGSEL:FEC00000H;IOWIN:FEC00010H。

因为这里谈的都是真正的物理地址,是不能够直接访问的,在Windows下访问则需要对物理地址进行一个映射(实际上就是添加一个页表项来描述这个映射关系),在wdk中提供了一个这样的映射函数:PVOID

MmMapIoSpace(

IN PHYSICAL_ADDRESS PhysicalAddress,

IN SIZE_T NumberOfBytes,

IN MEMORY_CACHING_TYPE CacheType

);

经过映射后,我们就可以对其进行操作了。

首先是IOREGSEL映射寄存器。这个寄存器的作用是:让你指定要访问哪一个IOAPIC的内部寄存器。可以指定的内部寄存器有:

IOREGSEL映射寄存器的描述符如下:

可以看出只有低8位是有效位(在编程时候要注意的)。这里根据Intel手册的说明是,指定的是内部寄存器对应的地址偏移,为了方便理解,我们可以理解为编号,就是指定每个寄存器对应的编号。

第二个是IOWIN映射寄存器。这个寄存器的作用的作用是:显示IOREGSEL指定的内部寄存器的内容,你可以读取或修改IOWIN这个映射寄存器的值,然后映射机制会修改真正的IOAPIC内部寄存器的值。

IOAPIC的各内部寄存器对应的描述如下(一下资料均来自intel手册):

IOAPICVER—IOAPIC VERSION REGISTER:

IOAPICVER—IOAPIC VERSION REGISTER:

IOAPICARB—IOAPIC ARBITRATION REGISTER:

IOREDTBL[23:0]—I/O REDIRECTION TABLE REGISTERS:

这就是重定向表,每个IRQ与中断向量号的映射关系就记录在里面的0~7这个位段,这个表是一个数组,24项,也就说明了为什么在《寒江独钓》中说是有24个可编程的IRQ。

每个IRQ描述项都是8个字节,64位,描述如下(其实无必要,只是作为资料):

所以,我们要做的就是将0~7这个位段修改成我们的预先插入的中断处理的向量号。

参考了上面资料后就开始编程:

一些数据结构的定义:

首先在IDT中插入一个中断处理(插入一个中断门),并返回一个所在的中断向量号:

然后就是修改IOAPIC的重定位表:

编写一个总的调用函数:

编写一个动态卸载时候的UNHOOK函数:

写一点东西不容易啊,筋疲力尽了,希望对大家有那么一丁点的帮助!!

相关主题
相关文档
最新文档