IoConnectInterrupt . 2

xp下用xuetr查看系统中断表,可以看到很多红色的未知模块,其实这就是设备正常的中断处理函数,那些序号保存在 HalpInTitoVector 里面
这一堆向量是通过 index*0x10 + 0x50 + (1..nPriority[index]) 计算出来的
譬如193,其中1是HalpMaxnode,93是向量,
lkd> db nPriority
8070ec40  00 03 04 04 04 04 04 00-00 00 00 0     // 第6位为4,那就是 6*0x10 + 0x50 + (1..4)     = > [b1-b4]
                                                 // 一直算到第1位 3, 那  1*0x10 +0x50 + (1..3) = > [61-63]
lkd> dd HalpMaxnode
8070e780  00000001
lkd> dd HalpInTitoVector
8070ed60  00000000 00000193 00000161 000001b2
8070ed70  00000192 000001a2 000001b3 00000191
8070ed80  000001a1 000001b1 00000171 00000181
8070ed90  000001a3 00000172 00000162 00000182
8070eda0  000001a4 00000194 00000174 00000184
8070edb0  00000183 00000173 00000163 000001b4
这些数值为什么这么排列还没搞清楚,反正与apic有关系,设备出现中断后,apic会计算出对应的vector供系统使用,目前只知道键盘在apic中的中断号是0x12
譬如键盘出现中断信息:apic(0x12) ---> os(0x93) ,系统拿这个0x93去idt里找对应的中断处理函数

这个值也是能修改的,参照 : https://blog.csdn.net/qq1841370452/article/details/73369188 (好想用RW手动改成0x95,就怕键盘真不响应了,那我咋改回来呢!!!)

另外这个中断号是能共用的,我的电脑上一个0x94里面就是共用的,在xuetr里反汇编"当前函数地址",往下面找一个mov edi,xxxxxxx指令,是个_kinterrupt结构

也可以不用反汇编,直接 "当前函数地址" 8A15FA6C-3c, 因为当前函数地址就是DispatchCode的地址,在_kinterrupt结构中偏移0x3C

lkd> dt _kinterrupt 8a15fa30
nt!_KINTERRUPT
   +0x000 Type             : 0n22
   +0x002 Size             : 0n484
   +0x004 InterruptListEntry : _LIST_ENTRY [ 0x8a0840ac - 0x88911bb4 ]             // 偏移+0x4, 下面随便取一个 0x8a0840ac-4 看看
   +0x00c ServiceRoutine   : 0xf765d2f0     unsigned char  ohci1394!OhciIsr+0      // 真正的处理函数, 与 ohci1394 有关
   +0x010 ServiceContext   : 0x8a0ae0e0 Void
   +0x014 SpinLock         : 0
   +0x018 TickCount        : 0xffffffff
   +0x01c ActualLock       : 0x8a0af600  -> 0
   +0x020 DispatchAddress  : 0x804dc6ca     void  nt!KiChainedDispatch+0           // 可能是在这个函数里,对不同的中断区分吧,不清楚
   +0x024 Vector           : 0x194                                                 // 向量号 0x194
   +0x028 Irql             : 0x8 ''
   +0x029 SynchronizeIrql  : 0x8 ''
   +0x02a FloatingSave     : 0 ''
   +0x02b Connected        : 0x1 ''
   +0x02c Number           : 0 ''
   +0x02d ShareVector      : 0x1 ''                                                // 共享
   +0x030 Mode             : 0 ( LevelSensitive )                                  // ...
   +0x034 ServiceCount     : 0
   +0x038 DispatchCount    : 0xffffffff
   +0x03c DispatchCode     : [106] 0x56535554                                      // "当前函数地址" 指向的值这里

lkd> dt _kinterrupt 0x8a0840ac-4 
nt!_KINTERRUPT
   +0x000 Type             : 0n22
   +0x002 Size             : 0n484
   +0x004 InterruptListEntry : _LIST_ENTRY [ 0x894be73c - 0x8a15fa34 ]
   +0x00c ServiceRoutine   : 0xb7ccced2     unsigned char  USBPORT!USBPORT_InterruptService+0    // 真正的处理函数, 与什么USBPORT有关
   +0x010 ServiceContext   : 0x89581028 Void                                      
   +0x014 SpinLock         : 0
   +0x018 TickCount        : 0xffffffff
   +0x01c ActualLock       : 0x8a08430c  -> 0
   +0x020 DispatchAddress  : (null)                                                // 共享,统一由上面的 nt!KiChainedDispatch+0 处理?
   +0x024 Vector           : 0x194                                                 // 向量号 0x194
   +0x028 Irql             : 0x8 ''
   +0x029 SynchronizeIrql  : 0x8 ''
   +0x02a FloatingSave     : 0 ''
   +0x02b Connected        : 0x1 ''
   +0x02c Number           : 0 ''
   +0x02d ShareVector      : 0x1 ''                                                // 共享
   +0x030 Mode             : 0 ( LevelSensitive )
   +0x034 ServiceCount     : 0
   +0x038 DispatchCount    : 0xffffffff
   +0x03c DispatchCode     : [106] 0x56535554

