mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
- 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:
parent
8be76ffcb3
commit
ccee43a360
|
@ -427,6 +427,11 @@ typedef struct _KSYSTEM_TIME
|
|||
|
||||
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
|
||||
{
|
||||
ULONG TickCountLowDeprecated;
|
||||
|
|
|
@ -39,6 +39,11 @@ Author:
|
|||
//
|
||||
#define SSDT_MAX_ENTRIES 2
|
||||
|
||||
//
|
||||
// Processor Architectures
|
||||
//
|
||||
#define PROCESSOR_ARCHITECTURE_INTEL 0
|
||||
|
||||
//
|
||||
// Object Type Mask for Kernel Dispatcher Objects
|
||||
//
|
||||
|
@ -87,8 +92,10 @@ Author:
|
|||
#define KF_3DNOW 0x00004000
|
||||
#define KF_AMDK6MTRR 0x00008000
|
||||
#define KF_XMMI64 0x00010000
|
||||
#define KF_NX_DISABLED 0x00400000
|
||||
#define KF_NX_ENABLED 0x00800000
|
||||
#define KF_DTS 0x00020000
|
||||
#define KF_NX_BIT 0x20000000
|
||||
#define KF_NX_DISABLED 0x40000000
|
||||
#define KF_NX_ENABLED 0x80000000
|
||||
|
||||
//
|
||||
// KPCR Access for non-IA64 builds
|
||||
|
|
|
@ -930,7 +930,7 @@ static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void
|
|||
unsigned long lo32;
|
||||
unsigned long hi32;
|
||||
|
||||
__asm__("rdtsc" : "=a" (lo32), "=d" (hi32));
|
||||
__asm__ __volatile__("rdtsc" : "=a" (lo32), "=d" (hi32));
|
||||
|
||||
{
|
||||
union u_
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// Failure to respect this will *ACHIEVE NOTHING*.
|
||||
//
|
||||
// Ke1:
|
||||
// - Implement KiInitMachineDependent.
|
||||
// - Implement Privileged Instruction Handler in Umode GPF.
|
||||
//
|
||||
// Ex:
|
||||
|
@ -28,10 +27,6 @@
|
|||
// Kd:
|
||||
// - Implement KD Kernel Debugging and WinDBG support.
|
||||
//
|
||||
// Native:
|
||||
// - Rewrite loader.
|
||||
// - Make smss NT-compatible.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// REACTOS GUIDANCE PLAN
|
||||
|
|
|
@ -39,6 +39,12 @@ BOOLEAN NoGuiBoot = FALSE;
|
|||
/* NT Boot Path */
|
||||
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 */
|
||||
PVOID ExpNlsTableBase;
|
||||
ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
|
||||
|
@ -68,7 +74,7 @@ ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
&LinkName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
|
||||
NULL,
|
||||
SePublicDefaultSd);
|
||||
SePublicDefaultUnrestrictedSd);
|
||||
|
||||
/* Create it */
|
||||
Status = NtCreateDirectoryObject(&LinkHandle,
|
||||
|
@ -88,7 +94,7 @@ ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
&LinkName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
|
||||
NULL,
|
||||
SePublicDefaultSd);
|
||||
SePublicDefaultUnrestrictedSd);
|
||||
|
||||
/* Create it */
|
||||
Status = NtCreateDirectoryObject(&LinkHandle,
|
||||
|
@ -115,7 +121,7 @@ ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
&LinkName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
|
||||
NULL,
|
||||
SePublicDefaultSd);
|
||||
SePublicDefaultUnrestrictedSd);
|
||||
|
||||
/* Build the ARC name */
|
||||
sprintf(Buffer,
|
||||
|
@ -353,10 +359,11 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
|
|||
PWSTR p;
|
||||
UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
|
||||
UNICODE_STRING SmssName, Environment, SystemDriveString;
|
||||
PVOID EnvironmentPtr = NULL;
|
||||
|
||||
/* Allocate memory for the process parameters */
|
||||
Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
|
||||
((MAX_PATH * 4) * sizeof(WCHAR));
|
||||
((MAX_PATH * 6) * sizeof(WCHAR));
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID)&ProcessParameters,
|
||||
0,
|
||||
|
@ -378,7 +385,7 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
|
|||
/* Allocate a page for the environment */
|
||||
Size = PAGE_SIZE;
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID)&ProcessParameters->Environment,
|
||||
&EnvironmentPtr,
|
||||
0,
|
||||
&Size,
|
||||
MEM_COMMIT,
|
||||
|
@ -389,6 +396,9 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
|
|||
KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Write the pointer */
|
||||
ProcessParameters->Environment = EnvironmentPtr;
|
||||
|
||||
/* Make a buffer for the DOS path */
|
||||
p = (PWSTR)(ProcessParameters + 1);
|
||||
ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
|
||||
|
@ -416,11 +426,48 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
|
|||
ProcessParameters->ImagePathName.Buffer = p;
|
||||
ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
|
||||
|
||||
/* Append the system path and session manager name */
|
||||
RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
|
||||
L"\\SystemRoot\\System32");
|
||||
RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
|
||||
L"\\smss.exe");
|
||||
/* Make sure the buffer is a valid string which within the given length */
|
||||
if ((NtInitialUserProcessBufferType != REG_SZ) ||
|
||||
((NtInitialUserProcessBufferLength != -1) &&
|
||||
((NtInitialUserProcessBufferLength < sizeof(WCHAR)) ||
|
||||
(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 */
|
||||
RtlInitEmptyUnicodeString(&Environment,
|
||||
|
@ -446,11 +493,8 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
|
|||
RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
|
||||
RtlAppendUnicodeStringToString(&Environment, &NullString);
|
||||
|
||||
/* Get and set the command line equal to the image path */
|
||||
ProcessParameters->CommandLine = ProcessParameters->ImagePathName;
|
||||
SmssName = ProcessParameters->ImagePathName;
|
||||
|
||||
/* Create SMSS process */
|
||||
SmssName = ProcessParameters->ImagePathName;
|
||||
Status = RtlCreateUserProcess(&SmssName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
RtlDeNormalizeProcessParams(
|
||||
|
@ -731,9 +775,9 @@ ExpInitializeExecutive(IN ULONG Cpu,
|
|||
Buffer[--AnsiPath.Length] = ANSI_NULL;
|
||||
|
||||
/* Get the string from KUSER_SHARED_DATA's buffer */
|
||||
NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
|
||||
NtSystemRoot.MaximumLength = sizeof(SharedUserData->NtSystemRoot) / sizeof(WCHAR);
|
||||
NtSystemRoot.Length = 0;
|
||||
RtlInitEmptyUnicodeString(&NtSystemRoot,
|
||||
SharedUserData->NtSystemRoot,
|
||||
sizeof(SharedUserData->NtSystemRoot));
|
||||
|
||||
/* Now fill it in */
|
||||
Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &AnsiPath, FALSE);
|
||||
|
@ -960,19 +1004,17 @@ ExPhase2Init(PVOID Context)
|
|||
/* Bugcheck the system if SMSS couldn't initialize */
|
||||
KeBugCheck(SESSION5_INITIALIZATION_FAILED);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Close process handles */
|
||||
ZwClose(ThreadHandle);
|
||||
ZwClose(ProcessHandle);
|
||||
|
||||
/* FIXME: We should free the initial process' memory!*/
|
||||
/* Close process handles */
|
||||
ZwClose(ThreadHandle);
|
||||
ZwClose(ProcessHandle);
|
||||
|
||||
/* Increase init phase */
|
||||
ExpInitializationPhase += 1;
|
||||
/* FIXME: We should free the initial process' memory!*/
|
||||
|
||||
/* Jump into zero page thread */
|
||||
MmZeroPageThreadMain(NULL);
|
||||
}
|
||||
/* Increase init phase */
|
||||
ExpInitializationPhase += 1;
|
||||
|
||||
/* Jump into zero page thread */
|
||||
MmZeroPageThreadMain(NULL);
|
||||
}
|
||||
/* EOF */
|
||||
|
|
|
@ -92,6 +92,12 @@ KiIsNpxPresent(
|
|||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KiIsNpxErrataPresent(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSetProcessorType(VOID);
|
||||
|
|
|
@ -37,6 +37,18 @@ typedef struct _DISPATCH_INFO
|
|||
PKINTERRUPT_ROUTINE *FlatDispatch;
|
||||
} 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
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
|
@ -113,7 +125,7 @@ extern KSPIN_LOCK BugCheckCallbackLock;
|
|||
extern KDPC KiExpireTimerDpc;
|
||||
extern KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];
|
||||
extern LIST_ENTRY KiTimerListHead;
|
||||
extern KMUTEX KiGenericCallDpcMutex;
|
||||
extern FAST_MUTEX KiGenericCallDpcMutex;
|
||||
extern LIST_ENTRY KiProfileListHead, KiProfileSourceListHead;
|
||||
extern KSPIN_LOCK KiProfileLock;
|
||||
extern LIST_ENTRY KiProcessListHead;
|
||||
|
@ -235,6 +247,13 @@ KiSelectNextThread(
|
|||
IN PKPRCB Prcb
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CPUID(
|
||||
OUT ULONG CpuInfo[4],
|
||||
IN ULONG InfoType
|
||||
);
|
||||
|
||||
/* gmutex.c ********************************************************************/
|
||||
|
||||
VOID
|
||||
|
|
|
@ -23,7 +23,7 @@ ULONG KiMinimumDpcRate = 3;
|
|||
ULONG KiAdjustDpcThreshold = 20;
|
||||
ULONG KiIdealDpcRate = 20;
|
||||
BOOLEAN KeThreadDpcEnable;
|
||||
KMUTEX KiGenericCallDpcMutex;
|
||||
FAST_MUTEX KiGenericCallDpcMutex;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
|
|
|
@ -340,6 +340,14 @@ KiGetFeatureBits(VOID)
|
|||
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 */
|
||||
CpuFeatures = Reg[3];
|
||||
}
|
||||
|
@ -354,6 +362,7 @@ KiGetFeatureBits(VOID)
|
|||
if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
|
||||
if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;
|
||||
if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;
|
||||
if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS;
|
||||
if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
|
||||
if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
|
||||
if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
|
||||
|
@ -389,6 +398,9 @@ KiGetFeatureBits(VOID)
|
|||
/* Check which extended features are available. */
|
||||
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 */
|
||||
switch (Vendor)
|
||||
{
|
||||
|
@ -741,8 +753,23 @@ ULONG_PTR
|
|||
NTAPI
|
||||
Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
|
||||
{
|
||||
/* FIXME: Support this */
|
||||
DPRINT1("Your machine supports XMMI exceptions but ReactOS doesn't\n");
|
||||
#if 0 // needs kitrap13
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -750,8 +777,34 @@ VOID
|
|||
NTAPI
|
||||
KiI386PentiumLockErrataFixup(VOID)
|
||||
{
|
||||
/* FIXME: Support this */
|
||||
DPRINT1("WARNING: Your machine has a CPU bug that ReactOS can't bypass!\n");
|
||||
KDESCRIPTOR IdtDescriptor;
|
||||
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 **********************************************************/
|
||||
|
|
|
@ -17,8 +17,56 @@
|
|||
#define Running 2
|
||||
#define WrDispatchInt 0x1F
|
||||
|
||||
Dividend: .float 4195835.0
|
||||
Divisor: .float 3145727.0
|
||||
Result1: .float 0
|
||||
Result2: .float 0
|
||||
|
||||
/* 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
|
||||
.func KiIsNpxPresent@0
|
||||
_KiIsNpxPresent@0:
|
||||
|
|
|
@ -30,15 +30,18 @@ KiInitMachineDependent(VOID)
|
|||
BOOLEAN FbCaching = FALSE;
|
||||
NTSTATUS Status;
|
||||
ULONG ReturnLength;
|
||||
ULONG i, Affinity;
|
||||
ULONG i, Affinity, Sample = 0;
|
||||
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 */
|
||||
if (KeFeatureBits & KF_LARGE_PAGE)
|
||||
{
|
||||
/* 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 */
|
||||
|
@ -70,6 +73,34 @@ KiInitMachineDependent(VOID)
|
|||
/* Assume no errata for now */
|
||||
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 */
|
||||
SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
|
||||
!KeI386NpxPresent;
|
||||
|
@ -148,18 +179,66 @@ KiInitMachineDependent(VOID)
|
|||
/* Start sampling loop */
|
||||
for (;;)
|
||||
{
|
||||
//
|
||||
// FIXME: TODO
|
||||
//
|
||||
break;
|
||||
/* Do a dummy CPUID to start the sample */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move on */
|
||||
CurrentSample++;
|
||||
Sample++;
|
||||
}
|
||||
|
||||
/* Save the CPU Speed */
|
||||
KeGetCurrentPrcb()->MHz = CurrentSample[-1].MHz;
|
||||
}
|
||||
|
||||
/* Check if we have MTRR without PAT */
|
||||
if (!(KeFeatureBits & KF_PAT) && (KeFeatureBits & KF_MTRR))
|
||||
/* Check if we have MTRR */
|
||||
if (KeFeatureBits & KF_MTRR)
|
||||
{
|
||||
/* 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 */
|
||||
|
@ -168,52 +247,53 @@ KiInitMachineDependent(VOID)
|
|||
/* Check if this is a buggy Pentium and apply the fixup if so */
|
||||
if (KiI386PentiumLockErrataPresent) KiI386PentiumLockErrataFixup();
|
||||
|
||||
/* Get the current thread NPX state */
|
||||
FxSaveArea = (PVOID)
|
||||
((ULONG_PTR)KeGetCurrentThread()->InitialStack -
|
||||
NPX_FRAME_LENGTH);
|
||||
/* Check if the CPU supports FXSR */
|
||||
if (KeFeatureBits & KF_FXSR)
|
||||
{
|
||||
/* Get the current thread NPX state */
|
||||
FxSaveArea = (PVOID)
|
||||
((ULONG_PTR)KeGetCurrentThread()->InitialStack -
|
||||
NPX_FRAME_LENGTH);
|
||||
|
||||
/* Clear initial MXCsr mask */
|
||||
FxSaveArea->U.FxArea.MXCsrMask = 0;
|
||||
/* Clear initial MXCsr mask */
|
||||
FxSaveArea->U.FxArea.MXCsrMask = 0;
|
||||
|
||||
/* Save the current NPX State */
|
||||
/* Save the current NPX State */
|
||||
#ifdef __GNUC__
|
||||
asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea));
|
||||
asm volatile("fxsave %0\n\t" : "=m" (*FxSaveArea));
|
||||
#else
|
||||
__asm fxsave [FxSaveArea]
|
||||
__asm fxsave [FxSaveArea]
|
||||
#endif
|
||||
/* Check if the current mask doesn't match the reserved bits */
|
||||
if (FxSaveArea->U.FxArea.MXCsrMask != MXCsrMask)
|
||||
{
|
||||
/* Then use whatever it's holding */
|
||||
MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask;
|
||||
}
|
||||
|
||||
/* Check if nobody set the kernel-wide mask */
|
||||
if (!KiMXCsrMask)
|
||||
{
|
||||
/* Then use the one we calculated above */
|
||||
NewMask = MXCsrMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the existing mask */
|
||||
NewMask = KiMXCsrMask;
|
||||
|
||||
/* Was it set to the same value we found now? */
|
||||
if (NewMask != MXCsrMask)
|
||||
/* Check if the current mask doesn't match the reserved bits */
|
||||
if (FxSaveArea->U.FxArea.MXCsrMask != 0)
|
||||
{
|
||||
/* No, something is definitely wrong */
|
||||
KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
|
||||
KF_FXSR,
|
||||
NewMask,
|
||||
MXCsrMask,
|
||||
0);
|
||||
/* Then use whatever it's holding */
|
||||
MXCsrMask = FxSaveArea->U.FxArea.MXCsrMask;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the kernel mask */
|
||||
KiMXCsrMask = NewMask & MXCsrMask;
|
||||
/* Check if nobody set the kernel-wide mask */
|
||||
if (!KiMXCsrMask)
|
||||
{
|
||||
/* Then use the one we calculated above */
|
||||
KiMXCsrMask = MXCsrMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Was it set to the same value we found now? */
|
||||
if (KiMXCsrMask != MXCsrMask)
|
||||
{
|
||||
/* No, something is definitely wrong */
|
||||
KEBUGCHECKEX(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
|
||||
KF_FXSR,
|
||||
KiMXCsrMask,
|
||||
MXCsrMask,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set the kernel mask */
|
||||
KiMXCsrMask &= MXCsrMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +322,7 @@ KiInitializePcr(IN ULONG ProcessorNumber,
|
|||
Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
||||
Pcr->NtTib.StackBase = 0;
|
||||
Pcr->NtTib.StackLimit = 0;
|
||||
Pcr->NtTib.Self = 0;
|
||||
Pcr->NtTib.Self = NULL;
|
||||
|
||||
/* Set the Current Thread */
|
||||
Pcr->PrcbData.CurrentThread = IdleThread;
|
||||
|
@ -282,7 +362,11 @@ KiInitializePcr(IN ULONG ProcessorNumber,
|
|||
Pcr->GDT = (PVOID)Gdt;
|
||||
Pcr->IDT = Idt;
|
||||
Pcr->TSS = Tss;
|
||||
Pcr->TssCopy = Tss;
|
||||
Pcr->PrcbData.DpcStack = DpcStack;
|
||||
|
||||
/* Setup the processor set */
|
||||
Pcr->PrcbData.MultiThreadProcessorSet = Pcr->PrcbData.SetMember;
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -299,6 +383,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
LARGE_INTEGER PageDirectory;
|
||||
PVOID DpcStack;
|
||||
ULONG NXSupportPolicy;
|
||||
ULONG Vendor[3];
|
||||
|
||||
/* Detect and set the CPU Type */
|
||||
KiSetProcessorType();
|
||||
|
@ -319,19 +404,19 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
FeatureBits = KiGetFeatureBits();
|
||||
|
||||
/* Set the default NX policy (opt-in) */
|
||||
NXSupportPolicy = 2;
|
||||
NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
|
||||
|
||||
/* Check if NPX is always on */
|
||||
if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
|
||||
{
|
||||
/* Set it always on */
|
||||
NXSupportPolicy = 1;
|
||||
NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
|
||||
FeatureBits |= KF_NX_ENABLED;
|
||||
}
|
||||
else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
|
||||
{
|
||||
/* Set it in opt-out mode */
|
||||
NXSupportPolicy = 3;
|
||||
NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
|
||||
FeatureBits |= KF_NX_ENABLED;
|
||||
}
|
||||
else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
|
||||
|
@ -344,7 +429,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
(strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
|
||||
{
|
||||
/* Set disabled mode */
|
||||
NXSupportPolicy = 0;
|
||||
NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF;
|
||||
FeatureBits |= KF_NX_DISABLED;
|
||||
}
|
||||
|
||||
|
@ -372,18 +457,32 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
KeI386NpxPresent = NpxPresent;
|
||||
KeI386CpuType = Prcb->CpuType;
|
||||
KeI386CpuStep = Prcb->CpuStep;
|
||||
KeProcessorArchitecture = 0;
|
||||
KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
|
||||
KeProcessorLevel = (USHORT)Prcb->CpuType;
|
||||
if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
|
||||
KeFeatureBits = FeatureBits;
|
||||
KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? 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 */
|
||||
Prcb->MultiThreadSetMaster = Prcb;
|
||||
|
||||
/* Lower to APC_LEVEL */
|
||||
KfLowerIrql(APC_LEVEL);
|
||||
KeLowerIrql(APC_LEVEL);
|
||||
|
||||
/* Initialize some spinlocks */
|
||||
KeInitializeSpinLock(&KiFreezeExecutionLock);
|
||||
|
@ -499,7 +598,9 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
KeSetPriorityThread(InitThread, 0);
|
||||
|
||||
/* If there's no thread scheduled, put this CPU in the Idle summary */
|
||||
KiAcquirePrcbLock(Prcb);
|
||||
if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
|
||||
KiReleasePrcbLock(Prcb);
|
||||
|
||||
/* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
|
||||
KfRaiseIrql(HIGH_LEVEL);
|
||||
|
@ -683,11 +784,6 @@ AppCpuInit:
|
|||
/* Set the right wait IRQL */
|
||||
KeGetCurrentThread()->WaitIrql = DISPATCH_LEVEL;
|
||||
|
||||
/* Set idle thread as running on UP builds */
|
||||
#ifndef CONFIG_SMP
|
||||
KeGetCurrentThread()->State = Running;
|
||||
#endif
|
||||
|
||||
/* Jump into the idle loop */
|
||||
KiIdleLoop();
|
||||
}
|
||||
|
|
|
@ -59,5 +59,5 @@ NTAPI
|
|||
KiInitializePAT(VOID)
|
||||
{
|
||||
/* 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");
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ KiInitSystem(VOID)
|
|||
InitializeListHead(&KiStackInSwapListHead);
|
||||
|
||||
/* Initialize the mutex for generic DPC calls */
|
||||
KeInitializeMutex(&KiGenericCallDpcMutex, 0);
|
||||
ExInitializeFastMutex(&KiGenericCallDpcMutex);
|
||||
|
||||
/* Initialize the syscall table */
|
||||
KeServiceDescriptorTable[0].Base = MainSSDT;
|
||||
|
@ -183,7 +183,7 @@ KiInitSpinLocks(IN PKPRCB Prcb,
|
|||
Prcb->QueueIndex = 1;
|
||||
Prcb->ReadySummary = 0;
|
||||
Prcb->DeferredReadyListHead.Next = NULL;
|
||||
for (i = 0; i < 32; i++)
|
||||
for (i = 0; i < MAXIMUM_PRIORITY; i++)
|
||||
{
|
||||
/* Initialize the ready list */
|
||||
InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
|
||||
|
@ -246,10 +246,14 @@ KiInitSpinLocks(IN PKPRCB Prcb,
|
|||
{
|
||||
/* Initialize the lock and setup the Queued Spinlock */
|
||||
KeInitializeSpinLock(&KiTimerTableLock[i]);
|
||||
Prcb->LockQueue[i].Next = NULL;
|
||||
Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
|
||||
Prcb->LockQueue[LockQueueTimerTableLock + i].Next = NULL;
|
||||
Prcb->LockQueue[LockQueueTimerTableLock + i].Lock =
|
||||
&KiTimerTableLock[i];
|
||||
}
|
||||
|
||||
/* Initialize the PRCB lock */
|
||||
KeInitializeSpinLock(&Prcb->PrcbLock);
|
||||
|
||||
/* Check if this is the boot CPU */
|
||||
if (!Number)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue