Beispiel #1
0
/*
 * @implemented
 */
BOOLEAN
NTAPI
KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt,
                       IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
                       IN PVOID SynchronizeContext OPTIONAL)
{
    BOOLEAN Success;
    KIRQL OldIrql;
    
    /* Raise IRQL */
    OldIrql = KfRaiseIrql(Interrupt->SynchronizeIrql);
    
    /* Acquire interrupt spinlock */
    KeAcquireSpinLockAtDpcLevel(Interrupt->ActualLock);
    
    /* Call the routine */
    Success = SynchronizeRoutine(SynchronizeContext);
    
    /* Release lock */
    KeReleaseSpinLockFromDpcLevel(Interrupt->ActualLock);
    
    /* Lower IRQL */
    KfLowerIrql(OldIrql);
    
    /* Return status */
    return Success;
}
Beispiel #2
0
VOID
NTAPI
INIT_FUNCTION
KiSystemStartupBootStack(VOID)
{
    PKTHREAD Thread;

    /* Initialize the kernel for the current CPU */
    KiInitializeKernel(&KiInitialProcess.Pcb,
                       (PKTHREAD)KeLoaderBlock->Thread,
                       (PVOID)(KeLoaderBlock->KernelStack & ~3),
                       (PKPRCB)__readfsdword(KPCR_PRCB),
                       KeNumberProcessors - 1,
                       KeLoaderBlock);

    /* Set the priority of this thread to 0 */
    Thread = KeGetCurrentThread();
    Thread->Priority = 0;

    /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
    _enable();
    KfLowerIrql(DISPATCH_LEVEL);

    /* Set the right wait IRQL */
    Thread->WaitIrql = DISPATCH_LEVEL;

    /* Jump into the idle loop */
    KiIdleLoop();
}
Beispiel #3
0
/*
 * @implemented
 */
VOID
NTAPI
KeLowerIrql(KIRQL NewIrql)
{
    /* Call the fastcall function */
    KfLowerIrql(NewIrql);
}
Beispiel #4
0
/*
 * @implemented
 */
VOID
FASTCALL
KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
{
    /* Simply lower IRQL back */
    KfLowerIrql(LockHandle->OldIrql);
}
Beispiel #5
0
/*
 * @implemented
 */
