mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 02:25:17 +00:00
- Multiple changes to low-level Kernel initalization sequence to bring it a bit closer to Windows.
- Main difference is new CPU detection algorithms for ID, cache, etc, as well as using KF_ Kernel Feature bits instead of x86 CPU features (For portability). - Also many many other cleanups and re-sequencing. svn path=/trunk/; revision=23852
This commit is contained in:
parent
3c411c196d
commit
369f93b984
15 changed files with 979 additions and 549 deletions
|
@ -1046,26 +1046,27 @@ typedef struct _KDEVICE_QUEUE_ENTRY {
|
|||
#define LOCK_QUEUE_TIMER_LOCK_SHIFT 4
|
||||
#define LOCK_QUEUE_TIMER_TABLE_LOCKS (1 << (8 - LOCK_QUEUE_TIMER_LOCK_SHIFT))
|
||||
|
||||
typedef enum _KSPIN_LOCK_QUEUE_NUMBER {
|
||||
LockQueueDispatcherLock,
|
||||
LockQueueContextSwapLock,
|
||||
LockQueuePfnLock,
|
||||
LockQueueSystemSpaceLock,
|
||||
LockQueueVacbLock,
|
||||
LockQueueMasterLock,
|
||||
LockQueueNonPagedPoolLock,
|
||||
LockQueueIoCancelLock,
|
||||
LockQueueWorkQueueLock,
|
||||
LockQueueIoVpbLock,
|
||||
LockQueueIoDatabaseLock,
|
||||
LockQueueIoCompletionLock,
|
||||
LockQueueNtfsStructLock,
|
||||
LockQueueAfdWorkQueueLock,
|
||||
LockQueueBcbLock,
|
||||
LockQueueMmNonPagedPoolLock,
|
||||
LockQueueUnusedSpare16,
|
||||
LockQueueTimerTableLock,
|
||||
LockQueueMaximumLock = LockQueueTimerTableLock + LOCK_QUEUE_TIMER_TABLE_LOCKS
|
||||
typedef enum _KSPIN_LOCK_QUEUE_NUMBER
|
||||
{
|
||||
LockQueueDispatcherLock,
|
||||
LockQueueExpansionLock,
|
||||
LockQueuePfnLock,
|
||||
LockQueueSystemSpaceLock,
|
||||
LockQueueVacbLock,
|
||||
LockQueueMasterLock,
|
||||
LockQueueNonPagedPoolLock,
|
||||
LockQueueIoCancelLock,
|
||||
LockQueueWorkQueueLock,
|
||||
LockQueueIoVpbLock,
|
||||
LockQueueIoDatabaseLock,
|
||||
LockQueueIoCompletionLock,
|
||||
LockQueueNtfsStructLock,
|
||||
LockQueueAfdWorkQueueLock,
|
||||
LockQueueBcbLock,
|
||||
LockQueueMmNonPagedPoolLock,
|
||||
LockQueueUnusedSpare16,
|
||||
LockQueueTimerTableLock,
|
||||
LockQueueMaximumLock = LockQueueTimerTableLock + LOCK_QUEUE_TIMER_TABLE_LOCKS
|
||||
} KSPIN_LOCK_QUEUE_NUMBER, *PKSPIN_LOCK_QUEUE_NUMBER;
|
||||
|
||||
typedef struct _KSPIN_LOCK_QUEUE {
|
||||
|
|
|
@ -62,7 +62,22 @@ Author:
|
|||
//
|
||||
// Kernel Feature Bits
|
||||
//
|
||||
#define KF_V86_VIS 0x00000001
|
||||
#define KF_RDTSC 0x00000002
|
||||
#define KF_CR4 0x00000004
|
||||
#define KF_CMOV 0x00000008
|
||||
#define KF_GLOBAL_PAGE 0x00000010
|
||||
#define KF_LARGE_PAGE 0x00000020
|
||||
#define KF_MTRR 0x00000040
|
||||
#define KF_CMPXCHG8B 0x00000080
|
||||
#define KF_MMX 0x00000100
|
||||
#define KF_WORKING_PTE 0x00000200
|
||||
#define KF_PAT 0x00000400
|
||||
#define KF_FXSR 0x00000800
|
||||
#define KF_FAST_SYSCALL 0x00001000
|
||||
#define KF_XMMI 0x00002000
|
||||
#define KF_3DNOW 0x00004000
|
||||
#define KF_AMDK6MTRR 0x00008000
|
||||
|
||||
//
|
||||
// KPCR Access for non-IA64 builds
|
||||
|
|
|
@ -25,11 +25,18 @@
|
|||
// - Use Object Type Mutex/Lock.
|
||||
//
|
||||
// Ke:
|
||||
// - Get rid of KiRosPrintAddress and use KiDumpParameterImages instead.
|
||||
// - Sanitize some context fields during conversions.
|
||||
// - Implement stack fault and segment fault handlers.
|
||||
// - Add DR macro/save and VM macro/save.
|
||||
// - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion.
|
||||
//
|
||||
// - FIXES:
|
||||
// * Get rid of KiRosPrintAddress and use KiDumpParameterImages instead.
|
||||
// * Sanitize some context fields during conversions.
|
||||
// * Implement stack fault and segment fault handlers.
|
||||
// * Add DR macro/save and VM macro/save.
|
||||
// * Make boot process more NT-like.
|
||||
// - FEATURES:
|
||||
// * Use Queued Spinlocks for scheduling and dispatching.
|
||||
// * New optimized table-based tick-hashed timer implementation.
|
||||
// * New Thread Scheduler based on XP.
|
||||
// * Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion.
|
||||
//
|
||||
// Ex:
|
||||
// - Use pushlocks for handle implementation.
|
||||
|
|
|
@ -26,21 +26,6 @@
|
|||
#define X86_CR4_OSFXSR 0x00000200 /* enable FXSAVE/FXRSTOR instructions */
|
||||
#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable #XF exception */
|
||||
|
||||
#define X86_FEATURE_VME 0x00000002 /* Virtual 8086 Extensions are present */
|
||||
#define X86_FEATURE_TSC 0x00000010 /* time stamp counters are present */
|
||||
#define X86_FEATURE_PAE 0x00000040 /* physical address extension is present */
|
||||
#define X86_FEATURE_CX8 0x00000100 /* CMPXCHG8B instruction present */
|
||||
#define X86_FEATURE_SYSCALL 0x00000800 /* SYSCALL/SYSRET support present */
|
||||
#define X86_FEATURE_PGE 0x00002000 /* Page Global Enable */
|
||||
#define X86_FEATURE_MMX 0x00800000 /* MMX extension present */
|
||||
#define X86_FEATURE_FXSR 0x01000000 /* FXSAVE/FXRSTOR instructions present */
|
||||
#define X86_FEATURE_SSE 0x02000000 /* SSE extension present */
|
||||
#define X86_FEATURE_SSE2 0x04000000 /* SSE2 extension present */
|
||||
#define X86_FEATURE_HT 0x10000000 /* Hyper-Threading present */
|
||||
|
||||
#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */
|
||||
#define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */
|
||||
|
||||
#define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */
|
||||
|
||||
#define FRAME_EDITED 0xFFF8
|
||||
|
@ -64,6 +49,29 @@ VOID
|
|||
Ki386InitializeLdt(VOID);
|
||||
VOID
|
||||
Ki386SetProcessorFeatures(VOID);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSetCR0Bits(VOID);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiGetCacheInformation(VOID);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KiIsNpxPresent(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSetProcessorType(VOID);
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
KiGetFeatureBits(VOID);
|
||||
|
||||
ULONG KeAllocateGdtSelector(ULONG Desc[2]);
|
||||
VOID KeFreeGdtSelector(ULONG Entry);
|
||||
VOID
|
||||
|
|
|
@ -70,6 +70,12 @@ extern ULONG_PTR KERNEL_BASE;
|
|||
extern ULONG KeI386NpxPresent;
|
||||
extern ULONG KeI386XMMIPresent;
|
||||
extern ULONG KeI386FxsrPresent;
|
||||
extern ULONG KeI386CpuType;
|
||||
extern ULONG KeI386CpuStep;
|
||||
extern ULONG KeProcessorArchitecture;
|
||||
extern ULONG KeProcessorLevel;
|
||||
extern ULONG KeProcessorRevision;
|
||||
extern ULONG KeFeatureBits;
|
||||
extern PKNODE KeNodeBlock[1];
|
||||
extern UCHAR KeNumberNodes;
|
||||
extern UCHAR KeProcessNodeSeed;
|
||||
|
@ -84,6 +90,10 @@ extern ULONG KeI386EFlagsOrMaskV86;
|
|||
extern BOOLEAN KeI386VirtualIntExtensions;
|
||||
extern KIDTENTRY KiIdt[];
|
||||
extern FAST_MUTEX KernelAddressSpaceLock;
|
||||
extern ULONG KiMaximumDpcQueueDepth;
|
||||
extern ULONG KiMinimumDpcRate;
|
||||
extern ULONG KiAdjustDpcThreshold;
|
||||
extern ULONG KiIdealDpcRate;
|
||||
|
||||
/* MACROS *************************************************************************/
|
||||
|
||||
|
@ -583,10 +593,6 @@ VOID
|
|||
NTAPI
|
||||
KeInitTimer(VOID);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeInitDpc(struct _KPRCB* Prcb);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeInitDispatcher(VOID);
|
||||
|
@ -606,8 +612,7 @@ Phase1Initialization(PVOID Context);
|
|||
VOID
|
||||
NTAPI
|
||||
KeInit1(
|
||||
PCHAR CommandLine,
|
||||
PULONG LastKernelAddress
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
|
@ -689,7 +694,7 @@ KeBugCheckWithTf(
|
|||
);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
NTAPI
|
||||
KeFlushCurrentTb(VOID);
|
||||
|
||||
VOID
|
||||
|
|
|
@ -12,10 +12,20 @@ PoInit(
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState);
|
||||
PopSetSystemPowerState(
|
||||
SYSTEM_POWER_STATE PowerState
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PopCleanupPowerState(IN PPOWER_STATE PowerState);
|
||||
PopCleanupPowerState(
|
||||
IN PPOWER_STATE PowerState
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PoInitializePrcb(
|
||||
IN PKPRCB Prcb
|
||||
);
|
||||
|
||||
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_PO_H */
|
||||
|
|
|
@ -36,28 +36,6 @@ ULONG KiIdealDpcRate = 20;
|
|||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/*
|
||||
* FUNCTION: Initialize DPC handling
|
||||
*/
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
NTAPI
|
||||
KeInitDpc(PKPRCB Prcb)
|
||||
{
|
||||
InitializeListHead(&Prcb->DpcData[0].DpcListHead);
|
||||
#if 0
|
||||
/*
|
||||
* FIXME:
|
||||
* Prcb->DpcEvent is a NULL pointer.
|
||||
*/
|
||||
KeInitializeEvent(Prcb->DpcEvent, 0, 0);
|
||||
#endif
|
||||
KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
|
||||
Prcb->MinimumDpcRate = KiMinimumDpcRate;
|
||||
Prcb->DpcData[0].DpcQueueDepth = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel
|
||||
* FILE: ntoskrnl/ke/i386/cpu.S
|
||||
* PURPOSE: Handles CPU-centric operations: TLB Flushes, Breakpoints, FPU
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <asm.h>
|
||||
.intel_syntax noprefix
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
.globl _KeFlushCurrentTb@0
|
||||
.func KeFlushCurrentTb@0
|
||||
_KeFlushCurrentTb@0:
|
||||
|
||||
/* Check for global page support */
|
||||
test byte ptr [_Ke386GlobalPagesEnabled], 0xff
|
||||
jz .L1
|
||||
|
||||
/* Modifying the PSE, PGE or PAE Flag in CR4 causes the TLB to be flushed */
|
||||
mov eax, cr4
|
||||
and eax, ~CR4_PGE
|
||||
mov cr4, eax
|
||||
or eax, CR4_PGE
|
||||
mov cr4, eax
|
||||
ret
|
||||
|
||||
.L1:
|
||||
/* the old way ... */
|
||||
mov eax, cr3
|
||||
mov cr3, eax
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
561
reactos/ntoskrnl/ke/i386/cpu.c
Normal file
561
reactos/ntoskrnl/ke/i386/cpu.c
Normal file
|
@ -0,0 +1,561 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ke/i386/cpu.c
|
||||
* PURPOSE: Routines for CPU-level support
|
||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FIXME: Local EFLAGS defines not used anywhere else */
|
||||
#define EFLAGS_IOPL 0x3000
|
||||
#define EFLAGS_NF 0x4000
|
||||
#define EFLAGS_RF 0x10000
|
||||
#define EFLAGS_ID 0x200000
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
ULONG KeI386CpuType;
|
||||
ULONG KeI386CpuStep;
|
||||
ULONG KeProcessorArchitecture;
|
||||
ULONG KeProcessorLevel;
|
||||
ULONG KeProcessorRevision;
|
||||
ULONG KeFeatureBits;
|
||||
ULONG KiFastSystemCallDisable = 1;
|
||||
ULONG KeI386NpxPresent = 0;
|
||||
ULONG MxcsrFeatureMask = 0;
|
||||
ULONG KeI386XMMIPresent = 0;
|
||||
ULONG KeI386FxsrPresent = 0;
|
||||
ULONG Ke386Pae = FALSE;
|
||||
ULONG Ke386GlobalPagesEnabled = FALSE;
|
||||
ULONG Ke386NoExecute = FALSE;
|
||||
BOOLEAN KiI386PentiumLockErrataPresent;
|
||||
|
||||
CHAR CmpIntelID[] = "GenuineIntel";
|
||||
CHAR CmpAmdID[] = "AuthenticAMD";
|
||||
CHAR CmpCyrixID[] = "CyrixInstead";
|
||||
CHAR CmpTransmetaID[] = "GenuineTMx86";
|
||||
CHAR CmpCentaurID[] = "CentaurHauls";
|
||||
CHAR CmpRiseID[] = "RiseRiseRise";
|
||||
|
||||
/* SUPPORT ROUTINES FOR MSVC COMPATIBILITY ***********************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CPUID(IN ULONG CpuInfo[4],
|
||||
IN ULONG InfoType)
|
||||
{
|
||||
Ki386Cpuid(InfoType, &CpuInfo[0], &CpuInfo[1], &CpuInfo[2], &CpuInfo[3]);
|
||||
}
|
||||
|
||||
VOID
|
||||
WRMSR(IN ULONG Register,
|
||||
IN LONGLONG Value)
|
||||
{
|
||||
LARGE_INTEGER LargeVal;
|
||||
LargeVal.QuadPart = Value;
|
||||
Ke386Wrmsr(Register, LargeVal.HighPart, LargeVal.LowPart);
|
||||
}
|
||||
|
||||
LONGLONG
|
||||
RDMSR(IN ULONG Register)
|
||||
{
|
||||
LARGE_INTEGER LargeVal;
|
||||
Ke386Rdmsr(Register, LargeVal.HighPart, LargeVal.LowPart);
|
||||
return LargeVal.QuadPart;
|
||||
}
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSetProcessorType(VOID)
|
||||
{
|
||||
ULONG EFlags, NewEFlags;
|
||||
ULONG Reg[4];
|
||||
ULONG Stepping, Type;
|
||||
|
||||
/* Start by assuming no CPUID data */
|
||||
KeGetCurrentPrcb()->CpuID = 0;
|
||||
|
||||
/* Save EFlags */
|
||||
Ke386SaveFlags(EFlags);
|
||||
|
||||
/* XOR out the ID bit and update EFlags */
|
||||
NewEFlags = EFlags ^ EFLAGS_ID;
|
||||
Ke386RestoreFlags(NewEFlags);
|
||||
|
||||
/* Get them back and see if they were modified */
|
||||
Ke386SaveFlags(NewEFlags);
|
||||
if (NewEFlags != EFlags)
|
||||
{
|
||||
/* The modification worked, so CPUID exists. Set the ID Bit again. */
|
||||
EFlags |= EFLAGS_ID;
|
||||
Ke386RestoreFlags(EFlags);
|
||||
|
||||
/* Peform CPUID 0 to see if CPUID 1 is supported */
|
||||
CPUID(Reg, 0);
|
||||
if (Reg[0] > 0)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("CPUID Support lacking\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("CPUID Support lacking\n");
|
||||
}
|
||||
|
||||
/* Restore EFLAGS */
|
||||
Ke386RestoreFlags(EFlags);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
KiGetCpuVendor(VOID)
|
||||
{
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
ULONG Vendor[5];
|
||||
|
||||
/* Assume no Vendor ID and fail if no CPUID Support. */
|
||||
Prcb->VendorString[0] = 0;
|
||||
if (!Prcb->CpuID) return 0;
|
||||
|
||||
/* Get the Vendor ID and null-terminate it */
|
||||
CPUID(Vendor, 0);
|
||||
Vendor[4] = 0;
|
||||
|
||||
/* Re-arrange vendor string */
|
||||
Vendor[5] = Vendor[2];
|
||||
Vendor[2] = Vendor[3];
|
||||
Vendor[3] = Vendor[5];
|
||||
|
||||
/* Copy it to the PRCB and null-terminate it again */
|
||||
RtlCopyMemory(Prcb->VendorString,
|
||||
&Vendor[1],
|
||||
sizeof(Prcb->VendorString) - sizeof(CHAR));
|
||||
Prcb->VendorString[sizeof(Prcb->VendorString) - sizeof(CHAR)] = ANSI_NULL;
|
||||
|
||||
/* Now check the CPU Type */
|
||||
if (!strcmp(Prcb->VendorString, CmpIntelID))
|
||||
{
|
||||
return CPU_INTEL;
|
||||
}
|
||||
else if (!strcmp(Prcb->VendorString, CmpAmdID))
|
||||
{
|
||||
return CPU_AMD;
|
||||
}
|
||||
else if (!strcmp(Prcb->VendorString, CmpCyrixID))
|
||||
{
|
||||
DPRINT1("Cyrix CPUs not fully supported\n");
|
||||
return 0;
|
||||
}
|
||||
else if (!strcmp(Prcb->VendorString, CmpTransmetaID))
|
||||
{
|
||||
DPRINT1("Transmeta CPUs not fully supported\n");
|
||||
return 0;
|
||||
}
|
||||
else if (!strcmp(Prcb->VendorString, CmpCentaurID))
|
||||
{
|
||||
DPRINT1("VIA CPUs not fully supported\n");
|
||||
return 0;
|
||||
}
|
||||
else if (!strcmp(Prcb->VendorString, CmpRiseID))
|
||||
{
|
||||
DPRINT1("Rise CPUs not fully supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Invalid CPU */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
KiGetFeatureBits(VOID)
|
||||
{
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
ULONG Vendor;
|
||||
ULONG FeatureBits = KF_WORKING_PTE;
|
||||
ULONG Reg[4];
|
||||
BOOLEAN ExtendedCPUID = TRUE;
|
||||
ULONG CpuFeatures = 0;
|
||||
|
||||
/* Get the Vendor ID */
|
||||
Vendor = KiGetCpuVendor();
|
||||
|
||||
/* Make sure we got a valid vendor ID at least. */
|
||||
if (!Vendor) return FeatureBits;
|
||||
|
||||
/* Get the CPUID Info. Features are in Reg[3]. */
|
||||
CPUID(Reg, 1);
|
||||
|
||||
/* Check for AMD CPU */
|
||||
if (Vendor == CPU_AMD)
|
||||
{
|
||||
/* Check if this is a K5 or higher. */
|
||||
if ((Reg[0] & 0x0F00) >= 0x0500)
|
||||
{
|
||||
/* Check if this is a K5 specifically. */
|
||||
if ((Reg[0] & 0x0F00) == 0x0500)
|
||||
{
|
||||
/* Get the Model Number */
|
||||
switch (Reg[0] & 0x00F0)
|
||||
{
|
||||
/* Check if this is the Model 1 */
|
||||
case 0x0010:
|
||||
|
||||
/* Check if this is Step 0 or 1. They don't support PGE */
|
||||
if ((Reg[0] & 0x000F) > 0x03) break;
|
||||
|
||||
case 0x0000:
|
||||
|
||||
/* Model 0 doesn't support PGE at all. */
|
||||
Reg[3] &= ~0x2000;
|
||||
break;
|
||||
|
||||
case 0x0080:
|
||||
|
||||
/* K6-2, Step 8 and over have support for MTRR. */
|
||||
if ((Reg[0] & 0x000F) >= 0x8) FeatureBits |= KF_AMDK6MTRR;
|
||||
break;
|
||||
|
||||
case 0x0090:
|
||||
|
||||
/* As does the K6-3 */
|
||||
FeatureBits |= KF_AMDK6MTRR;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Familes below 5 don't support PGE, PSE or CMOV at all */
|
||||
Reg[3] &= ~(0x08 | 0x2000 | 0x8000);
|
||||
|
||||
/* They also don't support advanced CPUID functions. */
|
||||
ExtendedCPUID = FALSE;
|
||||
}
|
||||
|
||||
/* Set the current features */
|
||||
CpuFeatures = Reg[3];
|
||||
}
|
||||
|
||||
/* Now check if this is Intel */
|
||||
if (Vendor == CPU_INTEL)
|
||||
{
|
||||
/* Check if it's a P6 */
|
||||
if (Prcb->CpuType == 6)
|
||||
{
|
||||
/* Perform the special sequence to get the MicroCode Signature */
|
||||
WRMSR(0x8B, 0);
|
||||
CPUID(Reg, 1);
|
||||
Prcb->UpdateSignature.QuadPart = RDMSR(0x8B);
|
||||
}
|
||||
else if (Prcb->CpuType == 5)
|
||||
{
|
||||
/* On P5, enable workaround for the LOCK errata. */
|
||||
KiI386PentiumLockErrataPresent = TRUE;
|
||||
}
|
||||
|
||||
/* Check for broken P6 with bad SMP PTE implementation */
|
||||
if (((Reg[0] & 0x0FF0) == 0x0610 && (Reg[0] & 0x000F) <= 0x9) ||
|
||||
((Reg[0] & 0x0FF0) == 0x0630 && (Reg[0] & 0x000F) <= 0x4))
|
||||
{
|
||||
/* Remove support for correct PTE support. */
|
||||
FeatureBits &= ~KF_WORKING_PTE;
|
||||
}
|
||||
|
||||
/* Set the current features */
|
||||
CpuFeatures = Reg[3];
|
||||
}
|
||||
|
||||
/* Convert all CPUID Feature bits into our format */
|
||||
if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4;
|
||||
if (CpuFeatures & 0x00000008) FeatureBits |= KF_LARGE_PAGE | KF_CR4;
|
||||
if (CpuFeatures & 0x00000010) FeatureBits |= KF_RDTSC;
|
||||
if (CpuFeatures & 0x00000100) FeatureBits |= KF_CMPXCHG8B;
|
||||
if (CpuFeatures & 0x00000800) FeatureBits |= KF_FAST_SYSCALL;
|
||||
if (CpuFeatures & 0x00001000) FeatureBits |= KF_MTRR;
|
||||
if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
|
||||
if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;
|
||||
if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;
|
||||
if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
|
||||
if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
|
||||
if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
|
||||
|
||||
/* Check if CPUID 0x80000000 is supported */
|
||||
if (ExtendedCPUID)
|
||||
{
|
||||
/* Do the call */
|
||||
CPUID(Reg, 0x80000000);
|
||||
if ((Reg[0] & 0xffffff00) == 0x80000000)
|
||||
{
|
||||
/* Check if CPUID 0x80000001 is supported */
|
||||
if (Reg[0] >= 0x80000001)
|
||||
{
|
||||
/* Check which extended features are available. */
|
||||
CPUID(Reg, 0x80000001);
|
||||
|
||||
/* Now handle each features for each CPU Vendor */
|
||||
switch (Vendor)
|
||||
{
|
||||
case CPU_AMD:
|
||||
if (Reg[3] & 0x80000000) FeatureBits |= KF_3DNOW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the Feature Bits */
|
||||
return FeatureBits;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiGetCacheInformation(VOID)
|
||||
{
|
||||
PKIPCR Pcr = (PKIPCR)KeGetPcr();
|
||||
ULONG Vendor;
|
||||
ULONG Data[4];
|
||||
ULONG CacheRequests = 0, i;
|
||||
ULONG CurrentRegister;
|
||||
UCHAR RegisterByte;
|
||||
BOOLEAN FirstPass = TRUE;
|
||||
|
||||
/* Set default L2 size */
|
||||
Pcr->SecondLevelCacheSize = 0;
|
||||
|
||||
/* Get the Vendor ID and make sure we support CPUID */
|
||||
Vendor = KiGetCpuVendor();
|
||||
if (!Vendor) return;
|
||||
|
||||
/* Check the Vendor ID */
|
||||
switch (Vendor)
|
||||
{
|
||||
/* Handle Intel case */
|
||||
case CPU_INTEL:
|
||||
|
||||
/*Check if we support CPUID 2 */
|
||||
CPUID(Data, 0);
|
||||
if (Data[0] >= 2)
|
||||
{
|
||||
/* We need to loop for the number of times CPUID will tell us to */
|
||||
do
|
||||
{
|
||||
/* Do the CPUID call */
|
||||
CPUID(Data, 2);
|
||||
|
||||
/* Check if it was the first call */
|
||||
if (FirstPass)
|
||||
{
|
||||
/*
|
||||
* The number of times to loop is the first byte. Read
|
||||
* it and then destroy it so we don't get confused.
|
||||
*/
|
||||
CacheRequests = Data[0] & 0xFF;
|
||||
Data[0] &= 0xFFFFFF00;
|
||||
|
||||
/* Don't go over this again */
|
||||
FirstPass = FALSE;
|
||||
}
|
||||
|
||||
/* Loop all 4 registers */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
/* Get the current register */
|
||||
CurrentRegister = Data[i];
|
||||
|
||||
/*
|
||||
* If the upper bit is set, then this register should
|
||||
* be skipped.
|
||||
*/
|
||||
if (CurrentRegister & 0x80000000) continue;
|
||||
|
||||
/* Keep looping for every byte inside this register */
|
||||
while (CurrentRegister)
|
||||
{
|
||||
/* Read a byte, skip a byte. */
|
||||
RegisterByte = (UCHAR)(CurrentRegister & 0xFF);
|
||||
CurrentRegister >>= 8;
|
||||
if (!RegisterByte) continue;
|
||||
|
||||
/*
|
||||
* Valid values are from 0x40 (0 bytes) to 0x49
|
||||
* (32MB), or from 0x80 to 0x89 (same size but
|
||||
* 8-way associative.
|
||||
*/
|
||||
if (((RegisterByte > 0x40) &&
|
||||
(RegisterByte <= 0x49)) ||
|
||||
((RegisterByte > 0x80) &&
|
||||
(RegisterByte <= 0x89)))
|
||||
{
|
||||
/* Mask out only the first nibble */
|
||||
RegisterByte &= 0x0F;
|
||||
|
||||
/* Set the L2 Cache Size */
|
||||
Pcr->SecondLevelCacheSize = 0x10000 <<
|
||||
RegisterByte;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (--CacheRequests);
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_AMD:
|
||||
|
||||
/* FIXME */
|
||||
DPRINT1("Not handling AMD caches yet\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSetCR0Bits(VOID)
|
||||
{
|
||||
ULONG Cr0;
|
||||
|
||||
/* Save current CR0 */
|
||||
Cr0 = Ke386GetCr0();
|
||||
|
||||
/* If this is a 486, enable Write-Protection */
|
||||
if (KeGetCurrentPrcb()->CpuType > 3) Cr0 |= CR0_WP;
|
||||
|
||||
/* Set new Cr0 */
|
||||
Ke386SetCr0(Cr0);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
Ki386SetProcessorFeatures(VOID)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName =
|
||||
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Kernel");
|
||||
UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FastSystemCallDisable");
|
||||
HANDLE KeyHandle;
|
||||
ULONG ResultLength;
|
||||
struct
|
||||
{
|
||||
KEY_VALUE_PARTIAL_INFORMATION Info;
|
||||
UCHAR Buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
|
||||
Data[0]) + sizeof(ULONG)];
|
||||
} ValueData;
|
||||
NTSTATUS Status;
|
||||
ULONG FastSystemCallDisable = 0;
|
||||
|
||||
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
|
||||
(KeFeatureBits & KF_CMPXCHG8B) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
|
||||
(KeFeatureBits & KF_MMX) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
|
||||
(KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] =
|
||||
(KeFeatureBits & KF_RDTSC) ? TRUE : FALSE;
|
||||
|
||||
/* Does the CPU Support Fast System Call? */
|
||||
if (KeFeatureBits & KF_FAST_SYSCALL) {
|
||||
|
||||
/* FIXME: Check for Family == 6, Model < 3 and Stepping < 3 and disable */
|
||||
|
||||
/* Make sure it's not disabled in registry */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenKey(&KeyHandle,
|
||||
KEY_QUERY_VALUE,
|
||||
&ObjectAttributes);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
/* Read the Value then Close the Key */
|
||||
Status = ZwQueryValueKey(KeyHandle,
|
||||
&ValueName,
|
||||
KeyValuePartialInformation,
|
||||
&ValueData,
|
||||
sizeof(ValueData),
|
||||
&ResultLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (ResultLength == sizeof(ValueData) &&
|
||||
ValueData.Info.Type == REG_DWORD)
|
||||
{
|
||||
FastSystemCallDisable = *(PULONG)ValueData.Info.Data != 0;
|
||||
}
|
||||
|
||||
ZwClose(KeyHandle);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Disable SYSENTER/SYSEXIT, because the CPU doesn't support it */
|
||||
FastSystemCallDisable = 1;
|
||||
|
||||
}
|
||||
|
||||
if (FastSystemCallDisable) {
|
||||
/* Use INT2E */
|
||||
const unsigned char Entry[7] = {0x8D, 0x54, 0x24, 0x08, /* lea 0x8(%esp),%edx */
|
||||
0xCD, 0x2E, /* int 0x2e */
|
||||
0xC3}; /* ret */
|
||||
memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry));
|
||||
} else {
|
||||
/* Use SYSENTER */
|
||||
const unsigned char Entry[5] = {0x8B, 0xD4, /* movl %esp,%edx */
|
||||
0x0F, 0x34, /* sysenter */
|
||||
0xC3}; /* ret */
|
||||
memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry));
|
||||
/* Enable SYSENTER/SYSEXIT */
|
||||
KiFastSystemCallDisable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeFlushCurrentTb(VOID)
|
||||
{
|
||||
/* Flush the TLB by resetting CR3 */
|
||||
_Ke386SetCr(3, _Ke386GetCr(3));
|
||||
}
|
||||
|
|
@ -21,54 +21,214 @@ PKNODE KeNodeBlock[1];
|
|||
UCHAR KeNumberNodes = 1;
|
||||
UCHAR KeProcessNodeSeed;
|
||||
ULONG KiPcrInitDone = 0;
|
||||
static ULONG PcrsAllocated = 0;
|
||||
static ULONG Ke386CpuidFlags2, Ke386CpuidExFlags, Ke386CpuidExMisc;
|
||||
ULONG Ke386CacheAlignment;
|
||||
CHAR Ke386CpuidModel[49] = {0,};
|
||||
ULONG Ke386L1CacheSize;
|
||||
BOOLEAN Ke386NoExecute = FALSE;
|
||||
BOOLEAN Ke386Pae = FALSE;
|
||||
BOOLEAN Ke386GlobalPagesEnabled = FALSE;
|
||||
ULONG KiFastSystemCallDisable = 1;
|
||||
ULONG KeI386NpxPresent = 0;
|
||||
ULONG MxcsrFeatureMask = 0;
|
||||
ULONG KeI386XMMIPresent = 0;
|
||||
ULONG KeI386FxsrPresent = 0;
|
||||
extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
|
||||
extern ULONG IdleProcessorMask;
|
||||
extern KIDTENTRY KiIdt[256];
|
||||
static VOID INIT_FUNCTION Ki386GetCpuId(VOID);
|
||||
extern ULONG Ke386GlobalPagesEnabled;
|
||||
|
||||
/* System-defined Spinlocks */
|
||||
KSPIN_LOCK KiDispatcherLock;
|
||||
KSPIN_LOCK MmPfnLock;
|
||||
KSPIN_LOCK MmSystemSpaceLock;
|
||||
KSPIN_LOCK CcBcbSpinLock;
|
||||
KSPIN_LOCK CcMasterSpinLock;
|
||||
KSPIN_LOCK CcVacbSpinLock;
|
||||
KSPIN_LOCK CcWorkQueueSpinLock;
|
||||
KSPIN_LOCK NonPagedPoolLock;
|
||||
KSPIN_LOCK MmNonPagedPoolLock;
|
||||
KSPIN_LOCK IopCancelSpinLock;
|
||||
KSPIN_LOCK IopVpbSpinLock;
|
||||
KSPIN_LOCK IopDatabaseLock;
|
||||
KSPIN_LOCK IopCompletionLock;
|
||||
KSPIN_LOCK NtfsStructLock;
|
||||
KSPIN_LOCK AfdWorkQueueSpinLock;
|
||||
KSPIN_LOCK KiTimerTableLock[16];
|
||||
KSPIN_LOCK KiReverseStallIpiLock;
|
||||
|
||||
#if defined (ALLOC_PRAGMA)
|
||||
#pragma alloc_text(INIT, Ki386GetCpuId)
|
||||
#pragma alloc_text(INIT, KeInit1)
|
||||
#pragma alloc_text(INIT, KeInit2)
|
||||
#pragma alloc_text(INIT, Ki386SetProcessorFeatures)
|
||||
#endif
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KiIsNpxPresent(
|
||||
VOID
|
||||
);
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
NTAPI
|
||||
KiCheckFPU(VOID)
|
||||
KiInitSpinLocks(IN PKPRCB Prcb,
|
||||
IN CCHAR Number)
|
||||
{
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
ULONG i;
|
||||
|
||||
/* Check for a math co-processor (NPX) */
|
||||
KeI386NpxPresent = KiIsNpxPresent();
|
||||
/* Initialize Dispatcher Fields */
|
||||
Prcb->QueueIndex = 1;
|
||||
Prcb->ReadySummary = 0;
|
||||
Prcb->DeferredReadyListHead.Next = NULL;
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
/* Initialize the ready list */
|
||||
InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
|
||||
}
|
||||
|
||||
/* Check for and enable MMX/SSE support if possible */
|
||||
KeI386FxsrPresent = Prcb->FeatureBits & X86_FEATURE_FXSR ? TRUE : FALSE;
|
||||
/* Initialize DPC Fields */
|
||||
InitializeListHead(&Prcb->DpcData[0].DpcListHead);
|
||||
KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock);
|
||||
Prcb->DpcData[0].DpcQueueDepth = 0;
|
||||
Prcb->DpcData[0].DpcCount = 0;
|
||||
Prcb->DpcRoutineActive = FALSE;
|
||||
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
|
||||
Prcb->MinimumDpcRate = KiMinimumDpcRate;
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);
|
||||
//KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);
|
||||
KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);
|
||||
|
||||
/* Check for SSE (2 and 3 should have this set too) */
|
||||
KeI386XMMIPresent = Prcb->FeatureBits & X86_FEATURE_SSE ? TRUE : FALSE;
|
||||
/* Initialize the Wait List Head */
|
||||
InitializeListHead(&Prcb->WaitListHead);
|
||||
|
||||
/* Initialize Queued Spinlocks */
|
||||
Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;
|
||||
Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;
|
||||
Prcb->LockQueue[LockQueuePfnLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;
|
||||
Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;
|
||||
Prcb->LockQueue[LockQueueBcbLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;
|
||||
Prcb->LockQueue[LockQueueMasterLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;
|
||||
Prcb->LockQueue[LockQueueVacbLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;
|
||||
Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;
|
||||
Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;
|
||||
Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;
|
||||
Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;
|
||||
Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;
|
||||
Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;
|
||||
Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;
|
||||
Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;
|
||||
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
|
||||
Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
|
||||
for (i = LockQueueTimerTableLock; i < LockQueueMaximumLock; i++)
|
||||
{
|
||||
KeInitializeSpinLock(&KiTimerTableLock[i - 16]);
|
||||
Prcb->LockQueue[i].Next = NULL;
|
||||
Prcb->LockQueue[i].Lock = &KiTimerTableLock[i - 16];
|
||||
}
|
||||
|
||||
/* Check if this is the boot CPU */
|
||||
if (!Number)
|
||||
{
|
||||
/* Initialize the lock themselves */
|
||||
KeInitializeSpinLock(&KiDispatcherLock);
|
||||
KeInitializeSpinLock(&KiReverseStallIpiLock);
|
||||
KeInitializeSpinLock(&MmPfnLock);
|
||||
KeInitializeSpinLock(&MmSystemSpaceLock);
|
||||
KeInitializeSpinLock(&CcBcbSpinLock);
|
||||
KeInitializeSpinLock(&CcMasterSpinLock);
|
||||
KeInitializeSpinLock(&CcVacbSpinLock);
|
||||
KeInitializeSpinLock(&CcWorkQueueSpinLock);
|
||||
KeInitializeSpinLock(&IopCancelSpinLock);
|
||||
KeInitializeSpinLock(&IopCompletionLock);
|
||||
KeInitializeSpinLock(&IopDatabaseLock);
|
||||
KeInitializeSpinLock(&IopVpbSpinLock);
|
||||
KeInitializeSpinLock(&NonPagedPoolLock);
|
||||
KeInitializeSpinLock(&MmNonPagedPoolLock);
|
||||
KeInitializeSpinLock(&NtfsStructLock);
|
||||
KeInitializeSpinLock(&AfdWorkQueueSpinLock);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeInit1(VOID)
|
||||
{
|
||||
PKIPCR KPCR;
|
||||
PKPRCB Prcb;
|
||||
BOOLEAN NpxPresent;
|
||||
ULONG FeatureBits;
|
||||
extern USHORT KiBootGdt[];
|
||||
extern KTSS KiBootTss;
|
||||
|
||||
/* Initialize the PCR */
|
||||
KPCR = (PKIPCR)KPCR_BASE;
|
||||
Prcb = &KPCR->PrcbData;
|
||||
memset(KPCR, 0, PAGE_SIZE);
|
||||
KPCR->Self = (PKPCR)KPCR;
|
||||
KPCR->Prcb = &KPCR->PrcbData;
|
||||
KPCR->Irql = SYNCH_LEVEL;
|
||||
KPCR->NtTib.Self = &KPCR->NtTib;
|
||||
KPCR->NtTib.ExceptionList = (PVOID)-1;
|
||||
KPCR->GDT = KiBootGdt;
|
||||
KPCR->IDT = KiIdt;
|
||||
KPCR->TSS = &KiBootTss;
|
||||
KPCR->Number = 0;
|
||||
KPCR->SetMember = 1 << 0;
|
||||
KeActiveProcessors = 1 << 0;
|
||||
KPCR->PrcbData.SetMember = 1 << 0;
|
||||
KiPcrInitDone = 1;
|
||||
|
||||
/*
|
||||
* Low-level GDT, TSS and LDT Setup, most of which Freeldr should have done
|
||||
* instead, and we should only add some extra information. This would be
|
||||
* required for future NTLDR compatibility.
|
||||
*/
|
||||
KiInitializeGdt(NULL);
|
||||
Ki386BootInitializeTSS();
|
||||
Ki386InitializeLdt();
|
||||
KeInitExceptions();
|
||||
KeInitInterrupts();
|
||||
|
||||
/* Detect and set the CPU Type */
|
||||
KiSetProcessorType();
|
||||
|
||||
/* Set CR0 features based on detected CPU */
|
||||
KiSetCR0Bits();
|
||||
|
||||
/* Check if an FPU is present */
|
||||
NpxPresent = KiIsNpxPresent();
|
||||
|
||||
/* Initialize the Power Management Support for this PRCB */
|
||||
PoInitializePrcb(Prcb);
|
||||
|
||||
/* Bugcheck if this is a 386 CPU */
|
||||
if (Prcb->CpuType == 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0);
|
||||
|
||||
/* Get the processor features for the CPU */
|
||||
FeatureBits = KiGetFeatureBits();
|
||||
|
||||
/* Save feature bits */
|
||||
Prcb->FeatureBits = FeatureBits;
|
||||
|
||||
/* Get cache line information for this CPU */
|
||||
KiGetCacheInformation();
|
||||
|
||||
/* Initialize spinlocks and DPC data */
|
||||
KiInitSpinLocks(Prcb, 0);
|
||||
|
||||
/* Set Node Data */
|
||||
KeNodeBlock[0] = &KiNode0;
|
||||
Prcb->ParentNode = KeNodeBlock[0];
|
||||
KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
|
||||
|
||||
/* Set boot-level flags */
|
||||
KeI386NpxPresent = NpxPresent;
|
||||
KeI386CpuType = Prcb->CpuType;
|
||||
KeI386CpuStep = Prcb->CpuStep;
|
||||
KeProcessorArchitecture = 0;
|
||||
KeProcessorLevel = (USHORT)Prcb->CpuType;
|
||||
if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
|
||||
KeFeatureBits = FeatureBits;
|
||||
KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE;
|
||||
KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
|
||||
|
||||
/* Check if Fxsr was found */
|
||||
if (KeI386FxsrPresent)
|
||||
|
@ -85,167 +245,8 @@ KiCheckFPU(VOID)
|
|||
/* FIXME: Implement and enable XMM Page Zeroing for Mm */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VOID INIT_FUNCTION
|
||||
Ki386GetCpuId(VOID)
|
||||
{
|
||||
ULONG OrigFlags, Flags, FinalFlags;
|
||||
ULONG MaxCpuidLevel;
|
||||
ULONG Dummy, Eax, Ecx, Edx;
|
||||
PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR();
|
||||
|
||||
Ke386CpuidFlags2 = Ke386CpuidExFlags = 0;
|
||||
Ke386CacheAlignment = 32;
|
||||
|
||||
/* Try to toggle the id bit in eflags. */
|
||||
Ke386SaveFlags(OrigFlags);
|
||||
Flags = OrigFlags ^ X86_EFLAGS_ID;
|
||||
Ke386RestoreFlags(Flags);
|
||||
Ke386SaveFlags(FinalFlags);
|
||||
|
||||
Pcr->PrcbData.LogicalProcessorsPerPhysicalProcessor = 1;
|
||||
Pcr->PrcbData.InitialApicId = 0xff;
|
||||
|
||||
if ((OrigFlags & X86_EFLAGS_ID) == (FinalFlags & X86_EFLAGS_ID))
|
||||
{
|
||||
/* No cpuid supported. */
|
||||
Pcr->PrcbData.CpuID = FALSE;
|
||||
Pcr->PrcbData.CpuType = 3;
|
||||
return;
|
||||
}
|
||||
Pcr->PrcbData.CpuID = TRUE;
|
||||
|
||||
/* Get the vendor name and the maximum cpuid level supported. */
|
||||
Ki386Cpuid(0, &MaxCpuidLevel, (PULONG)&Pcr->PrcbData.VendorString[0], (PULONG)&Pcr->PrcbData.VendorString[8], (PULONG)&Pcr->PrcbData.VendorString[4]);
|
||||
if (MaxCpuidLevel > 0)
|
||||
{
|
||||
/* Get the feature flags. */
|
||||
Ki386Cpuid(1, &Eax, &Ke386CpuidExMisc, &Ke386CpuidFlags2, &Pcr->PrcbData.FeatureBits);
|
||||
|
||||
DPRINT ("Model: %x\n", (Eax & 0xf00) == 0xf00 ? ((Eax >> 4) & 0xf) | ((Eax >> 12) & 0xf0) : (Eax >> 4) & 0xf);
|
||||
DPRINT ("Family: %x\n", (Eax & 0xf00) == 0xf00 ? ((Eax >> 8) & 0xf) + ((Eax >> 20) & 0xff) : (Eax >> 8) & 0xf);
|
||||
|
||||
/* Get the cache alignment, if it is available */
|
||||
if (Pcr->PrcbData.FeatureBits & (1<<19))
|
||||
{
|
||||
Ke386CacheAlignment = ((Ke386CpuidExMisc >> 8) & 0xff) * 8;
|
||||
}
|
||||
Pcr->PrcbData.CpuType = (Eax >> 8) & 0xf;
|
||||
Pcr->PrcbData.CpuStep = (Eax & 0xf) | ((Eax << 4) & 0xf00);
|
||||
|
||||
Pcr->PrcbData.InitialApicId = (Ke386CpuidExMisc >> 24) & 0xff;
|
||||
|
||||
/* detect Hyper-Threading on Pentium 4 CPUs or later */
|
||||
if ((Pcr->PrcbData.CpuType == 0xf || (Eax & 0x0f00000)) &&
|
||||
!strncmp(Pcr->PrcbData.VendorString, "GenuineIntel", 12) &&
|
||||
Pcr->PrcbData.FeatureBits & X86_FEATURE_HT)
|
||||
{
|
||||
Pcr->PrcbData.LogicalProcessorsPerPhysicalProcessor = (Ke386CpuidExMisc >> 16) & 0xff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Pcr->PrcbData.CpuType = 4;
|
||||
}
|
||||
|
||||
/* Get the maximum extended cpuid level supported. */
|
||||
Ki386Cpuid(0x80000000, &MaxCpuidLevel, &Dummy, &Dummy, &Dummy);
|
||||
if (MaxCpuidLevel > 0)
|
||||
{
|
||||
/* Get the extended feature flags. */
|
||||
Ki386Cpuid(0x80000001, &Dummy, &Dummy, &Dummy, &Ke386CpuidExFlags);
|
||||
}
|
||||
|
||||
/* Get the model name. */
|
||||
if (MaxCpuidLevel >= 0x80000004)
|
||||
{
|
||||
PULONG v = (PULONG)Ke386CpuidModel;
|
||||
Ki386Cpuid(0x80000002, v, v + 1, v + 2, v + 3);
|
||||
Ki386Cpuid(0x80000003, v + 4, v + 5, v + 6, v + 7);
|
||||
Ki386Cpuid(0x80000004, v + 8, v + 9, v + 10, v + 11);
|
||||
}
|
||||
|
||||
/* Get the L1 cache size */
|
||||
if (MaxCpuidLevel >= 0x80000005)
|
||||
{
|
||||
Ki386Cpuid(0x80000005, &Dummy, &Dummy, &Ecx, &Edx);
|
||||
Ke386L1CacheSize = (Ecx >> 24)+(Edx >> 24);
|
||||
if ((Ecx & 0xff) > 0)
|
||||
{
|
||||
Ke386CacheAlignment = Ecx & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the L2 cache size */
|
||||
if (MaxCpuidLevel >= 0x80000006)
|
||||
{
|
||||
Ki386Cpuid(0x80000006, &Dummy, &Dummy, &Ecx, &Dummy);
|
||||
Pcr->SecondLevelCacheSize = Ecx >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
NTAPI
|
||||
KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
|
||||
{
|
||||
PKIPCR KPCR;
|
||||
BOOLEAN Pae = FALSE;
|
||||
BOOLEAN NoExecute = FALSE;
|
||||
PCHAR p1, p2;
|
||||
extern USHORT KiBootGdt[];
|
||||
extern KTSS KiBootTss;
|
||||
|
||||
/*
|
||||
* Initialize the initial PCR region. We can't allocate a page
|
||||
* with MmAllocPage() here because MmInit1() has not yet been
|
||||
* called, so we use a predefined page in low memory
|
||||
*/
|
||||
|
||||
KPCR = (PKIPCR)KPCR_BASE;
|
||||
memset(KPCR, 0, PAGE_SIZE);
|
||||
KPCR->Self = (PKPCR)KPCR;
|
||||
KPCR->Prcb = &KPCR->PrcbData;
|
||||
KPCR->Irql = SYNCH_LEVEL;
|
||||
KPCR->NtTib.Self = &KPCR->NtTib;
|
||||
KPCR->GDT = KiBootGdt;
|
||||
KPCR->IDT = KiIdt;
|
||||
KPCR->TSS = &KiBootTss;
|
||||
KPCR->Number = 0;
|
||||
KPCR->SetMember = 1 << 0;
|
||||
KeActiveProcessors = 1 << 0;
|
||||
KPCR->PrcbData.SetMember = 1 << 0;
|
||||
KiPcrInitDone = 1;
|
||||
PcrsAllocated++;
|
||||
|
||||
KiInitializeGdt (NULL);
|
||||
Ki386BootInitializeTSS();
|
||||
Ki386InitializeLdt();
|
||||
|
||||
/* Get processor information. */
|
||||
Ki386GetCpuId();
|
||||
|
||||
/* Check FPU/MMX/SSE support. */
|
||||
KiCheckFPU();
|
||||
|
||||
/* Mark the end of the exception handler list */
|
||||
KPCR->NtTib.ExceptionList = (PVOID)-1;
|
||||
|
||||
KeInitDpc(KPCR->Prcb);
|
||||
InitializeListHead(&KPCR->PrcbData.WaitListHead);
|
||||
|
||||
KeInitExceptions ();
|
||||
KeInitInterrupts ();
|
||||
|
||||
KeActiveProcessors |= 1 << 0;
|
||||
|
||||
/* Set Node Data */
|
||||
KeNodeBlock[0] = &KiNode0;
|
||||
KPCR->PrcbData.ParentNode = KeNodeBlock[0];
|
||||
KeNodeBlock[0]->ProcessorMask = KPCR->PrcbData.SetMember;
|
||||
|
||||
if (KPCR->PrcbData.FeatureBits & X86_FEATURE_PGE)
|
||||
if (KeFeatureBits & KF_GLOBAL_PAGE)
|
||||
{
|
||||
ULONG Flags;
|
||||
/* Enable global pages */
|
||||
|
@ -256,32 +257,7 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
|
|||
Ke386RestoreFlags(Flags);
|
||||
}
|
||||
|
||||
/* Search for pae and noexecute */
|
||||
p1 = (PCHAR)KeLoaderBlock.CommandLine;
|
||||
while(*p1 && (p2 = strchr(p1, '/')))
|
||||
{
|
||||
p2++;
|
||||
if (!_strnicmp(p2, "PAE", 3))
|
||||
{
|
||||
if (p2[3] == ' ' || p2[3] == 0)
|
||||
{
|
||||
p2 += 3;
|
||||
Pae = TRUE;
|
||||
}
|
||||
}
|
||||
else if (!_strnicmp(p2, "NOEXECUTE", 9))
|
||||
{
|
||||
if (p2[9] == ' ' || p2[9] == '=' || p2[9] == 0)
|
||||
{
|
||||
p2 += 9;
|
||||
NoExecute = TRUE;
|
||||
}
|
||||
}
|
||||
p1 = p2;
|
||||
}
|
||||
|
||||
Ke386Pae = Ke386GetCr4() & X86_CR4_PAE ? TRUE : FALSE;
|
||||
if (KPCR->PrcbData.FeatureBits & X86_FEATURE_SYSCALL)
|
||||
if (KeFeatureBits & KF_FAST_SYSCALL)
|
||||
{
|
||||
extern void KiFastCallEntry(void);
|
||||
|
||||
|
@ -294,7 +270,7 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
|
|||
}
|
||||
|
||||
/* Does the CPU Support 'prefetchnta' (SSE) */
|
||||
if(KPCR->PrcbData.FeatureBits & X86_FEATURE_SSE)
|
||||
if(KeFeatureBits & KF_XMMI)
|
||||
{
|
||||
ULONG Protect;
|
||||
|
||||
|
@ -312,164 +288,40 @@ NTAPI
|
|||
KeInit2(VOID)
|
||||
{
|
||||
ULONG Protect;
|
||||
PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR();
|
||||
PKIPCR Pcr = (PKIPCR)KeGetPcr();
|
||||
PKPRCB Prcb = Pcr->Prcb;
|
||||
|
||||
KiInitializeBugCheck();
|
||||
KeInitializeDispatcher();
|
||||
KiInitializeSystemClock();
|
||||
|
||||
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_PAE)
|
||||
{
|
||||
DPRINT("CPU supports PAE mode\n");
|
||||
if (Ke386Pae)
|
||||
{
|
||||
DPRINT("CPU runs in PAE mode\n");
|
||||
if (Ke386NoExecute)
|
||||
{
|
||||
DPRINT("NoExecute is enabled\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("CPU doesn't run in PAE mode\n");
|
||||
}
|
||||
}
|
||||
if ((Pcr->PrcbData.FeatureBits & (X86_FEATURE_FXSR | X86_FEATURE_MMX | X86_FEATURE_SSE | X86_FEATURE_SSE2)) ||
|
||||
(Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3))
|
||||
{
|
||||
DPRINT("CPU supports" "%s%s%s%s%s" ".\n",
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_FXSR) ? " FXSR" : ""),
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? " MMX" : ""),
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? " SSE" : ""),
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? " SSE2" : ""),
|
||||
((Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3) ? " SSE3" : ""));
|
||||
}
|
||||
if (Ke386GetCr4() & X86_CR4_OSFXSR)
|
||||
{
|
||||
DPRINT("SSE enabled.\n");
|
||||
}
|
||||
if (Ke386GetCr4() & X86_CR4_OSXMMEXCPT)
|
||||
{
|
||||
DPRINT("Unmasked SIMD exceptions enabled.\n");
|
||||
}
|
||||
if (Pcr->PrcbData.VendorString[0])
|
||||
{
|
||||
DPRINT("CPU Vendor: %s\n", Pcr->PrcbData.VendorString);
|
||||
}
|
||||
if (Ke386CpuidModel[0])
|
||||
{
|
||||
DPRINT("CPU Model: %s\n", Ke386CpuidModel);
|
||||
}
|
||||
|
||||
DPRINT("Ke386CacheAlignment: %d\n", Ke386CacheAlignment);
|
||||
if (Ke386L1CacheSize)
|
||||
{
|
||||
|
||||
DPRINT("Ke386L1CacheSize: %dkB\n", Ke386L1CacheSize);
|
||||
}
|
||||
if (Pcr->SecondLevelCacheSize)
|
||||
{
|
||||
DPRINT("Ke386L2CacheSize: %dkB\n", Pcr->SecondLevelCacheSize);
|
||||
}
|
||||
DPRINT1("CPU Detection Complete.\n"
|
||||
"CPUID: %lx\n"
|
||||
"Step : %lx\n"
|
||||
"Type : %lx\n"
|
||||
"ID : %s\n"
|
||||
"FPU : %lx\n"
|
||||
"XMMI : %lx\n"
|
||||
"Fxsr : %lx\n"
|
||||
"Feat : %lx\n"
|
||||
"Ftrs : %lx\n"
|
||||
"Cache: %lx\n"
|
||||
"CR0 : %lx\n"
|
||||
"CR4 : %lx\n",
|
||||
Prcb->CpuID,
|
||||
Prcb->CpuStep,
|
||||
Prcb->CpuType,
|
||||
Prcb->VendorString,
|
||||
KeI386NpxPresent,
|
||||
KeI386XMMIPresent,
|
||||
KeI386FxsrPresent,
|
||||
Prcb->FeatureBits,
|
||||
KeFeatureBits,
|
||||
Pcr->SecondLevelCacheSize,
|
||||
Ke386GetCr0(),
|
||||
Ke386GetCr4());
|
||||
|
||||
/* Set IDT to writable */
|
||||
Protect = MmGetPageProtect(NULL, (PVOID)KiIdt);
|
||||
MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE);
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
Ki386SetProcessorFeatures(VOID)
|
||||
{
|
||||
PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR();
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName =
|
||||
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Kernel");
|
||||
UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FastSystemCallDisable");
|
||||
HANDLE KeyHandle;
|
||||
ULONG ResultLength;
|
||||
struct
|
||||
{
|
||||
KEY_VALUE_PARTIAL_INFORMATION Info;
|
||||
UCHAR Buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
|
||||
Data[0]) + sizeof(ULONG)];
|
||||
} ValueData;
|
||||
NTSTATUS Status;
|
||||
ULONG FastSystemCallDisable = 0;
|
||||
|
||||
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
|
||||
(Pcr->PrcbData.FeatureBits & X86_FEATURE_CX8) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
|
||||
(Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
|
||||
(Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
|
||||
(Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] =
|
||||
(Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC) ? TRUE : FALSE;
|
||||
SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386Pae;
|
||||
SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
|
||||
(Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? TRUE : FALSE;
|
||||
|
||||
/* Does the CPU Support Fast System Call? */
|
||||
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) {
|
||||
|
||||
/* FIXME: Check for Family == 6, Model < 3 and Stepping < 3 and disable */
|
||||
|
||||
/* Make sure it's not disabled in registry */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&KeyName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenKey(&KeyHandle,
|
||||
KEY_QUERY_VALUE,
|
||||
&ObjectAttributes);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
/* Read the Value then Close the Key */
|
||||
Status = ZwQueryValueKey(KeyHandle,
|
||||
&ValueName,
|
||||
KeyValuePartialInformation,
|
||||
&ValueData,
|
||||
sizeof(ValueData),
|
||||
&ResultLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (ResultLength == sizeof(ValueData) &&
|
||||
ValueData.Info.Type == REG_DWORD)
|
||||
{
|
||||
FastSystemCallDisable = *(PULONG)ValueData.Info.Data != 0;
|
||||
}
|
||||
|
||||
ZwClose(KeyHandle);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Disable SYSENTER/SYSEXIT, because the CPU doesn't support it */
|
||||
FastSystemCallDisable = 1;
|
||||
|
||||
}
|
||||
|
||||
if (FastSystemCallDisable) {
|
||||
/* Use INT2E */
|
||||
const unsigned char Entry[7] = {0x8D, 0x54, 0x24, 0x08, /* lea 0x8(%esp),%edx */
|
||||
0xCD, 0x2E, /* int 0x2e */
|
||||
0xC3}; /* ret */
|
||||
memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry));
|
||||
} else {
|
||||
/* Use SYSENTER */
|
||||
const unsigned char Entry[5] = {0x8B, 0xD4, /* movl %esp,%edx */
|
||||
0x0F, 0x34, /* sysenter */
|
||||
0xC3}; /* ret */
|
||||
memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry));
|
||||
/* Enable SYSENTER/SYSEXIT */
|
||||
KiFastSystemCallDisable = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,4 @@ _NtProcessStartup:
|
|||
|
||||
/* Call the main kernel initialization */
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
call __main
|
||||
|
||||
call _KiRosPrepareForSystemStartup@4
|
||||
|
|
|
@ -90,6 +90,12 @@ KiSystemStartup(BOOLEAN BootProcessor)
|
|||
{
|
||||
DPRINT("KiSystemStartup(%d)\n", BootProcessor);
|
||||
|
||||
/* Initialize the Debugger */
|
||||
KdInitSystem (0, &KeLoaderBlock);
|
||||
|
||||
/* Initialize HAL */
|
||||
HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
|
||||
|
||||
/* Initialize the Processor with HAL */
|
||||
HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
|
||||
|
||||
|
@ -124,18 +130,9 @@ KiSystemStartup(BOOLEAN BootProcessor)
|
|||
for(;;);
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Called by the boot loader to start the kernel
|
||||
* ARGUMENTS:
|
||||
* LoaderBlock = Pointer to boot parameters initialized by the boot
|
||||
* loader
|
||||
* NOTE: The boot parameters are stored in low memory which will become
|
||||
* invalid after the memory managment is initialized so we make a local copy.
|
||||
*/
|
||||
VOID
|
||||
INIT_FUNCTION
|
||||
_main(ULONG MultiBootMagic,
|
||||
PROS_LOADER_PARAMETER_BLOCK _LoaderBlock)
|
||||
NTAPI
|
||||
KiRosPrepareForSystemStartup(PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG size;
|
||||
|
@ -147,18 +144,52 @@ _main(ULONG MultiBootMagic,
|
|||
CHAR* s;
|
||||
|
||||
/* Copy the Loader Block Data locally since Low-Memory will be wiped */
|
||||
memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
|
||||
memcpy(&KeLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
|
||||
memcpy(&KeLoaderModules[1],
|
||||
(PVOID)KeLoaderBlock.ModsAddr,
|
||||
sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
|
||||
KeLoaderBlock.ModsCount++;
|
||||
KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
|
||||
|
||||
/* Check for BIOS memory map */
|
||||
KeMemoryMapRangeCount = 0;
|
||||
if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
|
||||
{
|
||||
/* We have a memory map from the nice BIOS */
|
||||
size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
|
||||
i = 0;
|
||||
|
||||
/* Map it until we run out of size */
|
||||
while (i < KeLoaderBlock.MmapLength)
|
||||
{
|
||||
/* Copy into the Kernel Memory Map */
|
||||
memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
|
||||
(PVOID)(KeLoaderBlock.MmapAddr + i),
|
||||
sizeof(ADDRESS_RANGE));
|
||||
|
||||
/* Increase Memory Map Count */
|
||||
KeMemoryMapRangeCount++;
|
||||
|
||||
/* Increase Size */
|
||||
i += size;
|
||||
}
|
||||
|
||||
/* Save data */
|
||||
KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
|
||||
KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing from BIOS */
|
||||
KeLoaderBlock.MmapLength = 0;
|
||||
KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
|
||||
}
|
||||
|
||||
/* Save the Base Address */
|
||||
MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
|
||||
|
||||
/* Set the Command Line */
|
||||
strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine);
|
||||
strcpy(KeLoaderCommandLine, (PCHAR)LoaderBlock->CommandLine);
|
||||
KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
|
||||
|
||||
/* Write the first Module (the Kernel) */
|
||||
|
@ -174,15 +205,15 @@ _main(ULONG MultiBootMagic,
|
|||
KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
|
||||
|
||||
/* Create a block for each module */
|
||||
for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
|
||||
|
||||
for (i = 1; i < KeLoaderBlock.ModsCount; i++)
|
||||
{
|
||||
/* Check if we have to copy the path or not */
|
||||
if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0) {
|
||||
|
||||
if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
|
||||
{
|
||||
strcpy(KeLoaderModuleStrings[i], s + 1);
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
|
||||
}
|
||||
|
||||
|
@ -205,9 +236,6 @@ _main(ULONG MultiBootMagic,
|
|||
/* Choose last module address as the final kernel address */
|
||||
LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
|
||||
|
||||
/* Low level architecture specific initialization */
|
||||
KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
|
||||
|
||||
/* Select the HAL Base */
|
||||
HalBase = KeLoaderModules[1].ModStart;
|
||||
|
||||
|
@ -238,6 +266,9 @@ _main(ULONG MultiBootMagic,
|
|||
/* Increase the last kernel address with the size of HAL */
|
||||
LastKernelAddress += PAGE_ROUND_UP(DriverSize);
|
||||
|
||||
/* FIXME: We need to do this in KiSystemStartup! */
|
||||
KeInit1();
|
||||
|
||||
/* Load the Kernel with the PE Loader */
|
||||
LdrSafePEProcessModule((PVOID)KERNEL_BASE,
|
||||
(PVOID)KERNEL_BASE,
|
||||
|
@ -248,45 +279,6 @@ _main(ULONG MultiBootMagic,
|
|||
FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
|
||||
LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
|
||||
|
||||
KeMemoryMapRangeCount = 0;
|
||||
if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO) {
|
||||
|
||||
/* We have a memory map from the nice BIOS */
|
||||
size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
|
||||
i = 0;
|
||||
|
||||
/* Map it until we run out of size */
|
||||
while (i < KeLoaderBlock.MmapLength) {
|
||||
|
||||
/* Copy into the Kernel Memory Map */
|
||||
memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
|
||||
(PVOID)(KeLoaderBlock.MmapAddr + i),
|
||||
sizeof(ADDRESS_RANGE));
|
||||
|
||||
/* Increase Memory Map Count */
|
||||
KeMemoryMapRangeCount++;
|
||||
|
||||
/* Increase Size */
|
||||
i += size;
|
||||
}
|
||||
|
||||
/* Save data */
|
||||
KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
|
||||
KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
|
||||
|
||||
} else {
|
||||
|
||||
/* Nothing from BIOS */
|
||||
KeLoaderBlock.MmapLength = 0;
|
||||
KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
|
||||
}
|
||||
|
||||
/* Initialize the Debugger */
|
||||
KdInitSystem (0, &KeLoaderBlock);
|
||||
|
||||
/* Initialize HAL */
|
||||
HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
|
||||
|
||||
/* Do general System Startup */
|
||||
KiSystemStartup(1);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<if property="ARCH" value="i386">
|
||||
<directory name="i386">
|
||||
<file first="true">main_asm.S</file>
|
||||
<file>cpu.S</file>
|
||||
<file>cpu.c</file>
|
||||
<file>ctxswitch.S</file>
|
||||
<file>clock.S</file>
|
||||
<file>exp.c</file>
|
||||
|
|
|
@ -320,6 +320,48 @@ PoInit(PROS_LOADER_PARAMETER_BLOCK LoaderBlock,
|
|||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PopPerfIdle(PPROCESSOR_POWER_STATE PowerState)
|
||||
{
|
||||
DPRINT1("PerfIdle function: %p\n", PowerState);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PopPerfIdleDpc(IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2)
|
||||
{
|
||||
/* Call the Perf Idle function */
|
||||
PopPerfIdle(&((PKPRCB)DeferredContext)->PowerState);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
PopIdle0(IN PKPRCB Prcb)
|
||||
{
|
||||
DPRINT1("Idle function: %p\n", Prcb);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PoInitializePrcb(IN PKPRCB Prcb)
|
||||
{
|
||||
/* Initialize the Power State */
|
||||
RtlZeroMemory(&Prcb->PowerState, sizeof(Prcb->PowerState));
|
||||
Prcb->PowerState.Idle0KernelTimeLimit = 0xFFFFFFFF;
|
||||
Prcb->PowerState.CurrentThrottle = 100;
|
||||
Prcb->PowerState.CurrentThrottleIndex = 0;
|
||||
Prcb->PowerState.IdleFunction = PopIdle0;
|
||||
|
||||
/* Initialize the Perf DPC and Timer */
|
||||
KeInitializeDpc(&Prcb->PowerState.PerfDpc, PopPerfIdleDpc, Prcb);
|
||||
//KeSetTargetProcessorDpc(&Prcb->PowerState.PerfDpc, Prcb->Number);
|
||||
KeInitializeTimerEx(&Prcb->PowerState.PerfTimer, SynchronizationTimer);
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
|
|
@ -76,7 +76,7 @@ KeI386VdmInitialize(VOID)
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Not present, so check if the CPU supports VME */
|
||||
if (KeGetPcr()->Prcb->FeatureBits & X86_FEATURE_VME)
|
||||
if (KeGetPcr()->Prcb->FeatureBits & KF_V86_VIS)
|
||||
{
|
||||
/* Enable them. FIXME: Use IPI */
|
||||
Ki386VdmEnablePentiumExtentions();
|
||||
|
|
Loading…
Reference in a new issue