/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    kernldat.c

Abstract:

    This module contains the declaration and allocation of kernel data
    structures.

Author:

    David N. Cutler (davec) 12-Mar-1989

--*/

#include "ki.h"

//
// The following data is read/write data that is grouped together for
// performance. The layout of this data is important and must not be
// changed.
//
// KiDispatcherReadyListHead - This is an array of type list entry. The
//      elements of the array are indexed by priority. Each element is a list
//      head for a set of threads that are in a ready state for the respective
//      priority. This array is used by the find next thread code to speed up
//      search for a ready thread when a thread becomes unrunnable. See also
//      KiReadySummary.
//

LIST_ENTRY KiDispatcherReadyListHead[MAXIMUM_PRIORITY];

//
// KiTimerTableListHead - This is a array of list heads that anchor the
//      individual timer lists.
//

LIST_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];

//
// KiTimeUpdateNotifyRoutine - This is the address of a callout routine
//      which is called when the runtime for a thread is updated if the
//      address is not NULL.
//

PTIME_UPDATE_NOTIFY_ROUTINE KiTimeUpdateNotifyRoutine;

//
// Public kernel data declaration and allocation.
//
// KeActiveProcessors - This is the set of processors that active in the
//      system.
//

KAFFINITY KeActiveProcessors = 0;

//
// KeBootTime - This is the absolute time when the system was booted.
//

LARGE_INTEGER KeBootTime;

//
// KeBootTimeBias - The time for which KeBootTime has ever been biased
//

ULONGLONG KeBootTimeBias;

//
// KeInterruptTimeBias - The time for which InterrupTime has ever been biased
//

ULONGLONG KeInterruptTimeBias;

//
// KeBugCheckCallbackListHead - This is the list head for registered
//      bug check callback routines.
//

LIST_ENTRY KeBugCheckCallbackListHead;
LIST_ENTRY KeBugCheckReasonCallbackListHead;

//
// KeBugCheckCallbackLock - This is the spin lock that guards the bug
//      check callback list.
//

KSPIN_LOCK KeBugCheckCallbackLock;

//
// KeDcacheFlushCount - This is the number of data cache flushes that have
//      been performed since the system was booted.
//

ULONG KeDcacheFlushCount = 0;

//
// KeIcacheFlushCount - This is the number of instruction cache flushes that
//      have been performed since the system was booted.
//

ULONG KeIcacheFlushCount = 0;

//
// KeGdiFlushUserBatch - This is the address of the GDI user batch flush
//      routine which is initialized when the win32k subsystem is loaded.
//

PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch;

//
// KeLoaderBlock - This is a pointer to the loader parameter block which is
//      constructed by the OS Loader.
//

PLOADER_PARAMETER_BLOCK KeLoaderBlock = NULL;

//
// KeMinimumIncrement - This is the minimum time between clock interrupts
//      in 100ns units that is supported by the host HAL.
//

ULONG KeMinimumIncrement;

//
// KeNumberProcessors - This is the number of processors in the configuration.
//      If is used by the ready thread and spin lock code to determine if a
//      faster algorithm can be used for the case of a single processor system.
//      The value of this variable is set when processors are initialized.
//

CCHAR KeNumberProcessors = 0;

//
// KeRegisteredProcessors - This is the maximum number of processors which
// can utilized by the system.
//

#if !defined(NT_UP)

#if DBG

ULONG KeRegisteredProcessors = 4;
ULONG KeLicensedProcessors;

#else

ULONG KeRegisteredProcessors = 2;
ULONG KeLicensedProcessors;

#endif

#endif

//
// KeProcessorArchitecture - Architecture of all processors present in system.
//      See PROCESSOR_ARCHITECTURE_ defines in ntexapi.h
//

USHORT KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;

//
// KeProcessorLevel - Architectural specific processor level of all processors
//      present in system.
//

USHORT KeProcessorLevel = 0;

//
// KeProcessorRevision - Architectural specific processor revision number that is
//      the least common denominator of all processors present in system.
//

USHORT KeProcessorRevision = 0;

//
// KeFeatureBits - Architectural specific processor features present
// on all processors.
//

ULONG KeFeatureBits = 0;

//
// KeServiceDescriptorTable - This is a table of descriptors for system
//      service providers. Each entry in the table describes the base
//      address of the dispatch table and the number of services provided.
//

KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[NUMBER_SERVICE_TABLES];
KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow[NUMBER_SERVICE_TABLES];

//
// KeThreadSwitchCounters - These counters record the number of times a
//      thread can be scheduled on the current processor, any processor,
//      or the last processor it ran on.
//