VOID
FASTCALL
KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber,
                        IN KIRQL OldIrql)
{
    /* Simply lower IRQL back */
    KfLowerIrql(OldIrql);
}
Beispiel #6
0
VOID
HalpPCIReleaseType2Lock (
    PKSPIN_LOCK SpinLock,
    KIRQL       Irql
    )
{
    if (!HalpDoingCrashDump) {
        KiReleaseSpinLock (SpinLock);
        KfLowerIrql (Irql);
    }
}
Beispiel #7
0
// ******************************************************************
// * 0x00A3 - KiUnlockDispatcherDatabase()
// ******************************************************************
XBSYSAPI EXPORTNUM(163) xboxkrnl::VOID FASTCALL xboxkrnl::KiUnlockDispatcherDatabase
(
	IN KIRQL OldIrql
)
{
	LOG_FUNC_ONE_ARG_TYPE(KIRQL_TYPE, OldIrql);

	if (!(KeGetCurrentPrcb()->DpcRoutineActive)) // Avoid KeIsExecutingDpc(), as that logs
		HalRequestSoftwareInterrupt(DISPATCH_LEVEL);

	LOG_INCOMPLETE(); // TODO : Thread-switch?

	KfLowerIrql(OldIrql);
}
Beispiel #8
0
DECLSPEC_NORETURN
VOID
FASTCALL
KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
{
    ULONG i, j, Iopl;
    BOOLEAN Privileged = FALSE;
    PUCHAR Instructions;
    UCHAR Instruction = 0;
    KIRQL OldIrql;
    
    /* Check for V86 GPF */
    if (__builtin_expect(KiV86Trap(TrapFrame), 1))
    {
        /* Enter V86 trap */
        KiEnterV86Trap(TrapFrame);
        
        /* Must be a VDM process */
        if (__builtin_expect(!PsGetCurrentProcess()->VdmObjects, 0))
        {
            /* Enable interrupts */
            _enable();
            
            /* Setup illegal instruction fault */
            KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
                                     TrapFrame->Eip,
                                     TrapFrame);
        }
        
        /* Go to APC level */
        OldIrql = KfRaiseIrql(APC_LEVEL);
        _enable();
        
        /* Handle the V86 opcode */
        if (__builtin_expect(Ki386HandleOpcodeV86(TrapFrame) == 0xFF, 0))
        {
            /* Should only happen in VDM mode */
            UNIMPLEMENTED;
            while (TRUE);
        }
        
        /* Bring IRQL back */
        KfLowerIrql(OldIrql);
        _disable();
        
        /* Do a quick V86 exit if possible */
        KiExitV86Trap(TrapFrame);
    }
    
    /* Save trap frame */
    KiEnterTrap(TrapFrame);

    /* Check for user-mode GPF */
    if (KiUserTrap(TrapFrame))
    {
        /* Should not be VDM */
        ASSERT(KiVdmTrap(TrapFrame) == FALSE);
        
        /* Enable interrupts and check error code */
        _enable();
        if (!TrapFrame->ErrCode)
        {
            /* FIXME: Use SEH */
            Instructions = (PUCHAR)TrapFrame->Eip;
            
            /* Scan next 15 bytes */
            for (i = 0; i < 15; i++)
            {
                /* Skip prefix instructions */
                for (j = 0; j < sizeof(KiTrapPrefixTable); j++)
                {
                    /* Is this a prefix instruction? */
                    if (Instructions[i] == KiTrapPrefixTable[j])
                    {
                        /* Stop looking */
                        break;
                    }
                }
                
                /* Is this NOT any prefix instruction? */
                if (j == sizeof(KiTrapPrefixTable))
                {
                    /* We can go ahead and handle the fault now */
                    Instruction = Instructions[i];
                    break;
                }
            }
            
            /* If all we found was prefixes, then this instruction is too long */
            if (i == 15)
            {
                /* Setup illegal instruction fault */
                KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
                                         TrapFrame->Eip,
                                         TrapFrame);
            }
            
            /* Check for privileged instructions */
            if (Instruction == 0xF4)                            // HLT
            {
                /* HLT is privileged */
                Privileged = TRUE;
            }
            else if (Instruction == 0x0F)
            {
                /* Test if it's any of the privileged two-byte opcodes */
                if (((Instructions[i + 1] == 0x00) &&              // LLDT or LTR
                     (((Instructions[i + 2] & 0x38) == 0x10) ||        // LLDT
                      (Instructions[i + 2] == 0x18))) ||               // LTR
                    ((Instructions[i + 1] == 0x01) &&              // LGDT or LIDT or LMSW
                     (((Instructions[i + 2] & 0x38) == 0x10) ||        // LGDT
                      (Instructions[i + 2] == 0x18) ||                 // LIDT
                      (Instructions[i + 2] == 0x30))) ||               // LMSW
                    (Instructions[i + 1] == 0x08) ||               // INVD
                    (Instructions[i + 1] == 0x09) ||               // WBINVD
                    (Instructions[i + 1] == 0x35) ||               // SYSEXIT
                    (Instructions[i + 1] == 0x26) ||               // MOV DR, XXX
                    (Instructions[i + 1] == 0x06) ||               // CLTS
                    (Instructions[i + 1] == 0x20) ||               // MOV CR, XXX
                    (Instructions[i + 1] == 0x24) ||               // MOV YYY, DR
                    (Instructions[i + 1] == 0x30) ||               // WRMSR
                    (Instructions[i + 1] == 0x33))                 // RDPMC
                    // INVLPG, INVLPGA, SYSRET
                {
                    /* These are all privileged */
                    Privileged = TRUE;
                }
            }
            else
            {
                /* Get the IOPL and compare with the RPL mask */
                Iopl = (TrapFrame->EFlags & EFLAGS_IOPL) >> 12;
                if ((TrapFrame->SegCs & RPL_MASK) > Iopl)
                {
                    /* I/O privilege error -- check for known instructions */
                    if ((Instruction == 0xFA) || (Instruction == 0xFB)) // CLI or STI
                    {
                        /* These are privileged */
                        Privileged = TRUE;
                    }
                    else
                    {
                        /* Last hope: an IN/OUT instruction */
                        for (j = 0; j < sizeof(KiTrapIoTable); j++)
                        {
                            /* Is this an I/O instruction? */
                            if (Instruction == KiTrapIoTable[j])
                            {
                                /* Then it's privileged */
                                Privileged = TRUE;
                                break;
                            }
                        }
                    }
                }
            }
            
            /* So now... was the instruction privileged or not? */
            if (Privileged)
            {
                /* Whew! We have a privileged instruction, so dispatch the fault */
                KiDispatchException0Args(STATUS_PRIVILEGED_INSTRUCTION,
                                         TrapFrame->Eip,
                                         TrapFrame);
            }
        }
            
        /* If we got here, send an access violation */
        KiDispatchException2Args(STATUS_ACCESS_VIOLATION,
                                 TrapFrame->Eip,
                                 0,
                                 0xFFFFFFFF,
                                 TrapFrame);
    }
