VOID NTAPI INIT_FUNCTION KiSetProcessorType(VOID) { ULONG EFlags, NewEFlags; ULONG Reg, Dummy; ULONG Stepping, Type; /* Start by assuming no CPUID data */ KeGetCurrentPrcb()->CpuID = 0; /* Save EFlags */ EFlags = __readeflags(); /* XOR out the ID bit and update EFlags */ NewEFlags = EFlags ^ EFLAGS_ID; __writeeflags(NewEFlags); /* Get them back and see if they were modified */ NewEFlags = __readeflags(); if (NewEFlags != EFlags) { /* The modification worked, so CPUID exists. Set the ID Bit again. */ EFlags |= EFLAGS_ID; __writeeflags(EFlags); /* Peform CPUID 0 to see if CPUID 1 is supported */ CPUID(0, &Reg, &Dummy, &Dummy, &Dummy); if (Reg > 0) { /* Do CPUID 1 now */ CPUID(1, &Reg, &Dummy, &Dummy, &Dummy); /* * Get the Stepping and Type. The stepping contains both the * Model and the Step, while the Type contains the returned Type. * We ignore the family. * * For the stepping, we convert this: zzzzzzxy into this: x0y */ Stepping = Reg & 0xF0; Stepping <<= 4; Stepping += (Reg & 0xFF); Stepping &= 0xF0F; Type = Reg & 0xF00; Type >>= 8; /* Save them in the PRCB */ KeGetCurrentPrcb()->CpuID = TRUE; KeGetCurrentPrcb()->CpuType = (UCHAR)Type; KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping; }
/* * @implemented */ BOOLEAN NTAPI KeIsExecutingDpc(VOID) { /* Return if the Dpc Routine is active */ return KeGetCurrentPrcb()->DpcRoutineActive; }
VOID FASTCALL KiUnexpectedInterruptTailHandler(IN PKTRAP_FRAME TrapFrame) { KIRQL OldIrql; /* Enter trap */ KiEnterInterruptTrap(TrapFrame); /* Increase interrupt count */ KeGetCurrentPrcb()->InterruptCount++; /* Start the interrupt */ if (HalBeginSystemInterrupt(HIGH_LEVEL, TrapFrame->ErrCode, &OldIrql)) { /* Warn user */ DPRINT1("\n\x7\x7!!! Unexpected Interrupt 0x%02lx !!!\n", TrapFrame->ErrCode); /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, FALSE); } else { /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, TRUE); } }
VOID KiAdjustQuantumThread ( IN PKTHREAD Thread ) /*++ Routine Description: If the current thread is not a time critical or realtime thread, then adjust its quantum in accordance with the adjustment that would have occured if the thread had actually waited. Arguments: Thread - Supplies a pointer to the current thread. Return Value: None. --*/ { PKPRCB Prcb; PKPROCESS Process; PKTHREAD NewThread; SCHAR ThreadPriority; if ((Thread->Priority < LOW_REALTIME_PRIORITY) && (Thread->BasePriority < TIME_CRITICAL_PRIORITY_BOUND)) { Thread->Quantum -= WAIT_QUANTUM_DECREMENT; if (Thread->Quantum <= 0) { Process = Thread->ApcState.Process; Thread->Quantum = Process->ThreadQuantum; ThreadPriority = Thread->Priority - (Thread->PriorityDecrement + 1); if (ThreadPriority < Thread->BasePriority) { ThreadPriority = Thread->BasePriority; } Thread->PriorityDecrement = 0; if (ThreadPriority != Thread->Priority) { KiSetPriorityThread(Thread, ThreadPriority); } else { Prcb = KeGetCurrentPrcb(); if (Prcb->NextThread == NULL) { NewThread = KiFindReadyThread(Thread->NextProcessor, ThreadPriority); if (NewThread != NULL) { Prcb->NextThread = NewThread; NewThread->State = Standby; } } } } } return; }
VOID FASTCALL KiInterruptDispatch(IN PKTRAP_FRAME TrapFrame, IN PKINTERRUPT Interrupt) { KIRQL OldIrql; /* Increase interrupt count */ KeGetCurrentPrcb()->InterruptCount++; /* Begin the interrupt, making sure it's not spurious */ if (HalBeginSystemInterrupt(Interrupt->SynchronizeIrql, Interrupt->Vector, &OldIrql)) { /* Acquire interrupt lock */ KxAcquireSpinLock(Interrupt->ActualLock); /* Call the ISR */ Interrupt->ServiceRoutine(Interrupt, Interrupt->ServiceContext); /* Release interrupt lock */ KxReleaseSpinLock(Interrupt->ActualLock); /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, FALSE); } else { /* Now call the epilogue code */ KiExitInterrupt(TrapFrame, OldIrql, TRUE); } }
/* * @implemented */ VOID NTAPI KeGenericCallDpc(IN PKDEFERRED_ROUTINE Routine, IN PVOID Context) { ULONG Barrier = KeNumberProcessors; KIRQL OldIrql; DEFERRED_REVERSE_BARRIER ReverseBarrier; ASSERT(KeGetCurrentIrql () < DISPATCH_LEVEL); // // The barrier is the number of processors, each processor will decrement it // by one, so when all processors have run the DPC, the barrier reaches zero // ReverseBarrier.Barrier = Barrier; ReverseBarrier.TotalProcessors = Barrier; // // But we don't need the barrier on UP, since we can simply call the routine // directly while at DISPATCH_LEVEL and not worry about anything else // KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); Routine(&KeGetCurrentPrcb()->CallDpc, Context, &Barrier, &ReverseBarrier); KeLowerIrql(OldIrql); }
VOID HalCalibratePerformanceCounter ( IN volatile PLONG Number ) /*++ Routine Description: This routine resets the performance counter value for the current processor to zero. The reset is done such that the resulting value is closely synchronized with other processors in the configuration. Arguments: Number - Supplies a pointer to count of the number of processors in the configuration. Return Value: None. --*/ { KSPIN_LOCK Lock; KIRQL OldIrql; PKPRCB Prcb; // // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and // wait until the number is zero. // KeInitializeSpinLock(&Lock); KeRaiseIrql(HIGH_LEVEL, &OldIrql); if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) { do { } while (*Number !=0); } // // Write the compare register, clear the count register, and zero the // performance counter for the current processor. // HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT); Prcb = KeGetCurrentPrcb(); HalpPerformanceCounter[Prcb->Number].QuadPart = 0; // // Restore IRQL to its previous value and return. // KeLowerIrql(OldIrql); return; }
VOID KiRestoreProcessorState ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function moves processor register state from the current processor context structure in the processor block to the specified trap and exception frames. Arguments: TrapFrame - Supplies a pointer to a trap frame. ExceptionFrame - Supplies a pointer to an exception frame. Return Value: None. --*/ { PKPRCB Prcb; // // Get the address of the current processor block and move the // specified register state from the processor context structure // to the specified trap and exception frames // Prcb = KeGetCurrentPrcb(); #if !defined(NT_UP) KeContextToKframes(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame, CONTEXT_FULL, KernelMode); #endif // // Restore the current processor control state. // Currently, the primary use is to allow the kernel // debugger to set hardware debug registers. Still // investigating whether this is required for MP systems. // KiRestoreProcessorControlState(&Prcb->ProcessorState); return; }
VOID HalStartProfileInterrupt ( KPROFILE_SOURCE ProfileSource ) /*++ Routine Description: This routine computes the profile count value, writes the compare register, clears the count register, and updates the performance counter. N.B. This routine must be called at PROFILE_LEVEL while holding the profile lock. Arguments: Source - Supplies the profile source. Return Value: None. --*/ { PKPRCB Prcb; ULONG PreviousCount; LARGE_INTEGER TempValue; // // Compute the profile count from the current profile interval. // TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, HalpProfileInterval); TempValue.QuadPart += ROUND_VALUE; TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL); // // Write the compare register and clear the count register. // PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart); // // Update the performance counter by adding in the previous count value. // Prcb = KeGetCurrentPrcb(); HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount; return; }
/* * @implemented */ VOID KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql) { /* Release the lock */ KxReleaseSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK /* Lower IRQL back */ KeLowerIrql(OldIrql); }
VOID HalpVerifyPrcbVersion( VOID ) /*++ Routine Description: This function verifies that the HAL matches the kernel. If there is a mismatch the HAL bugchecks the system. Arguments: None. Return Value: None. --*/ { PKPRCB Prcb; // // Verify Prcb major version number, and build options are // all conforming to this binary image // Prcb = KeGetCurrentPrcb(); #if DBG if (!(Prcb->BuildType & PRCB_BUILD_DEBUG)) { // This checked hal requires a checked kernel KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, PRCB_BUILD_DEBUG, 0); } #else if (Prcb->BuildType & PRCB_BUILD_DEBUG) { // This free hal requires a free kernel KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0); } #endif #ifndef NT_UP if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) { // This MP hal requires an MP kernel KeBugCheckEx (MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0); } #endif if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { KeBugCheckEx (MISMATCHED_HAL, 1, Prcb->MajorVersion, PRCB_MAJOR_VERSION, 0); } }
KCONTINUE_STATUS KeSwitchFrozenProcessor ( IN ULONG ProcessorNumber ) { #if !defined(NT_UP) PKPRCB TargetPrcb, CurrentPrcb; // // If Processor number is out of range, reselect current processor // if (ProcessorNumber >= (ULONG) KeNumberProcessors) { return ContinueProcessorReselected; } TargetPrcb = KiProcessorBlock[ProcessorNumber]; CurrentPrcb = KeGetCurrentPrcb(); // // Move active flag to correct processor. // CurrentPrcb->IpiFrozen &= ~FREEZE_ACTIVE; TargetPrcb->IpiFrozen |= FREEZE_ACTIVE; // // If this processor is frozen in KiFreezeTargetExecution, return to it // if (FrozenState(CurrentPrcb->IpiFrozen) == TARGET_FROZEN) { return ContinueNextProcessor; } // // This processor must be FREEZE_OWNER, wait to be reselected as the // active processor // if (FrozenState(CurrentPrcb->IpiFrozen) != FREEZE_OWNER) { return ContinueError; } while (!(CurrentPrcb->IpiFrozen & FREEZE_ACTIVE)) { KeYieldProcessor(); } #endif // !defined(NT_UP) // // Reselect this processor // return ContinueProcessorReselected; }
VOID KiSaveProcessorState ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function saves the processor state from the specified exception and trap frames, and saves the processor control state. Arguments: TrapFrame - Supplies a pointer to a trap frame. ExceptionFrame - Supplies a pointer to an exception frame. Return Value: None. --*/ { #if !defined(NT_UP) PKPRCB Prcb; // // Get the address of the current processor block, move the specified // register state from specified trap and exception frames to the current // processor context structure, and save the processor control state. // Prcb = KeGetCurrentPrcb(); Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL; KeContextFromKframes(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame); KiSaveProcessorControlState(&Prcb->ProcessorState); #else UNREFERENCED_PARAMETER(TrapFrame); UNREFERENCED_PARAMETER(ExceptionFrame); #endif return; }
/* * @implemented */ KIRQL KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) { KIRQL OldIrql; /* Raise to synch */ KeRaiseIrql(SYNCH_LEVEL, &OldIrql); /* Acquire the lock */ KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK return OldIrql; }
BOOLEAN NTAPI HalEnableSystemInterrupt( IN ULONG Vector, IN KIRQL Irql, IN KINTERRUPT_MODE InterruptMode) { IOAPIC_REDIRECTION_REGISTER ReDirReg; PKPRCB Prcb = KeGetCurrentPrcb(); UCHAR Index; ASSERT(Irql <= HIGH_LEVEL); ASSERT((IrqlToTpr(Irql) & 0xF0) == (Vector & 0xF0)); /* Get the irq for this vector */ Index = HalpVectorToIndex[Vector]; /* Check if its valid */ if (Index == 0xff) { /* Interrupt is not in use */ return FALSE; } /* Read the redirection entry */ ReDirReg = ApicReadIORedirectionEntry(Index); /* Check if the interrupt was unused */ if (ReDirReg.Vector != Vector) { ReDirReg.Vector = Vector; ReDirReg.DeliveryMode = APIC_MT_LowestPriority; ReDirReg.DestinationMode = APIC_DM_Logical; ReDirReg.Destination = 0; } /* Check if the destination is logical */ if (ReDirReg.DestinationMode == APIC_DM_Logical) { /* Set the bit for this cpu */ ReDirReg.Destination |= ApicLogicalId(Prcb->Number); } /* Set the trigger mode */ ReDirReg.TriggerMode = 1 - InterruptMode; /* Now unmask it */ ReDirReg.Mask = FALSE; /* Write back the entry */ ApicWriteIORedirectionEntry(Index, ReDirReg); return TRUE; }
VOID NTAPI KiSetProcessorType(VOID) { ULONG64 EFlags; INT Reg[4]; ULONG Stepping, Type; /* Start by assuming no CPUID data */ KeGetCurrentPrcb()->CpuID = 0; /* Save EFlags */ EFlags = __readeflags(); /* Do CPUID 1 now */ __cpuid(Reg, 1); /* * Get the Stepping and Type. The stepping contains both the * Model and the Step, while the Type contains the returned Type. * We ignore the family. * * For the stepping, we convert this: zzzzzzxy into this: x0y */ Stepping = Reg[0] & 0xF0; Stepping <<= 4; Stepping += (Reg[0] & 0xFF); Stepping &= 0xF0F; Type = Reg[0] & 0xF00; Type >>= 8; /* Save them in the PRCB */ KeGetCurrentPrcb()->CpuID = TRUE; KeGetCurrentPrcb()->CpuType = (UCHAR)Type; KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping; /* Restore EFLAGS */ __writeeflags(EFlags); }
/* * @implemented */ KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) { KIRQL OldIrql; /* Raise to dispatch */ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); /* Acquire the lock */ KxAcquireSpinLock(KeGetCurrentPrcb()->LockQueue[LockNumber].Lock); // HACK return OldIrql; }
VOID ExInitPoolLookasidePointers ( VOID ) /*++ Routine Description: This function initializes the PRCB lookaside pointers to temporary values that will be updated during phase 1 initialization. Arguments: None. Return Value: None. --*/ { ULONG Index; PGENERAL_LOOKASIDE Lookaside; PKPRCB Prcb; // // Initialize the paged and nonpaged small pool lookaside list // pointers in the PRCB to temporarily point to the global pool // lookaside lists. During phase 1 initialization per processor // lookaside lists are allocated and the pointer to these lists // are established in the PRCB of each processor. // Prcb = KeGetCurrentPrcb(); for (Index = 0; Index < POOL_SMALL_LISTS; Index += 1) { Lookaside = &ExpSmallNPagedPoolLookasideLists[Index]; ExInitializeSListHead(&Lookaside->ListHead); Prcb->PPNPagedLookasideList[Index].P = Lookaside; Prcb->PPNPagedLookasideList[Index].L = Lookaside; Lookaside = &ExpSmallPagedPoolLookasideLists[Index]; ExInitializeSListHead(&Lookaside->ListHead); Prcb->PPPagedLookasideList[Index].P = Lookaside; Prcb->PPPagedLookasideList[Index].L = Lookaside; } return; }
VOID KiSaveProcessorState ( IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame ) /*++ Routine Description: This function moves processor register state from the specified trap and exception frames to the processor context structure in the current processor block. Arguments: TrapFrame - Supplies a pointer to a trap frame. ExceptionFrame - Supplies a pointer to an exception frame. Return Value: None. --*/ { PKPRCB Prcb; // // Get the address of the current processor block and move the // specified register state from specified trap and exception // frames to the current processor context structure. // Prcb = KeGetCurrentPrcb(); Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; KeContextFromKframes(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame); // // Save the current processor control state. // Prcb->ProcessorState.SpecialRegisters.KernelDr6 = Prcb->ProcessorState.ContextFrame.Dr6; KiSaveProcessorControlState(&Prcb->ProcessorState); return; }
VOID KiPollFreezeExecution( VOID ) /*++ Routine Description: This routine is called from code that is spinning with interrupts disabled, waiting for something to happen, when there is some (possibly extremely small) chance that that thing will not happen because a system freeze has been initiated. N.B. Interrupts are disabled. Arguments: None. Return Value: None. --*/ { // // Check to see if a freeze is pending for this processor. // PKPRCB Prcb = KeGetCurrentPrcb(); if ((Prcb->RequestSummary & IPI_FREEZE) != 0) { // // Clear the freeze request and freeze this processor. // InterlockedExchangeAdd((PLONG)&Prcb->RequestSummary, -(IPI_FREEZE)); KiFreezeTargetExecution(NULL, NULL); } else { // // No freeze pending, assume this processor is spinning. // KeYieldProcessor(); } }
// ****************************************************************** // * 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); }
VOID NTAPI KiAdjustQuantumThread(IN PKTHREAD Thread) { PKPRCB Prcb = KeGetCurrentPrcb(); PKTHREAD NextThread; /* Acquire thread and PRCB lock */ KiAcquireThreadLock(Thread); KiAcquirePrcbLock(Prcb); /* Don't adjust for RT threads */ if ((Thread->Priority < LOW_REALTIME_PRIORITY) && (Thread->BasePriority < (LOW_REALTIME_PRIORITY - 2))) { /* Decrease Quantum by one and see if we've ran out */ if (--Thread->Quantum <= 0) { /* Return quantum */ Thread->Quantum = Thread->QuantumReset; /* Calculate new Priority */ Thread->Priority = KiComputeNewPriority(Thread, 1); /* Check if there's no next thread scheduled */ if (!Prcb->NextThread) { /* Select a ready thread and check if we found one */ NextThread = KiSelectReadyThread(Thread->Priority, Prcb); if (NextThread) { /* Set it on standby and switch to it */ NextThread->State = Standby; Prcb->NextThread = NextThread; } } else { /* This thread can be preempted again */ Thread->Preempted = FALSE; } } } /* Release locks */ KiReleasePrcbLock(Prcb); KiReleaseThreadLock(Thread); KiExitDispatcher(Thread->WaitIrql); }
ULONG NTAPI KiGetCpuVendor(VOID) { PKPRCB Prcb = KeGetCurrentPrcb(); INT Vendor[5]; /* Get the Vendor ID and null-terminate it */ __cpuid(Vendor, 0); /* Copy it to the PRCB and null-terminate it */ *(ULONG*)&Prcb->VendorString[0] = Vendor[1]; // ebx *(ULONG*)&Prcb->VendorString[4] = Vendor[3]; // edx *(ULONG*)&Prcb->VendorString[8] = Vendor[2]; // ecx *(ULONG*)&Prcb->VendorString[12] = 0; /* Now check the CPU Type */ if (!strcmp((PCHAR)Prcb->VendorString, CmpIntelID)) { return CPU_INTEL; } else if (!strcmp((PCHAR)Prcb->VendorString, CmpAmdID)) { return CPU_AMD; } else if (!strcmp((PCHAR)Prcb->VendorString, CmpCyrixID)) { DPRINT1("Cyrix CPUs not fully supported\n"); return 0; } else if (!strcmp((PCHAR)Prcb->VendorString, CmpTransmetaID)) { DPRINT1("Transmeta CPUs not fully supported\n"); return 0; } else if (!strcmp((PCHAR)Prcb->VendorString, CmpCentaurID)) { DPRINT1("VIA CPUs not fully supported\n"); return 0; } else if (!strcmp((PCHAR)Prcb->VendorString, CmpRiseID)) { DPRINT1("Rise CPUs not fully supported\n"); return 0; } /* Invalid CPU */ return 0; }
VOID HalpRegisterInternalBusHandlers ( VOID ) { PBUS_HANDLER Bus; if (KeGetCurrentPrcb()->Number) { // only need to do this once return ; } // // Initalize BusHandler data before registering any handlers // HalpInitBusHandler (); // // Build internal-bus 0, or system level bus // Bus = HalpAllocateBusHandler ( Internal, ConfigurationSpaceUndefined, 0, // Internal BusNumber 0 InterfaceTypeUndefined, // no parent bus 0, 0 // no bus specfic data ); Bus->GetInterruptVector = HalpGetSystemInterruptVector; Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; // // Build Isa bus 0 // Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0); Bus->GetBusData = HalpNoBusData; Bus->GetInterruptVector = HalpGetIsaInterruptVector; Bus->AdjustResourceList = HalpAdjustIsaResourceList; HalpInitOtherBuses (); }
VOID HalStopProfileInterrupt ( KPROFILE_SOURCE ProfileSource ) /*++ Routine Description: This routine sets the default count value, writes the compare register, clears the count register, and updates the performance counter. N.B. This routine must be called at PROFILE_LEVEL while holding the profile lock. Arguments: Source - Provides the profile source. Return Value: None. --*/ { PKPRCB Prcb; ULONG PreviousCount; // // Write the compare register and clear the count register. // PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT); // // Update the performance counter by adding in the previous count value. // Prcb = KeGetCurrentPrcb(); HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount; return; }
VOID NTAPI KiCheckTimerTable(IN ULARGE_INTEGER CurrentTime) { #if DBG ULONG i = 0; PLIST_ENTRY ListHead, NextEntry; KIRQL OldIrql; PKTIMER Timer; /* Raise IRQL to high and loop timers */ KeRaiseIrql(HIGH_LEVEL, &OldIrql); do { /* Loop the current list */ ListHead = &KiTimerTableListHead[i].Entry; NextEntry = ListHead->Flink; while (NextEntry != ListHead) { /* Get the timer and move to the next one */ Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); NextEntry = NextEntry->Flink; /* Check if it expired */ if (Timer->DueTime.QuadPart <= CurrentTime.QuadPart) { /* Check if the DPC was queued, but didn't run */ if (!(KeGetCurrentPrcb()->TimerRequest) && !(*((volatile PULONG*)(&KiTimerExpireDpc.DpcData)))) { /* This is bad, breakpoint! */ DPRINT1("Invalid timer state!\n"); DbgBreakPoint(); } } } /* Move to the next timer */ i++; } while(i < TIMER_TABLE_SIZE); /* Lower IRQL and return */ KeLowerIrql(OldIrql); #endif }
VOID KiSetIoMap( IN PKIPI_CONTEXT SignalDone, IN PVOID MapSource, IN PVOID MapNumber, IN PVOID Parameter3 ) /*++ Routine Description: copy the specified map into this processor's TSS. This procedure runs at IPI level. Arguments: Argument - actually a pointer to a KIPI_SET_IOPM structure ReadyFlag - pointer to flag to set once setiopm has completed Return Value: none --*/ { PKPROCESS CurrentProcess; PKPRCB Prcb; PVOID pt; // // Copy the IOPM map and load the map for the current process. // Prcb = KeGetCurrentPrcb(); pt = &(KiPcr()->TSS->IoMaps[((ULONG) MapNumber)-1].IoMap); RtlMoveMemory(pt, MapSource, IOPM_SIZE); CurrentProcess = Prcb->CurrentThread->ApcState.Process; KiPcr()->TSS->IoMapBase = CurrentProcess->IopmOffset; KiIpiSignalPacketDone(SignalDone); return; }
static VOID NTAPI DpcHandler( IN PRKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) { PKPRCB Prcb = KeGetCurrentPrcb(); ok_irql(DISPATCH_LEVEL); InterlockedIncrement(&DpcCount); ok(DeferredContext == Dpc, "DeferredContext = %p, Dpc = %p, expected equal\n", DeferredContext, Dpc); ok_eq_pointer(SystemArgument1, (PVOID)0xabc123); ok_eq_pointer(SystemArgument2, (PVOID)0x5678); /* KDPC object contents */ ok_eq_uint(Dpc->Type, DpcObject); ok_eq_uint(Dpc->Importance, DpcImportance); ok_eq_uint(Dpc->Number, 0); ok(Dpc->DpcListEntry.Blink != NULL, "\n"); ok(Dpc->DpcListEntry.Blink != &Dpc->DpcListEntry, "\n"); if (!skip(Dpc->DpcListEntry.Blink != NULL, "DpcListEntry.Blink == NULL\n")) ok_eq_pointer(Dpc->DpcListEntry.Flink, Dpc->DpcListEntry.Blink->Flink); ok(Dpc->DpcListEntry.Flink != NULL, "\n"); ok(Dpc->DpcListEntry.Flink != &Dpc->DpcListEntry, "\n"); if (!skip(Dpc->DpcListEntry.Flink != NULL, "DpcListEntry.Flink == NULL\n")) ok_eq_pointer(Dpc->DpcListEntry.Blink, Dpc->DpcListEntry.Flink->Blink); ok_eq_pointer(Dpc->DeferredRoutine, DpcHandler); ok_eq_pointer(Dpc->DeferredContext, DeferredContext); ok_eq_pointer(Dpc->SystemArgument1, SystemArgument1); ok_eq_pointer(Dpc->SystemArgument2, SystemArgument2); ok_eq_pointer(Dpc->DpcData, NULL); ok_eq_uint(Prcb->DpcRoutineActive, 1); /* this DPC is not in the list anymore, but it was at the head! */ ok_eq_pointer(Prcb->DpcData[DPC_NORMAL].DpcListHead.Flink, Dpc->DpcListEntry.Flink); ok_eq_pointer(Prcb->DpcData[DPC_NORMAL].DpcListHead.Blink, Dpc->DpcListEntry.Blink); }
VOID NTAPI KdpSymbol(IN PSTRING DllPath, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN Unload, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT ContextRecord, IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame) { BOOLEAN Enable; PKPRCB Prcb = KeGetCurrentPrcb(); /* Check if we need to do anything */ if ((PreviousMode != KernelMode) || (KdDebuggerNotPresent)) return; /* Enter the debugger */ Enable = KdEnterDebugger(TrapFrame, ExceptionFrame); /* Save the CPU Control State and save the context */ KiSaveProcessorControlState(&Prcb->ProcessorState); RtlCopyMemory(&Prcb->ProcessorState.ContextFrame, ContextRecord, sizeof(CONTEXT)); /* Report the new state */ KdpReportLoadSymbolsStateChange(DllPath, SymbolInfo, Unload, &Prcb->ProcessorState.ContextFrame); /* Restore the processor state */ RtlCopyMemory(ContextRecord, &Prcb->ProcessorState.ContextFrame, sizeof(CONTEXT)); KiRestoreProcessorControlState(&Prcb->ProcessorState); /* Exit the debugger and return */ KdExitDebugger(Enable); }
VOID KiLoadIopmOffset( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID Parameter2, IN PVOID Parameter3 ) /*++ Routine Description: Edit IopmBase of Tss to match that of currently running process. Arguments: Argument - actually a pointer to a KIPI_LOAD_IOPM_OFFSET structure ReadyFlag - Pointer to flag to be set once we are done Return Value: none --*/ { PKPROCESS CurrentProcess; PKPRCB Prcb; // // Update IOPM field in TSS from current process // Prcb = KeGetCurrentPrcb(); CurrentProcess = Prcb->CurrentThread->ApcState.Process; KiPcr()->TSS->IoMapBase = CurrentProcess->IopmOffset; KiIpiSignalPacketDone(SignalDone); return; }