- Fix __rdtsc so it's considered volatile by GCC instead of caching it.

- Add NtInitialUserProcessBuffer settings and validate/user them when launching smss.
- Use SePublicDefaultUnrestrictedSd for the root system link.
- Make enough space for the smss process parameters, there's 6 strings, not 4.
- Fix incorrect length of NtSystemRoot string.
- Disable SYSENTER on CPUs that don't support it.
- Detect and enable NX feature bit.
- Detect and enable DTS support.
- Implement Ki386EnableXMMIExceptions (the XMMI handler still needs to be done, however).
- Implement KiI386PentiumLockErrataFixup to work around the F00F bug.
- Implement KiIsNpxErrataPresent to detect the FDIV bug.
- Implement CPU Speed detection.
- Only setup Initial FX State if the CPU supports FXSR.
- Setup some more PCR fields during init.
- Use NX_SUPPORT_POLICY flags documented in ntddk.h
- Don't boot if CMPXCHG8B is not supported by the CPU. This is the same requirement as Windows.
- Don't overwrite all the PRCB locks in KiInitSpinlocks due to a stupid bug in the timer spinlock initialization.

svn path=/trunk/; revision=25503
This commit is contained in:
Alex Ionescu 2007-01-18 06:23:14 +00:00
parent 8be76ffcb3
commit ccee43a360
13 changed files with 382 additions and 107 deletions

View file