顺便看看键盘的0x93, 0x894876EC-0x3C

lkd> dt _kinterrupt 894876b0
nt!_KINTERRUPT
   +0x000 Type             : 0n22
   +0x002 Size             : 0n484
   +0x004 InterruptListEntry : _LIST_ENTRY [ 0x894876b4 - 0x894876b4 ]             // 链表就自己一项
   +0x00c ServiceRoutine   : 0xb88b6495     unsigned char  i8042prt!I8042KeyboardInterruptService+0
   +0x010 ServiceContext   : 0x89561b20 Void
   +0x014 SpinLock         : 0
   +0x018 TickCount        : 0xffffffff
   +0x01c ActualLock       : 0x89561be0  -> 0
   +0x020 DispatchAddress  : 0x804dc8ca     void  nt!KiInterruptDispatch+0         // 独享中断由此函数处理?
   +0x024 Vector           : 0x193                                                 // 向量号 0x193
   +0x028 Irql             : 0x8 ''
   +0x029 SynchronizeIrql  : 0x9 ''
   +0x02a FloatingSave     : 0 ''
   +0x02b Connected        : 0x1 ''
   +0x02c Number           : 0 ''
   +0x02d ShareVector      : 0 ''                                                  // 不共享
   +0x030 Mode             : 1 ( Latched )                                         // ...
   +0x034 ServiceCount     : 0
   +0x038 DispatchCount    : 0xffffffff
   +0x03c DispatchCode     : [106] 0x56535554
  • 不清楚apic怎么把硬件中断,和系统的idt vector对应的, (0x12 -> 0x93),但 ( ??? -> 0x94) --- reactos里面的代码,关于apic的重定位
键盘的的0x12原来是这么来的  IOAPIC_REDTBL + 2 * 1。 这个 1 是“设备管理器”->“属性”->“资源”里的 “中断请求” 值, 
devicenode里的ResourceList 包含了中断资源 vector = 1, ResourceListTranslated里的vector = 0x193
IOAPIC_REDTBL = 0x10
ApicWriteIORedirectionEntry(UCHAR Index,IOAPIC_REDIRECTION_REGISTER ReDirReg)            
{ // 写 apic vector -> os vector 的对应
    IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);      
    IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
}
ApicReadIORedirectionEntry(UCHAR Index)                                                  
{ // 读 apic vector->os vector的对应
    IOAPIC_REDIRECTION_REGISTER ReDirReg;

    ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);            // 在系统测试,果然获得 apic的 0x10 + 2*17 (0x32) -> os的0x94
    ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1);

    return ReDirReg;
}
KiChainedDispatch() // 共用的中断处理模板
{
      ...
      ListHead = &Interrupt->InterruptListEntry;
      NextEntry = ListHead;

      while (TRUE) //遍历中断对象链表,直至找到一个能处理这个中断的中断对象为止
      {            
            if (Interrupt->SynchronizeIrql > Interrupt->Irql)//再次提升irql
                  OldIrql = KfRaiseIrql(Interrupt->SynchronizeIrql);  

            KxAcquireSpinLock(Interrupt->ActualLock);//加锁,保障多cpu互斥

            //执行我们的isr(即用户自己提供的isr),注意返回值

            Handled = Interrupt->ServiceRoutine(Interrupt,Interrupt->ServiceContext);

            KxReleaseSpinLock(Interrupt->ActualLock);

            if (Interrupt->SynchronizeIrql > Interrupt->Irql)
                KfLowerIrql(OldIrql);

            //if本中断对象认领了,且不许执行下一个中断对象就退出查找循环。
            //(LevelSensitive即FALSE,一般的中断对象都这样)
            if ((Handled) && (Interrupt->Mode == LevelSensitive))             // 找到能处理的就跳出
                  break;

            NextEntry = NextEntry->Flink;
            if (NextEntry == ListHead)//if链表中的最后一个中断对象
            {
                if (Interrupt->Mode == LevelSensitive) break;
                if (!Handled) break;//if没能处理这个中断,退出循环
            }
            Interrupt = CONTAINING_RECORD(NextEntry, KINTERRUPT, InterruptListEntry);
      } // end while
      ...
}
posted @ 2020-11-20 17:20  一条小鳄鱼  阅读(160)  评论(0)    收藏  举报