[NTOS:KE/x64] Handle shared interrupts

This commit is contained in:
Timo Kreuzer 2018-03-09 23:55:54 +01:00
parent ce537f1ae9
commit 7f2e0ece5a
2 changed files with 60 additions and 14 deletions

View file

@ -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

View file

@ -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