@ -427,6 +427,11 @@ typedef struct _KSYSTEM_TIME
extern volatile KSYSTEM_TIME KeTickCount; extern volatile KSYSTEM_TIME KeTickCount;
#define NX_SUPPORT_POLICY_ALWAYSOFF 0
#define NX_SUPPORT_POLICY_ALWAYSON 1
#define NX_SUPPORT_POLICY_OPTIN 2
#define NX_SUPPORT_POLICY_OPTOUT 3
typedef struct _KUSER_SHARED_DATA typedef struct _KUSER_SHARED_DATA
{ {
ULONG TickCountLowDeprecated; ULONG TickCountLowDeprecated;

View file

@ -39,6 +39,11 @@ Author:
// //
#define SSDT_MAX_ENTRIES 2 #define SSDT_MAX_ENTRIES 2
//
// Processor Architectures
//
#define PROCESSOR_ARCHITECTURE_INTEL 0
// //
// Object Type Mask for Kernel Dispatcher Objects // Object Type Mask for Kernel Dispatcher Objects
// //
@ -87,8 +92,10 @@ Author:
#define KF_3DNOW 0x00004000 #define KF_3DNOW 0x00004000
#define KF_AMDK6MTRR 0x00008000 #define KF_AMDK6MTRR 0x00008000
#define KF_XMMI64 0x00010000 #define KF_XMMI64 0x00010000
#define KF_NX_DISABLED 0x00400000 #define KF_DTS 0x00020000
#define KF_NX_ENABLED 0x00800000 #define KF_NX_BIT 0x20000000
#define KF_NX_DISABLED 0x40000000
#define KF_NX_ENABLED 0x80000000
// //
// KPCR Access for non-IA64 builds // KPCR Access for non-IA64 builds

View file

@ -930,7 +930,7 @@ static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void
unsigned long lo32; unsigned long lo32;
unsigned long hi32; unsigned long hi32;
__asm__("rdtsc" : "=a" (lo32), "=d" (hi32)); __asm__ __volatile__("rdtsc" : "=a" (lo32), "=d" (hi32));
{ {
union u_ union u_

View file

@ -9,7 +9,6 @@
// Failure to respect this will *ACHIEVE NOTHING*. // Failure to respect this will *ACHIEVE NOTHING*.
// //
// Ke1: // Ke1:
// - Implement KiInitMachineDependent.
// - Implement Privileged Instruction Handler in Umode GPF. // - Implement Privileged Instruction Handler in Umode GPF.
// //
// Ex: // Ex:
@ -28,10 +27,6 @@
// Kd: // Kd:
// - Implement KD Kernel Debugging and WinDBG support. // - Implement KD Kernel Debugging and WinDBG support.
// //
// Native:
// - Rewrite loader.
// - Make smss NT-compatible.
//
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// REACTOS GUIDANCE PLAN // REACTOS GUIDANCE PLAN

View file

@ -39,6 +39,12 @@ BOOLEAN NoGuiBoot = FALSE;
/* NT Boot Path */ /* NT Boot Path */
UNICODE_STRING NtSystemRoot; UNICODE_STRING NtSystemRoot;
/* NT Initial User Application */
WCHAR NtInitialUserProcessBuffer[128] = L"\\SystemRoot\\System32\\smss.exe";
ULONG NtInitialUserProcessBufferLength = sizeof(NtInitialUserProcessBuffer) -
sizeof(WCHAR);
ULONG NtInitialUserProcessBufferType = REG_SZ;
/* Boot NLS information */ /* Boot NLS information */
PVOID ExpNlsTableBase; PVOID ExpNlsTableBase;
ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset; ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
@ -68,7 +74,7 @@ ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
&LinkName, &LinkName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL, NULL,
SePublicDefaultSd); SePublicDefaultUnrestrictedSd);
/* Create it */ /* Create it */
Status = NtCreateDirectoryObject(&LinkHandle, Status = NtCreateDirectoryObject(&LinkHandle,
@ -88,7 +94,7 @@ ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
&LinkName, &LinkName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL, NULL,
SePublicDefaultSd); SePublicDefaultUnrestrictedSd);
/* Create it */ /* Create it */
Status = NtCreateDirectoryObject(&LinkHandle, Status = NtCreateDirectoryObject(&LinkHandle,
@ -115,7 +121,7 @@ ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
&LinkName, &LinkName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL, NULL,
SePublicDefaultSd); SePublicDefaultUnrestrictedSd);
/* Build the ARC name */ /* Build the ARC name */
sprintf(Buffer, sprintf(Buffer,
@ -353,10 +359,11 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
PWSTR p; PWSTR p;
UNICODE_STRING NullString = RTL_CONSTANT_STRING(L""); UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
UNICODE_STRING SmssName, Environment, SystemDriveString; UNICODE_STRING SmssName, Environment, SystemDriveString;
PVOID EnvironmentPtr = NULL;
/* Allocate memory for the process parameters */ /* Allocate memory for the process parameters */
Size = sizeof(RTL_USER_PROCESS_PARAMETERS) + Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
((MAX_PATH * 4) * sizeof(WCHAR)); ((MAX_PATH * 6) * sizeof(WCHAR));
Status = ZwAllocateVirtualMemory(NtCurrentProcess(), Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
(PVOID)&ProcessParameters, (PVOID)&ProcessParameters,
0, 0,
@ -378,7 +385,7 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
/* Allocate a page for the environment */ /* Allocate a page for the environment */
Size = PAGE_SIZE; Size = PAGE_SIZE;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(), Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
(PVOID)&ProcessParameters->Environment, &EnvironmentPtr,
0, 0,
&Size, &Size,
MEM_COMMIT, MEM_COMMIT,
@ -389,6 +396,9 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0); KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
} }
/* Write the pointer */
ProcessParameters->Environment = EnvironmentPtr;
/* Make a buffer for the DOS path */ /* Make a buffer for the DOS path */
p = (PWSTR)(ProcessParameters + 1); p = (PWSTR)(ProcessParameters + 1);
ProcessParameters->CurrentDirectory.DosPath.Buffer = p; ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
@ -416,11 +426,48 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
ProcessParameters->ImagePathName.Buffer = p; ProcessParameters->ImagePathName.Buffer = p;
ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR); ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
/* Append the system path and session manager name */ /* Make sure the buffer is a valid string which within the given length */
RtlAppendUnicodeToString(&ProcessParameters->ImagePathName, if ((NtInitialUserProcessBufferType != REG_SZ) ||
L"\\SystemRoot\\System32"); ((NtInitialUserProcessBufferLength != -1) &&
RtlAppendUnicodeToString(&ProcessParameters->ImagePathName, ((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
L"\\smss.exe"); (NtInitialUserProcessBufferLength >
sizeof(NtInitialUserProcessBuffer) - sizeof(WCHAR)))))
{
/* Invalid initial process string, bugcheck */
KeBugCheckEx(SESSION2_INITIALIZATION_FAILED,
(ULONG_PTR)STATUS_INVALID_PARAMETER,
NtInitialUserProcessBufferType,
NtInitialUserProcessBufferLength,
sizeof(NtInitialUserProcessBuffer));
}
/* Cut out anything after a space */
p = NtInitialUserProcessBuffer;
while (*p && *p != L' ') p++;
/* Set the image path length */
ProcessParameters->ImagePathName.Length =
(USHORT)((PCHAR)p - (PCHAR)NtInitialUserProcessBuffer);
/* Copy the actual buffer */
RtlCopyMemory(ProcessParameters->ImagePathName.Buffer,
NtInitialUserProcessBuffer,
ProcessParameters->ImagePathName.Length);
/* Null-terminate it */
ProcessParameters->
ImagePathName.Buffer[ProcessParameters->ImagePathName.Length /
sizeof(WCHAR)] = UNICODE_NULL;
/* Make a buffer for the command line */
p = (PWSTR)((PCHAR)ProcessParameters->ImagePathName.Buffer +
ProcessParameters->ImagePathName.MaximumLength);
ProcessParameters->CommandLine.Buffer = p;
ProcessParameters->CommandLine.MaximumLength = MAX_PATH * sizeof(WCHAR);
/* Add the image name to the command line */
RtlAppendUnicodeToString(&ProcessParameters->CommandLine,
NtInitialUserProcessBuffer);
/* Create the environment string */ /* Create the environment string */
RtlInitEmptyUnicodeString(&Environment, RtlInitEmptyUnicodeString(&Environment,
@ -446,11 +493,8 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot); RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
RtlAppendUnicodeStringToString(&Environment, &NullString); RtlAppendUnicodeStringToString(&Environment, &NullString);
/* Get and set the command line equal to the image path */
ProcessParameters->CommandLine = ProcessParameters->ImagePathName;
SmssName = ProcessParameters->ImagePathName;
/* Create SMSS process */ /* Create SMSS process */
SmssName = ProcessParameters->ImagePathName;
Status = RtlCreateUserProcess(&SmssName, Status = RtlCreateUserProcess(&SmssName,
OBJ_CASE_INSENSITIVE, OBJ_CASE_INSENSITIVE,
RtlDeNormalizeProcessParams( RtlDeNormalizeProcessParams(
@ -731,9 +775,9 @@ ExpInitializeExecutive(IN ULONG Cpu,
Buffer[--AnsiPath.Length] = ANSI_NULL; Buffer[--AnsiPath.Length] = ANSI_NULL;
/* Get the string from KUSER_SHARED_DATA's buffer */ /* Get the string from KUSER_SHARED_DATA's buffer */
NtSystemRoot.Buffer = SharedUserData->NtSystemRoot; RtlInitEmptyUnicodeString(&NtSystemRoot,
NtSystemRoot.MaximumLength = sizeof(SharedUserData->NtSystemRoot) / sizeof(WCHAR); SharedUserData->NtSystemRoot,
NtSystemRoot.Length = 0; sizeof(SharedUserData->NtSystemRoot));
/* Now fill it in */ /* Now fill it in */
Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE); Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
@ -960,8 +1004,7 @@ ExPhase2Init(PVOID Context)
/* Bugcheck the system if SMSS couldn't initialize */ /* Bugcheck the system if SMSS couldn't initialize */
KeBugCheck(SESSION5_INITIALIZATION_FAILED); KeBugCheck(SESSION5_INITIALIZATION_FAILED);
} }
else
{
/* Close process handles */ /* Close process handles */
ZwClose(ThreadHandle); ZwClose(ThreadHandle);
ZwClose(ProcessHandle); ZwClose(ProcessHandle);
@ -973,6 +1016,5 @@ ExPhase2Init(PVOID Context)
/* Jump into zero page thread */ /* Jump into zero page thread */
MmZeroPageThreadMain(NULL); MmZeroPageThreadMain(NULL);
}
} }
/* EOF */ /* EOF */

View file

@ -92,6 +92,12 @@ KiIsNpxPresent(
VOID VOID
); );
BOOLEAN
NTAPI
KiIsNpxErrataPresent(
VOID
);
VOID VOID
NTAPI NTAPI
KiSetProcessorType(VOID); KiSetProcessorType(VOID);

View file

@ -37,6 +37,18 @@ typedef struct _DISPATCH_INFO
PKINTERRUPT_ROUTINE *FlatDispatch; PKINTERRUPT_ROUTINE *FlatDispatch;
} DISPATCH_INFO, *PDISPATCH_INFO; } DISPATCH_INFO, *PDISPATCH_INFO;
typedef struct _KI_SAMPLE_MAP
{
LARGE_INTEGER PerfStart;
LARGE_INTEGER PerfEnd;
LONGLONG PerfDelta;
LARGE_INTEGER PerfFreq;
LONGLONG TSCStart;
LONGLONG TSCEnd;
LONGLONG TSCDelta;
ULONG MHz;
} KI_SAMPLE_MAP, *PKI_SAMPLE_MAP;
typedef struct _KTIMER_TABLE_ENTRY typedef struct _KTIMER_TABLE_ENTRY
{ {
LIST_ENTRY Entry; LIST_ENTRY Entry;
@ -113,7 +125,7 @@ extern KSPIN_LOCK BugCheckCallbackLock;
extern KDPC KiExpireTimerDpc; extern KDPC KiExpireTimerDpc;
extern KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]; extern KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];
extern LIST_ENTRY KiTimerListHead; extern LIST_ENTRY KiTimerListHead;
extern KMUTEX KiGenericCallDpcMutex; extern FAST_MUTEX KiGenericCallDpcMutex;
extern LIST_ENTRY KiProfileListHead, KiProfileSourceListHead; extern LIST_ENTRY KiProfileListHead, KiProfileSourceListHead;
extern KSPIN_LOCK KiProfileLock; extern KSPIN_LOCK KiProfileLock;
extern LIST_ENTRY KiProcessListHead; extern LIST_ENTRY KiProcessListHead;
@ -235,6 +247,13 @@ KiSelectNextThread(
IN PKPRCB Prcb IN PKPRCB Prcb
); );
VOID
NTAPI
CPUID(
OUT ULONG CpuInfo[4],
IN ULONG InfoType
);
/* gmutex.c ********************************************************************/ /* gmutex.c ********************************************************************/
VOID VOID