Beispiel #9
0
DECLSPEC_NORETURN
VOID
FASTCALL
KiTrap06Handler(IN PKTRAP_FRAME TrapFrame)
{
    PUCHAR Instruction;
    ULONG i;
    KIRQL OldIrql;
    
    /* Check for V86 GPF */
    if (__builtin_expect(KiV86Trap(TrapFrame), 1))
    {
        /* Enter V86 trap */
        KiEnterV86Trap(TrapFrame);
        
        /* Must be a VDM process */
        if (__builtin_expect(!PsGetCurrentProcess()->VdmObjects, 0))
        {
            /* Enable interrupts */
            _enable();
            
            /* Setup illegal instruction fault */
            KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
                                     TrapFrame->Eip,
                                     TrapFrame);
        }
        
        /* Go to APC level */
        OldIrql = KfRaiseIrql(APC_LEVEL);
        _enable();
        
        /* Check for BOP */
        if (!VdmDispatchBop(TrapFrame))
        {
            /* Should only happen in VDM mode */
            UNIMPLEMENTED;
            while (TRUE);
        }
        
        /* Bring IRQL back */
        KfLowerIrql(OldIrql);
        _disable();
        
        /* Do a quick V86 exit if possible */
        KiExitV86Trap(TrapFrame);
    }

    /* Save trap frame */
    KiEnterTrap(TrapFrame);
    
    /* Enable interrupts */
    Instruction = (PUCHAR)TrapFrame->Eip;
    _enable();
        
    /* Check for user trap */
    if (KiUserTrap(TrapFrame))
    {
        /* FIXME: Use SEH */
        
        /* Scan next 4 opcodes */
        for (i = 0; i < 4; i++)
        {
            /* Check for LOCK instruction */
            if (Instruction[i] == 0xF0)
            {
                /* Send invalid lock sequence exception */
                KiDispatchException0Args(STATUS_INVALID_LOCK_SEQUENCE,
                                         TrapFrame->Eip,
                                         TrapFrame);
            }
        }
        
        /* FIXME: SEH ends here */
    }
    
    /* Kernel-mode or user-mode fault (but not LOCK) */
    KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION,
                             TrapFrame->Eip,
                             TrapFrame);
    
}
Beispiel #10
0
VOID
FASTCALL
KiTimedChainedDispatch2ndLvl(
    PKINTERRUPT Interrupt
    )

/*++

Routine Description:

    This function performs the same function as KiChainedDispatch2ndLvl
    except that it is written in C instead of assembly code and includes
    code for timing ISRs.

    I'd be interested in seeing some benchmarks to show if the assembly
    code is actually faster.    The Acquire/Release spinlock could be
    inlined fairly easily.

Arguments:

    Interrupt - Supplies a pointer to a control object of type interrupt.

Return Value:

    None.

--*/

