https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7f2e0ece5a4e408f509299a7efe1aec72a471432

commit 7f2e0ece5a4e408f509299a7efe1aec72a471432
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Fri Mar 9 23:55:54 2018 +0100
Commit:     Timo Kreuzer <[email protected]>
CommitDate: Fri Jun 4 09:19:13 2021 +0200

    [NTOS:KE/x64] Handle shared interrupts
---
 ntoskrnl/ke/amd64/interrupt.c | 37 ++++++++++++++++++++++++++++++-------
 ntoskrnl/ke/amd64/trap.S      | 37 ++++++++++++++++++++++++++++++-------
 2 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/ntoskrnl/ke/amd64/interrupt.c b/ntoskrnl/ke/amd64/interrupt.c
index 1ca46b33673..a1e66da4dde 100644
--- a/ntoskrnl/ke/amd64/interrupt.c
+++ b/ntoskrnl/ke/amd64/interrupt.c
@@ -81,10 +81,14 @@ NTAPI
 KeConnectInterrupt(IN PKINTERRUPT Interrupt)
 {
     PVOID CurrentHandler;
+    PKINTERRUPT ConnectedInterrupt;
 
+    ASSERT(Interrupt->Vector >= PRIMARY_VECTOR_BASE);
     ASSERT(Interrupt->Vector <= MAXIMUM_IDTVECTOR);
     ASSERT(Interrupt->Number < KeNumberProcessors);
     ASSERT(Interrupt->Irql <= HIGH_LEVEL);
+    ASSERT(Interrupt->SynchronizeIrql >= Interrupt->Irql);
+    ASSERT(Interrupt->Irql == (Interrupt->Vector >> 4));
 
     /* Check if its already connected */
     if (Interrupt->Connected) return TRUE;
@@ -92,7 +96,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
     /* Query the current handler */
     CurrentHandler = KeQueryInterruptHandler(Interrupt->Vector);
 
-    /* Check if the vector is already unused */
+    /* Check if the vector is unused */
     if ((CurrentHandler >= (PVOID)KiUnexpectedRange) &&
         (CurrentHandler <= (PVOID)KiUnexpectedRangeEnd))
     {
@@ -106,6 +110,7 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
         KeRegisterInterruptHandler(Interrupt->Vector,
                                    Interrupt->DispatchCode);
 
+        /* Enable the interrupt */
         if (!HalEnableSystemInterrupt(Interrupt->Vector,
                                       Interrupt->Irql,
                                       Interrupt->Mode))
@@ -115,16 +120,28 @@ KeConnectInterrupt(IN PKINTERRUPT Interrupt)
             KeRegisterInterruptHandler(Interrupt->Vector, CurrentHandler);
             return FALSE;
         }
-
-        /* Mark as connected */
-        Interrupt->Connected = TRUE;
     }
     else
     {
-        // later
-        __debugbreak();
+        /* Get the connected interrupt */
+        ConnectedInterrupt = CONTAINING_RECORD(CurrentHandler, KINTERRUPT, 
DispatchCode);
+
+        /* Check if sharing is ok */
+        if ((Interrupt->ShareVector == 0) ||
+            (ConnectedInterrupt->ShareVector == 0) ||
+            (Interrupt->Mode != ConnectedInterrupt->Mode))
+        {
+            return FALSE;
+        }
+
+        /* Insert the new interrupt into the connected interrupt's list */
+        InsertTailList(&ConnectedInterrupt->InterruptListEntry,
+                       &Interrupt->InterruptListEntry);
     }
 
+    /* Mark as connected */
+    Interrupt->Connected = TRUE;
+
     return TRUE;
 }
 
@@ -132,9 +149,15 @@ BOOLEAN
 NTAPI
 KeDisconnectInterrupt(IN PKINTERRUPT Interrupt)
 {
+    /* If the interrupt wasn't connected, there's nothing to do */
+    if (!Interrupt->Connected)
+    {
+        return FALSE;
+    }
+
     UNIMPLEMENTED;
     __debugbreak();
-    return FALSE;
+    return TRUE;
 }
 
 BOOLEAN
diff --git a/ntoskrnl/ke/amd64/trap.S b/ntoskrnl/ke/amd64/trap.S
index 7fb5c05919b..b7a267a7256 100644
--- a/ntoskrnl/ke/amd64/trap.S
+++ b/ntoskrnl/ke/amd64/trap.S
@@ -696,26 +696,35 @@ FUNC KiInterruptDispatch
     /* Increase interrupt count */
     inc dword ptr gs:[PcInterruptCount];
 
-    /* Load the address of the interrupt object into rcx */
-    mov rcx, [rbp + KTRAP_FRAME_ErrorCode]
+    /* Save rbx and rsi in the trap frame */
+    mov [rbp + KTRAP_FRAME_Rbx], rbx
+    mov [rbp + KTRAP_FRAME_Rsi], rsi
+
+    /* Load the address of the dispatch code into rbx */
+    mov rbx, [rbp + KTRAP_FRAME_ErrorCode]
 
     /* Substract offset of the DispatchCode member plus 6 for the call 
instruction */
-    sub rcx, KINTERRUPT_DispatchCode + 6
+    sub rbx, KINTERRUPT_DispatchCode + 6
+
+    /* Save the address of the InterruptListEntry in rsi */
+    lea rsi, [rbx + KINTERRUPT_InterruptListEntry]
 
+.DoDispatchInterrupt:
     /* Raise IRQL to SynchronizeIrql */
-    movzx rax, byte ptr [rcx + KINTERRUPT_SynchronizeIrql]
+    movzx rax, byte ptr [rbx + KINTERRUPT_SynchronizeIrql]
     mov cr8, rax
 
 #ifdef CONFIG_SMP
     /* Acquire interrupt lock */
-    mov r8, [rcx + KINTERRUPT_ActualLock]
+    mov r8, [rbx + KINTERRUPT_ActualLock]
 
     //KxAcquireSpinLock(Interrupt->ActualLock);
 #endif
 
     /* Call the ISR */
-    mov rdx, [rcx + KINTERRUPT_ServiceContext]
-    call qword ptr [rcx + KINTERRUPT_ServiceRoutine]
+    mov rcx, rbx
+    mov rdx, [rbx + KINTERRUPT_ServiceContext]
+    call qword ptr [rbx + KINTERRUPT_ServiceRoutine]
 
 #ifdef CONFIG_SMP
     /* Release interrupt lock */
@@ -726,6 +735,20 @@ FUNC KiInterruptDispatch
     movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql]
     mov cr8, rax
 
+    /* Check for chained interrupts */
+    mov rax, [rbx + KINTERRUPT_InterruptListEntry]
+    cmp rax, rsi
+    je .Done
+
+    /* Load the next interrupt object into rbx and repeat */
+    lea rbx, [rax - KINTERRUPT_InterruptListEntry]
+    jmp .DoDispatchInterrupt
+
+.Done:
+    /* Restore rbx and rsi */
+    mov rbx, [rbp + KTRAP_FRAME_Rbx]
+    mov rsi, [rbp + KTRAP_FRAME_Rsi]
+
     /* Return */
     ExitTrap (TF_SAVE_ALL or TF_SEND_EOI)
 ENDFUNC

Reply via email to