View file

@ -23,7 +23,7 @@ ULONG KiMinimumDpcRate = 3;
ULONG KiAdjustDpcThreshold = 20; ULONG KiAdjustDpcThreshold = 20;
ULONG KiIdealDpcRate = 20; ULONG KiIdealDpcRate = 20;
BOOLEAN KeThreadDpcEnable; BOOLEAN KeThreadDpcEnable;
KMUTEX KiGenericCallDpcMutex; FAST_MUTEX KiGenericCallDpcMutex;
/* PRIVATE FUNCTIONS *********************************************************/ /* PRIVATE FUNCTIONS *********************************************************/

View file

@ -340,6 +340,14 @@ KiGetFeatureBits(VOID)
FeatureBits &= ~KF_WORKING_PTE; FeatureBits &= ~KF_WORKING_PTE;
} }
/* Check if the CPU is too old to support SYSENTER */
if ((Prcb->CpuType < 6) ||
((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303)))
{
/* Disable it */
Reg[3] &= ~0x800;
}
/* Set the current features */ /* Set the current features */
CpuFeatures = Reg[3]; CpuFeatures = Reg[3];
} }
@ -354,6 +362,7 @@ KiGetFeatureBits(VOID)
if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4; if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV; if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;
if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT; if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;
if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS;
if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX; if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR; if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI; if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
@ -389,6 +398,9 @@ KiGetFeatureBits(VOID)
/* Check which extended features are available. */ /* Check which extended features are available. */
CPUID(Reg, 0x80000001); CPUID(Reg, 0x80000001);
/* Check if NX-bit is supported */
if (Reg[3] & 0x00100000) FeatureBits |= KF_NX_BIT;
/* Now handle each features for each CPU Vendor */ /* Now handle each features for each CPU Vendor */
switch (Vendor) switch (Vendor)
{ {
@ -741,8 +753,23 @@ ULONG_PTR
NTAPI NTAPI
Ki386EnableXMMIExceptions(IN ULONG_PTR Context) Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
{ {
/* FIXME: Support this */ #if 0 // needs kitrap13
DPRINT1("Your machine supports XMMI exceptions but ReactOS doesn't\n"); PKIDTENTRY IdtEntry;
/* Get the IDT Entry for Interrupt 19 */
IdtEntry = ((PKIPCR)KeGetPcr())->IDT[19];
/* Set it up */
IdtEntry->Selector = KGDT_R0_CODE;
IdtEntry->Offset = (KiTrap13 & 0xFFFF);
IdtEntry->ExtendedOffset = (KiTrap13 >> 16) & 0xFFFF;
((PKIDT_ACCESS)&IdtEntry->Access)->Dpl = 0;
((PKIDT_ACCESS)&IdtEntry->Access)->Present = 1;
((PKIDT_ACCESS)&IdtEntry->Access)->SegmentType = I386_INTERRUPT_GATE;
#endif
/* Enable XMMI exceptions */
__writecr4(__readcr4() | CR4_XMMEXCPT);
return 0; return 0;
} }
@ -750,8 +777,34 @@ VOID
NTAPI NTAPI
KiI386PentiumLockErrataFixup(VOID) KiI386PentiumLockErrataFixup(VOID)
{ {
/* FIXME: Support this */ KDESCRIPTOR IdtDescriptor;
DPRINT1("WARNING: Your machine has a CPU bug that ReactOS can't bypass!\n"); PKIDTENTRY NewIdt, NewIdt2;
/* Allocate memory for a new IDT */
NewIdt = ExAllocatePool(NonPagedPool, 2 * PAGE_SIZE);
/* Put everything after the first 7 entries on a new page */
NewIdt2 = (PVOID)((ULONG_PTR)NewIdt + PAGE_SIZE - (7 * sizeof(KIDTENTRY)));
/* Disable interrupts */
_disable();
/* Get the current IDT and copy it */
Ke386GetInterruptDescriptorTable(IdtDescriptor);
RtlCopyMemory(NewIdt2,
(PVOID)IdtDescriptor.Base,
IdtDescriptor.Limit + 1);
IdtDescriptor.Base = (ULONG)NewIdt2;
/* Set the new IDT */
Ke386SetInterruptDescriptorTable(IdtDescriptor);
((PKIPCR)KeGetPcr())->IDT = NewIdt2;
/* Restore interrupts */
_enable();
/* Set the first 7 entries as read-only to produce a fault */
MmSetPageProtect(NULL, NewIdt, PAGE_READONLY);
} }
/* PUBLIC FUNCTIONS **********************************************************/ /* PUBLIC FUNCTIONS **********************************************************/

View file

@ -17,8 +17,56 @@
#define Running 2 #define Running 2
#define WrDispatchInt 0x1F #define WrDispatchInt 0x1F
Dividend: .float 4195835.0
Divisor: .float 3145727.0
Result1: .float 0
Result2: .float 0
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
.globl _KiIsNpxErrataPresent@0
.func KiIsNpxErrataPresent@0
_KiIsNpxErrataPresent@0:
/* Disable interrupts */
cli
/* Get CR0 and mask out FPU flags */
mov eax, cr0
mov ecx, eax
and eax, ~(CR0_MP + CR0_TS + CR0_EM)
mov cr0, eax
/* Initialize the FPU */
fninit
/* Do the divison and inverse multiplication */
fld qword ptr Dividend
fstp qword ptr Result1
fld qword ptr Divisor
fstp qword ptr Result2
fld qword ptr Result1
fdiv qword ptr Result2
fmul qword ptr Result2
/* Do the compare and check flags */
fcomp qword ptr Result1
fstsw ax
sahf
/* Restore CR0 and interrupts */
mov cr0, ecx
sti
/* Return errata status */
xor eax, eax
jz NoErrata
inc eax
NoErrata:
ret
.endfunc
.globl _KiIsNpxPresent@0 .globl _KiIsNpxPresent@0
.func KiIsNpxPresent@0 .func KiIsNpxPresent@0
_KiIsNpxPresent@0: _KiIsNpxPresent@0:

View file

@ -30,15 +30,18 @@ KiInitMachineDependent(VOID)
BOOLEAN FbCaching = FALSE; BOOLEAN FbCaching = FALSE;
NTSTATUS Status; NTSTATUS Status;
ULONG ReturnLength; ULONG ReturnLength;
ULONG i, Affinity; ULONG i, Affinity, Sample = 0;
PFX_SAVE_AREA FxSaveArea; PFX_SAVE_AREA FxSaveArea;
ULONG MXCsrMask = 0xFFBF, NewMask; ULONG MXCsrMask = 0xFFBF;
ULONG Dummy[4];
KI_SAMPLE_MAP Samples[4];
PKI_SAMPLE_MAP CurrentSample = Samples;
/* Check for large page support */ /* Check for large page support */
if (KeFeatureBits & KF_LARGE_PAGE) if (KeFeatureBits & KF_LARGE_PAGE)
{ {
/* FIXME: Support this */ /* FIXME: Support this */
DPRINT1("Your machine supports PGE but ReactOS doesn't yet.\n"); DPRINT1("Large Page support detected but not yet taken advantage of!\n");
} }
/* Check for global page support */ /* Check for global page support */
@ -70,6 +73,34 @@ KiInitMachineDependent(VOID)
/* Assume no errata for now */ /* Assume no errata for now */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0; SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = 0;
/* Check if we have an NPX */
if (KeI386NpxPresent)
{
/* Loop every CPU */
i = KeActiveProcessors;
for (Affinity = 1; i; Affinity <<= 1)
{
/* Check if this is part of the set */
if (i & Affinity)
{
/* Run on this CPU */
i &= ~Affinity;
KeSetSystemAffinityThread(Affinity);
/* Detect FPU errata */
if (KiIsNpxErrataPresent())
{
/* Disable NPX support */
KeI386NpxPresent = FALSE;
SharedUserData->
ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
TRUE;
break;
}
}
}
}
/* If there's no NPX, then we're emulating the FPU */ /* If there's no NPX, then we're emulating the FPU */
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
!KeI386NpxPresent; !KeI386NpxPresent;
@ -148,18 +179,66 @@ KiInitMachineDependent(VOID)
/* Start sampling loop */ /* Start sampling loop */
for (;;) for (;;)
{ {
// /* Do a dummy CPUID to start the sample */
// FIXME: TODO CPUID(Dummy, 0);
//
/* Fill out the starting data */
CurrentSample->PerfStart = KeQueryPerformanceCounter(NULL);
CurrentSample->TSCStart = __rdtsc();
CurrentSample->PerfFreq.QuadPart = -50000;
/* Sleep for this sample */
KeDelayExecutionThread(KernelMode,
FALSE,
&CurrentSample->PerfFreq);
/* Do another dummy CPUID */
CPUID(Dummy, 0);
/* Fill out the ending data */
CurrentSample->PerfEnd =
KeQueryPerformanceCounter(&CurrentSample->PerfFreq);
CurrentSample->TSCEnd = __rdtsc();
/* Calculate the differences */
CurrentSample->PerfDelta = CurrentSample->PerfEnd.QuadPart -
CurrentSample->PerfStart.QuadPart;
CurrentSample->TSCDelta = CurrentSample->TSCEnd -
CurrentSample->TSCStart;
/* Compute CPU Speed */
CurrentSample->MHz = ((CurrentSample->TSCDelta *
CurrentSample->PerfFreq.QuadPart +
500000) /
(CurrentSample->PerfDelta * 1000000));
/* Check if this isn't the first sample */
if (Sample)
{
/* Check if we got a good precision within 1MHz */
if ((CurrentSample->MHz == CurrentSample[-1].MHz) ||
(CurrentSample->MHz == CurrentSample[-1].MHz + 1) ||
(CurrentSample->MHz == CurrentSample[-1].MHz - 1))
{
/* We did, stop sampling */
break; break;
} }
} }
/* Check if we have MTRR without PAT */ /* Move on */
if (!(KeFeatureBits & KF_PAT) && (KeFeatureBits & KF_MTRR)) CurrentSample++;
Sample++;
}
/* Save the CPU Speed */
KeGetCurrentPrcb()->MHz = CurrentSample[-1].MHz;
}
/* Check if we have MTRR */
if (KeFeatureBits & KF_MTRR)
{ {
/* Then manually initialize MTRR for the CPU */ /* Then manually initialize MTRR for the CPU */
KiInitializeMTRR((BOOLEAN)i); KiInitializeMTRR((BOOLEAN)i ? FALSE : TRUE);
} }
/* Check if we have AMD MTRR and initialize it for the CPU */ /* Check if we have AMD MTRR and initialize it for the CPU */
@ -168,6 +247,9 @@ KiInitMachineDependent(VOID)
/* Check if this is a buggy Pentium and apply the fixup if so */ /* Check if this is a buggy Pentium and apply the fixup if so */
if (KiI386PentiumLockErrataPresent) KiI386PentiumLockErrataFixup(); if (KiI386PentiumLockErrataPresent) KiI386PentiumLockErrataFixup();
/* Check if the CPU supports FXSR */
if (KeFeatureBits & KF_FXSR)
{
/* Get the current thread NPX state */ /* Get the current thread NPX state */
FxSaveArea = (PVOID) FxSaveArea = (PVOID)
((ULONG_PTR)KeGetCurrentThread()->InitialStack - ((ULONG_PTR)KeGetCurrentThread()->InitialStack -
@ -183,7 +265,7 @@ KiInitMachineDependent(VOID)
__asm fxsave [FxSaveArea] __asm fxsave [FxSaveArea]
#endif #endif
/* Check if the current mask doesn't match the reserved bits */ /* Check if the current mask doesn't match the reserved bits */
if (FxSaveArea->U.FxArea.MXCsrMask != MXCsrMask) if (FxSaveArea->U.FxArea.MXCsrMask != 0)
{ {
/* Then use whatever it's holding */ /* Then use whatever it's holding */
MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask; MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask;
@ -193,27 +275,25 @@ KiInitMachineDependent(VOID)
if (!KiMXCsrMask) if (!KiMXCsrMask)
{ {
/* Then use the one we calculated above */ /* Then use the one we calculated above */
NewMask = MXCsrMask; KiMXCsrMask = MXCsrMask;
} }
else else
{ {
/* Use the existing mask */
NewMask = KiMXCsrMask;
/* Was it set to the same value we found now? */ /* Was it set to the same value we found now? */
if (NewMask != MXCsrMask) if (KiMXCsrMask != MXCsrMask)
{ {
/* No, something is definitely wrong */ /* No, something is definitely wrong */
KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
KF_FXSR, KF_FXSR,
NewMask, KiMXCsrMask,
MXCsrMask, MXCsrMask,
0); 0);
} }
} }
/* Now set the kernel mask */ /* Now set the kernel mask */
KiMXCsrMask = NewMask & MXCsrMask; KiMXCsrMask &= MXCsrMask;
}
} }
} }
@ -242,7 +322,7 @@ KiInitializePcr(IN ULONG ProcessorNumber,
Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END; Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
Pcr->NtTib.StackBase = 0; Pcr->NtTib.StackBase = 0;
Pcr->NtTib.StackLimit = 0; Pcr->NtTib.StackLimit = 0;
Pcr->NtTib.Self = 0; Pcr->NtTib.Self = NULL;
/* Set the Current Thread */ /* Set the Current Thread */
Pcr->PrcbData.CurrentThread = IdleThread; Pcr->PrcbData.CurrentThread = IdleThread;
@ -282,7 +362,11 @@ KiInitializePcr(IN ULONG ProcessorNumber,
Pcr->GDT = (PVOID)Gdt; Pcr->GDT = (PVOID)Gdt;
Pcr->IDT = Idt; Pcr->IDT = Idt;
Pcr->TSS = Tss; Pcr->TSS = Tss;
Pcr->TssCopy = Tss;
Pcr->PrcbData.DpcStack = DpcStack; Pcr->PrcbData.DpcStack = DpcStack;
/* Setup the processor set */
Pcr->PrcbData.MultiThreadProcessorSet = Pcr->PrcbData.SetMember;
} }
VOID VOID
@ -299,6 +383,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
LARGE_INTEGER PageDirectory; LARGE_INTEGER PageDirectory;
PVOID DpcStack; PVOID DpcStack;
ULONG NXSupportPolicy; ULONG NXSupportPolicy;
ULONG Vendor[3];
/* Detect and set the CPU Type */ /* Detect and set the CPU Type */
KiSetProcessorType(); KiSetProcessorType();
@ -319,19 +404,19 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
FeatureBits = KiGetFeatureBits(); FeatureBits = KiGetFeatureBits();
/* Set the default NX policy (opt-in) */ /* Set the default NX policy (opt-in) */
NXSupportPolicy = 2; NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
/* Check if NPX is always on */ /* Check if NPX is always on */
if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON")) if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
{ {
/* Set it always on */ /* Set it always on */
NXSupportPolicy = 1; NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
FeatureBits |= KF_NX_ENABLED; FeatureBits |= KF_NX_ENABLED;
} }
else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT")) else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
{ {
/* Set it in opt-out mode */ /* Set it in opt-out mode */
NXSupportPolicy = 3; NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
FeatureBits |= KF_NX_ENABLED; FeatureBits |= KF_NX_ENABLED;
} }
else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) || else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
@ -344,7 +429,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
(strstr(KeLoaderBlock->LoadOptions, "EXECUTE"))) (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
{ {
/* Set disabled mode */ /* Set disabled mode */
NXSupportPolicy = 0; NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF;
FeatureBits |= KF_NX_DISABLED; FeatureBits |= KF_NX_DISABLED;
} }
@ -372,18 +457,32 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
KeI386NpxPresent = NpxPresent; KeI386NpxPresent = NpxPresent;
KeI386CpuType = Prcb->CpuType; KeI386CpuType = Prcb->CpuType;
KeI386CpuStep = Prcb->CpuStep; KeI386CpuStep = Prcb->CpuStep;
KeProcessorArchitecture = 0; KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
KeProcessorLevel = (USHORT)Prcb->CpuType; KeProcessorLevel = (USHORT)Prcb->CpuType;
if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep; if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
KeFeatureBits = FeatureBits; KeFeatureBits = FeatureBits;
KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE; KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE;
KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE; KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
/* Detect 8-byte compare exchange support */
if (!(KeFeatureBits & KF_CMPXCHG8B))
{
/* Copy the vendor string */
RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor));
/* Bugcheck the system. Windows *requires* this */
KeBugCheckEx(0x5D,
(1 << 24 ) | (Prcb->CpuType << 16) | Prcb->CpuStep,
Vendor[0],
Vendor[1],
Vendor[2]);
}
/* Set the current MP Master KPRCB to the Boot PRCB */ /* Set the current MP Master KPRCB to the Boot PRCB */
Prcb->MultiThreadSetMaster = Prcb; Prcb->MultiThreadSetMaster = Prcb;
/* Lower to APC_LEVEL */ /* Lower to APC_LEVEL */
KfLowerIrql(APC_LEVEL); KeLowerIrql(APC_LEVEL);
/* Initialize some spinlocks */ /* Initialize some spinlocks */
KeInitializeSpinLock(&KiFreezeExecutionLock); KeInitializeSpinLock(&KiFreezeExecutionLock);
@ -499,7 +598,9 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
KeSetPriorityThread(InitThread, 0); KeSetPriorityThread(InitThread, 0);
/* If there's no thread scheduled, put this CPU in the Idle summary */ /* If there's no thread scheduled, put this CPU in the Idle summary */
KiAcquirePrcbLock(Prcb);
if (!Prcb->NextThread) KiIdleSummary |= 1 << Number; if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
KiReleasePrcbLock(Prcb);
/* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
KfRaiseIrql(HIGH_LEVEL); KfRaiseIrql(HIGH_LEVEL);
@ -683,11 +784,6 @@ AppCpuInit:
/* Set the right wait IRQL */ /* Set the right wait IRQL */
KeGetCurrentThread()->WaitIrql = DISPATCH_LEVEL; KeGetCurrentThread()->WaitIrql = DISPATCH_LEVEL;
/* Set idle thread as running on UP builds */
#ifndef CONFIG_SMP
KeGetCurrentThread()->State = Running;
#endif
/* Jump into the idle loop */ /* Jump into the idle loop */
KiIdleLoop(); KiIdleLoop();
} }