{
    BOOLEAN Handled = FALSE;
    PVOID ListEnd = &Interrupt->InterruptListEntry.Flink;
    //
    //BEGINTIMING

    PKPRCB Prcb = KeGetCurrentPrcb();
    ULONGLONG StartTimeHigher;
    ULONGLONG StartTime;
    ULONGLONG TimeHigher;
    ULONGLONG ElapsedTime;

    //BEGINTIMINGend


    //
    // For each interrupt on this chain.
    //

    do {

        //
        // If the current IRQL (IRQL raised to by nature of taking this
        // interrupt) is not equal to the Synchronization IRQL required
        // for this interrupt, raise to the appropriate level.
        //

        if (Interrupt->Irql != Interrupt->SynchronizeIrql) {
            KfRaiseIrql(Interrupt->SynchronizeIrql);
        }

        //BEGINTIMING

        StartTimeHigher = Prcb->IsrTime;
        StartTime = RDTSC();

        //BEGINTIMINGend

        //
        // Acquire the interrupt lock.
        //

        KiAcquireSpinLock(Interrupt->ActualLock);

        //
        // Call the Interrupt Service Routine.
        //

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

        //
        // Release the interrupt lock.
        //

        KiReleaseSpinLock(Interrupt->ActualLock);

        //ENDTIMING

        //
        // ElapsedTime is time since we started looking at this element
        // on the chain.  (ie the current interrupt object).
        //

        ElapsedTime = RDTSC() - StartTime;

        //
        // TimeHigher is the amount Prcb->IsrTime has increased since we
        // begin servicing this interrupt object, ie the amount of time
        // spent in higher level ISRs.
        //

        TimeHigher = Prcb->IsrTime - StartTimeHigher;

        //
        // Adjust ElapsedTime to time spent on this interrupt object, excluding 
        // higher level ISRs.
        //

        ElapsedTime -= TimeHigher;
        if (ElapsedTime > KiIsrTscLimit) {

            //
            // If there is a debugger attached, breakin.   Otherwise do nothing.
            // N.B. bugchecking is another possibility.
            //

            if (KdDebuggerEnabled) {
                DbgPrint("KE; ISR time limit exceeded (intobj %p)\n",
                         Interrupt);
                DbgBreakPoint();
            }
        }

        //
        // Update time spent processing interrupts.   This doesn't need 
        // to be atomic as it doesn't matter if it's a little bit lossy.
        // (Though a simple atomic add would do, it's per processor and
        // at IRQL > DISPATCH_LEVEL so it doesn't need to be locked).
        //

        Prcb->IsrTime += ElapsedTime;

        //ENDTIMINGend

        //
        // If IRQL was raised, lower to the previous level.
        //

        if (Interrupt->Irql != Interrupt->SynchronizeIrql) {
            KfLowerIrql(Interrupt->Irql);
        }

        if ((Handled != FALSE) &&
            (Interrupt->Mode == LevelSensitive)) {

            //
            // The interrupt has been handled.
            //

            return;
        }

        //
        // If this is the last entry on the chain, get out, otherwise
        // advance to the next entry.
        //

        if (Interrupt->InterruptListEntry.Flink == ListEnd) {
            ASSERT(Interrupt->Mode != LevelSensitive);

            //
            // We should only get to the end of the list if
            // (a) interrupts are on this chain are level sensitive and
            //     no ISR handled the request.   This is a system fatal
            //     condition, or,
            // (b) the chain has edge triggered interrupts in which case
            //     we must run the chain repeatedly until no ISR services
            //     the request.
            //
            // Question:  Do we actually have chained edge triggered
            //            interrupts anymore?
            //

            if (Handled == FALSE) {
                break;
            }
        }
        Interrupt = CONTAINING_RECORD(Interrupt->InterruptListEntry.Flink,
                                      KINTERRUPT,
                                      InterruptListEntry);
    } while (TRUE);
}
Beispiel #11
0
VOID
FASTCALL
KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
                  IN PKINTERRUPT Interrupt)
{
    KIRQL OldIrql, OldInterruptIrql = 0;
    BOOLEAN Handled;
    PLIST_ENTRY NextEntry, ListHead;

    /* Increase interrupt count */
    KeGetCurrentPrcb()->InterruptCount++;

    /* Begin the interrupt, making sure it's not spurious */
    if (HalBeginSystemInterrupt(Interrupt->Irql,
                                Interrupt->Vector,
                                &OldIrql))
    {
        /* Get list pointers */
        ListHead = &Interrupt->InterruptListEntry;
        NextEntry = ListHead; /* The head is an entry! */
        while (TRUE)
        {
            /* Check if this interrupt's IRQL is higher than the current one */
            if (Interrupt->SynchronizeIrql > Interrupt->Irql)
            {
                /* Raise to higher IRQL */
                OldInterruptIrql = KfRaiseIrql(Interrupt->SynchronizeIrql);
            }
        
            /* Acquire interrupt lock */
            KxAcquireSpinLock(Interrupt->ActualLock);

            /* Call the ISR */
            Handled = Interrupt->ServiceRoutine(Interrupt,
                                                Interrupt->ServiceContext);

            /* Release interrupt lock */
            KxReleaseSpinLock(Interrupt->ActualLock);
        
            /* Check if this interrupt's IRQL is higher than the current one */
            if (Interrupt->SynchronizeIrql > Interrupt->Irql)
            {
                /* Lower the IRQL back */
                ASSERT(OldInterruptIrql == Interrupt->Irql);
                KfLowerIrql(OldInterruptIrql);
            }
        
            /* Check if the interrupt got handled and it's level */
            if ((Handled) && (Interrupt->Mode == LevelSensitive)) break;
            
            /* What's next? */
            NextEntry = NextEntry->Flink;
                
            /* Is this the last one? */
            if (NextEntry == ListHead)
            {
                /* Level should not have gotten here */
                if (Interrupt->Mode == LevelSensitive) break;
                
                /* As for edge, we can only exit once nobody can handle the interrupt */
                if (!Handled) break;
            }
            
            /* Get the interrupt object for the next pass */
            Interrupt = CONTAINING_RECORD(NextEntry, KINTERRUPT, InterruptListEntry);
        }

        /* Now call the epilogue code */
        KiExitInterrupt(TrapFrame, OldIrql, FALSE);
    }
    else
    {
        /* Now call the epilogue code */
        KiExitInterrupt(TrapFrame, OldIrql, TRUE);
    }
}