KTHREAD_SWITCH_COUNTERS KeThreadSwitchCounters;

//
// KeTimeIncrement - This is the nominal number of 100ns units that are to
//      be added to the system time at each interval timer interupt. This
//      value is set by the HAL and is used to compute the dure time for
//      timer table entries.
//

ULONG KeTimeIncrement;

//
// KeTimeSynchronization - This variable controls whether time synchronization
//      is performed using the realtime clock (TRUE) or whether it is under the
//      control of a service (FALSE).
//

BOOLEAN KeTimeSynchronization = TRUE;

//
// KeUserApcDispatcher - This is the address of the user mode APC dispatch
//      code. This address is looked up in NTDLL.DLL during initialization
//      of the system.
//

PVOID KeUserApcDispatcher;

//
// KeUserCallbackDispatcher - This is the address of the user mode callback
//      dispatch code. This address is looked up in NTDLL.DLL during
//      initialization of the system.
//

PVOID KeUserCallbackDispatcher;

//
// KeUserExceptionDispatcher - This is the address of the user mode exception
//      dispatch code. This address is looked up in NTDLL.DLL during system
//      initialization.
//

PVOID KeUserExceptionDispatcher;

//
// KeRaiseUserExceptionDispatcher - This is the address of the raise user
//      mode exception dispatch code. This address is looked up in NTDLL.DLL
//      during system initialization.
//

PVOID KeRaiseUserExceptionDispatcher;

//
// KeLargestCacheLine - This variable contains the size in bytes of
//      the largest cache line discovered during system initialization.
//      It is used to provide the recommend alignment (and padding)
//      for data that may be used heavily by more than one processor.
//      The initial value was chosen as a reasonable value to use on
//      systems where the discovery process doesn't find a value.
//

ULONG KeLargestCacheLine = 64;

//
// Private kernel data declaration and allocation.
//
// KiBugCodeMessages - Address of where the BugCode messages can be found.
//

PMESSAGE_RESOURCE_DATA KiBugCodeMessages = NULL;

//
// KiDmaIoCoherency - This determines whether the host platform supports
//      coherent DMA I/O.
//

ULONG KiDmaIoCoherency;

//
// KiMaximumSearchCount - this is the maximum number of timers entries that
//      have had to be examined to insert in the timer tree.
//

ULONG KiMaximumSearchCount = 0;

//
// KiDebugRoutine - This is the address of the kernel debugger. Initially
//      this is filled with the address of a routine that just returns. If
//      the system debugger is present in the system, then it sets this
//      location to the address of the systemn debugger's routine.
//

PKDEBUG_ROUTINE KiDebugRoutine;

//
// KiDebugSwitchRoutine - This is the address of the kernel debuggers
//      processor switch routine.  This is used on an MP system to
//      switch host processors while debugging.
//

PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine;

//
// KiDispatcherLock - This is the spin lock that guards the dispatcher
//      database.
//

extern KSPIN_LOCK KiDispatcherLock;

const CCHAR KiFindFirstSetRight[256] = {
        0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};

const CCHAR KiFindFirstSetLeft[256] = {
        0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
        4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};

//
// KiFreezeExecutionLock - This is the spin lock that guards the freezing
//      of execution.
//

extern KSPIN_LOCK KiFreezeExecutionLock;

//
// KiFreezeLockBackup - For debug builds only.  Allows kernel debugger to
//      be entered even FreezeExecutionLock is jammed.
//

extern KSPIN_LOCK KiFreezeLockBackup;

//
// KiFreezeFlag - For debug builds only.  Flags to track and signal non-
//      normal freezelock conditions.
//

ULONG KiFreezeFlag;

//
// KiSuspenState - Flag to track suspend/resume state of processors.
//

volatile ULONG KiSuspendState;

//
// KiProcessorBlock - This is an array of pointers to processor control blocks.
//      The elements of the array are indexed by processor number. Each element
//      is a pointer to the processor control block for one of the processors
//      in the configuration. This array is used by various sections of code
//      that need to effect the execution of another processor.
//

PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];

//
// KeNumberNodes - This is the number of ccNUMA nodes in the system. Logically
// an SMP system is the same as a single node ccNUMA system.
//

UCHAR KeNumberNodes = 1;

//
// KeNodeBlock - This is an array of pointers to KNODE structures. A KNODE
// structure describes the resources of a NODE in a ccNUMA system.
//

KNODE KiNode0;

#if defined(KE_MULTINODE)