View file

@ -59,5 +59,5 @@ NTAPI
KiInitializePAT(VOID) KiInitializePAT(VOID)
{ {
/* FIXME: Support this */ /* FIXME: Support this */
DPRINT1("Your machine supports PAT but ReactOS doesn't yet.\n"); DPRINT1("Advanced Memory features detected but not yet taken advantage of.\n");
} }

View file

@ -94,7 +94,7 @@ KiInitSystem(VOID)
InitializeListHead(&KiStackInSwapListHead); InitializeListHead(&KiStackInSwapListHead);
/* Initialize the mutex for generic DPC calls */ /* Initialize the mutex for generic DPC calls */
KeInitializeMutex(&KiGenericCallDpcMutex, 0); ExInitializeFastMutex(&KiGenericCallDpcMutex);
/* Initialize the syscall table */ /* Initialize the syscall table */
KeServiceDescriptorTable[0].Base = MainSSDT; KeServiceDescriptorTable[0].Base = MainSSDT;
@ -183,7 +183,7 @@ KiInitSpinLocks(IN PKPRCB Prcb,
Prcb->QueueIndex = 1; Prcb->QueueIndex = 1;
Prcb->ReadySummary = 0; Prcb->ReadySummary = 0;
Prcb->DeferredReadyListHead.Next = NULL; Prcb->DeferredReadyListHead.Next = NULL;
for (i = 0; i < 32; i++) for (i = 0; i < MAXIMUM_PRIORITY; i++)
{ {
/* Initialize the ready list */ /* Initialize the ready list */
InitializeListHead(&Prcb->DispatcherReadyListHead[i]); InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
@ -246,10 +246,14 @@ KiInitSpinLocks(IN PKPRCB Prcb,
{ {
/* Initialize the lock and setup the Queued Spinlock */ /* Initialize the lock and setup the Queued Spinlock */
KeInitializeSpinLock(&KiTimerTableLock[i]); KeInitializeSpinLock(&KiTimerTableLock[i]);
Prcb->LockQueue[i].Next = NULL; Prcb->LockQueue[LockQueueTimerTableLock + i].Next = NULL;
Prcb->LockQueue[i].Lock = &KiTimerTableLock[i]; Prcb->LockQueue[LockQueueTimerTableLock + i].Lock =
&KiTimerTableLock[i];
} }
/* Initialize the PRCB lock */
KeInitializeSpinLock(&Prcb->PrcbLock);
/* Check if this is the boot CPU */ /* Check if this is the boot CPU */
if (!Number) if (!Number)
{ {