PKNODE KeNodeBlock[MAXIMUM_CCNUMA_NODES];
UCHAR KeProcessNodeSeed;

#else

PKNODE KeNodeBlock[1] = { &KiNode0 };

#endif

//
// KiSwapEvent - This is the event that is used to wake up the balance set
//      thread to inswap processes, outswap processes, and to inswap kernel
//      stacks.
//

KEVENT KiSwapEvent;

//
// KiSwappingThread - This is a pointer to the swap thread object.
//

PKTHREAD KiSwappingThread;

//
// KiProcessInSwapListHead - This is the list of processes that are waiting
//      to be inswapped.
//

SINGLE_LIST_ENTRY KiProcessInSwapListHead;

//
// KiProcessOutSwapListHead - This is the list of processes that are waiting
//      to be outswapped.
//

SINGLE_LIST_ENTRY KiProcessOutSwapListHead;

//
// KiStackInSwapListHead - This is the list of threads that are waiting
//      to get their stack inswapped before they can run. Threads are
//      inserted in this list in ready thread and removed by the balance
//      set thread.
//

SINGLE_LIST_ENTRY KiStackInSwapListHead;

//
// KiProfileSourceListHead - The list of profile sources that are currently
//      active.
//

LIST_ENTRY KiProfileSourceListHead;

//
// KiProfileAlignmentFixup - Indicates whether alignment fixup profiling
//      is active.
//

BOOLEAN KiProfileAlignmentFixup;

//
// KiProfileAlignmentFixupInterval - Indicates the current alignment fixup
//      profiling interval.
//

ULONG KiProfileAlignmentFixupInterval;

//
// KiProfileAlignmentFixupCount - Indicates the current alignment fixup
//      count.
//

ULONG KiProfileAlignmentFixupCount;

//
// KiProfileInterval - The profile interval in 100ns units.
//

#if !defined(_IA64_)

ULONG KiProfileInterval = DEFAULT_PROFILE_INTERVAL;

#endif // !_IA64_

//
// KiProfileListHead - This is the list head for the profile list.
//

LIST_ENTRY KiProfileListHead;

//
// KiProfileLock - This is the spin lock that guards the profile list.
//

extern KSPIN_LOCK KiProfileLock;

//
// KiTimerExpireDpc - This is the Deferred Procedure Call (DPC) object that
//      is used to process the timer queue when a timer has expired.
//

KDPC KiTimerExpireDpc;

//
// KiTimeIncrementReciprocal - This is the reciprocal fraction of the time
//      increment value that is specified by the HAL when the system is
//      booted.
//

LARGE_INTEGER KiTimeIncrementReciprocal;

//
// KiTimeIncrementShiftCount - This is the shift count that corresponds to
//      the time increment reciprocal value.
//

CCHAR KiTimeIncrementShiftCount;

//
// KiWaitListHead - This is a list of threads that are waiting with a
//      resident kernel stack and are elligible to have their stack
//      swapped.
//

LIST_ENTRY KiWaitListHead;

//
// KiIpiCounts - This is the instrumentation counters for IPI requests. Each
//      processor has its own set.  Intstrumentation build only.
//

#if NT_INST

KIPI_COUNTS KiIpiCounts[MAXIMUM_PROCESSORS];

#endif  // NT_INST

//
// KxUnexpectedInterrupt - This is the interrupt object that is used to
//      populate the interrupt vector table for interrupt that are not
//      connected to any interrupt.
//

#if defined(_IA64_)

KINTERRUPT KxUnexpectedInterrupt;

#endif

//
// Performance data declaration and allocation.
//
// KiFlushSingleCallData - This is the call performance data for the kernel
//      flush single TB function.
//

#if defined(_COLLECT_FLUSH_SINGLE_CALLDATA_)

CALL_PERFORMANCE_DATA KiFlushSingleCallData;

#endif

//
// KiSetEventCallData - This is the call performance data for the kernel
//      set event function.
//

#if defined(_COLLECT_SET_EVENT_CALLDATA_)

CALL_PERFORMANCE_DATA KiSetEventCallData;

#endif

//
// KiWaitSingleCallData - This is the call performance data for the kernel
//      wait for single object function.
//

#if defined(_COLLECT_WAIT_SINGLE_CALLDATA_)

CALL_PERFORMANCE_DATA KiWaitSingleCallData;

#endif

//
// KiEnableTimerWatchdog - Flag to enable/disable timer latency watchdog.
//

#if (DBG)
ULONG KiEnableTimerWatchdog = 1;
#else
ULONG KiEnableTimerWatchdog = 0;
#endif