DPRINT1("PAT support detected but not yet taken advantage of!\n");
}
+ /* Allocate the IOPM save area. */
+// Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
+// PAGE_SIZE * 2,
+// TAG('K', 'e', ' ', ' '));
+// if (!Ki386IopmSaveArea)
+// {
+// /* Bugcheck. We need this for V86/VDM support. */
+// KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
+// }
}
/* Set the Processor Number and current Processor Mask */
Pcr->Prcb.Number = (UCHAR)ProcessorNumber;
- Pcr->Prcb.SetMember = 1 << ProcessorNumber;
+ Pcr->Prcb.SetMember = 1ULL << ProcessorNumber;
/* Get GDT and IDT descriptors */
__sgdt(&GdtDescriptor.Limit);
Pcr->Irql = PASSIVE_LEVEL;
KeSetCurrentIrql(PASSIVE_LEVEL);
+ /* Set GS base */
+ __writemsr(X86_MSR_GSBASE, (ULONG64)Pcr);
+ __writemsr(X86_MSR_KERNEL_GSBASE, (ULONG64)Pcr);
}
VOID
NTAPI
-KiInitializeCpuFeatures(ULONG Cpu)
+KiInitializeCpu(PKPRCB Prcb)
{
ULONG FeatureBits;
+ /* Detect and set the CPU Type */
+ KiSetProcessorType();
+
/* Get the processor features for this CPU */
FeatureBits = KiGetFeatureBits();
FeatureBits |= KF_NX_ENABLED;
/* Save feature bits */
- KeGetCurrentPrcb()->FeatureBits = FeatureBits;
+ Prcb->FeatureBits = FeatureBits;
/* Enable fx save restore support */
__writecr4(__readcr4() | CR4_FXSR);
/* Disable x87 fpu exceptions */
__writecr0(__readcr0() & ~CR0_NE);
-
+
+ /* LDT is unused */
+ __lldt(0);
}
VOID
-NTAPI
-KiInitializeKernel(IN PKPROCESS InitProcess,
- IN PKTHREAD InitThread,
- IN PVOID IdleStack,
- IN PKPRCB Prcb,
- IN CCHAR Number,
- IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+FASTCALL
+KiInitializeTss(IN PKTSS64 Tss,
+ IN UINT64 Stack)
{
- ULONG PageDirectory[2];
- PVOID DpcStack;
+ PKGDTENTRY64 TssEntry;
- /* Detect and set the CPU Type */
- KiSetProcessorType();
+ /* Get pointer to the GDT entry */
+ TssEntry = KiGetGdtEntry(KeGetPcr()->GdtBase, KGDT64_SYS_TSS);
- /* Initialize the Power Management Support for this PRCB */
-// PoInitializePrcb(Prcb);
+ /* Initialize the GDT entry */
+ KiInitGdtEntry(TssEntry, (ULONG64)Tss, sizeof(KTSS64), AMD64_TSS, 0);
- /* Save CPU state */
- KiSaveProcessorControlState(&Prcb->ProcessorState);
+ /* Zero out the TSS */
+ RtlZeroMemory(Tss, sizeof(KTSS64));
- /* Get cache line information for this CPU */
- KiGetCacheInformation();
+ /* FIXME: I/O Map? */
+ Tss->IoMapBase = 0x68;
- /* Initialize spinlocks and DPC data */
- KiInitSpinLocks(Prcb, Number);
+ /* Setup ring 0 stack pointer */
+ Tss->Rsp0 = Stack;
- /* Check if this is the Boot CPU */
- if (Number == 0)
- {
- /* Set Node Data */
- KeNodeBlock[0] = &KiNode0;
- Prcb->ParentNode = KeNodeBlock[0];
- KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
-
- /* Set boot-level flags */
- KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
- KeProcessorLevel = (USHORT)Prcb->CpuType;
- if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
-
- /* Set the current MP Master KPRCB to the Boot PRCB */
- Prcb->MultiThreadSetMaster = Prcb;
-
- /* Lower to APC_LEVEL */
- KeLowerIrql(APC_LEVEL);
-
- /* Initialize some spinlocks */
- KeInitializeSpinLock(&KiFreezeExecutionLock);
-
- /* Initialize portable parts of the OS */
- KiInitSystem();
-
- /* Initialize the Idle Process and the Process Listhead */
- InitializeListHead(&KiProcessListHead);
- PageDirectory[0] = 0;
- PageDirectory[1] = 0;
- KeInitializeProcess(InitProcess,
- 0,
- 0xFFFFFFFF,
- PageDirectory,
- FALSE);
- InitProcess->QuantumReset = MAXCHAR;
- }
- else
- {
- /* FIXME */
- DPRINT1("SMP Boot support not yet present\n");
- }
+ /* Setup a stack for Double Fault Traps */
+ Tss->Ist[1] = (ULONG64)KiDoubleFaultStack;
+
+ /* Setup a stack for CheckAbort Traps */
+ Tss->Ist[2] = (ULONG64)KiDoubleFaultStack;
- /* HACK for MmUpdatePageDir */
- ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
-
- /* Setup the Idle Thread */
- KeInitializeThread(InitProcess,
- InitThread,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- IdleStack);
-
- InitThread->NextProcessor = Number;
- InitThread->Priority = HIGH_PRIORITY;
- InitThread->State = Running;
- InitThread->Affinity = 1 << Number;
- InitThread->WaitIrql = DISPATCH_LEVEL;
- InitProcess->ActiveProcessors = 1 << Number;
+ /* Setup a stack for NMI Traps */
+ Tss->Ist[3] = (ULONG64)KiDoubleFaultStack;
+
+ /* Load the task register */
+ __ltr(KGDT64_SYS_TSS);
+}
+
+VOID
+NTAPI
+INIT_FUNCTION
+KiInitializeKernelMachineDependent(
+ IN PKPRCB Prcb,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ /* Set boot-level flags */
+ KeI386CpuType = Prcb->CpuType;
+ KeI386CpuStep = Prcb->CpuStep;
+ KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
+ KeProcessorLevel = (USHORT)Prcb->CpuType;
+ if (Prcb->CpuID) KeProcessorRevision = Prcb->CpuStep;
/* Set basic CPU Features that user mode can read */
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
- (KeFeatureBits & KF_MMX) ? TRUE: FALSE;
- SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
- (KeFeatureBits & KF_CMPXCHG8B) ? TRUE: FALSE;
+ (Prcb->FeatureBits & KF_MMX) ? TRUE: FALSE;
+ SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
- ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI)) ? TRUE: FALSE;
+ ((Prcb->FeatureBits & KF_FXSR) && (Prcb->FeatureBits & KF_XMMI)) ? TRUE: FALSE;
SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
- ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI64)) ? TRUE: FALSE;
+ ((Prcb->FeatureBits & KF_FXSR) && (Prcb->FeatureBits & KF_XMMI64)) ? TRUE: FALSE;
SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
- (KeFeatureBits & KF_3DNOW) ? TRUE: FALSE;
- SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] =
- (KeFeatureBits & KF_RDTSC) ? TRUE: FALSE;
+ (Prcb->FeatureBits & KF_3DNOW) ? TRUE: FALSE;
+ SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
- /* Set up the thread-related fields in the PRCB */
- Prcb->CurrentThread = InitThread;
- Prcb->NextThread = NULL;
- Prcb->IdleThread = InitThread;
+ /* Set the default NX policy (opt-in) */
+ SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
- /* Initialize the Kernel Executive */
- ExpInitializeExecutive(Number, LoaderBlock);
-
- /* Only do this on the boot CPU */
- if (Number == 0)
+ /* Check if NPX is always on */
+ if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSON"))
+ {
+ /* Set it always on */
+ SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON;
+ Prcb->FeatureBits |= KF_NX_ENABLED;
+ }
+ else if (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTOUT"))
+ {
+ /* Set it in opt-out mode */
+ SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT;
+ Prcb->FeatureBits |= KF_NX_ENABLED;
+ }
+ else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=OPTIN")) ||
+ (strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE")))
+ {
+ /* Set the feature bits */
+ Prcb->FeatureBits |= KF_NX_ENABLED;
+ }
+ else if ((strstr(KeLoaderBlock->LoadOptions, "NOEXECUTE=ALWAYSOFF")) ||
+ (strstr(KeLoaderBlock->LoadOptions, "EXECUTE")))
{
- /* Calculate the time reciprocal */
- KiTimeIncrementReciprocal =
- KiComputeReciprocal(KeMaximumIncrement,
- &KiTimeIncrementShiftCount);
+ /* Set disabled mode */
+ SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF;
+ Prcb->FeatureBits |= KF_NX_DISABLED;
+ }
- /* Update DPC Values in case they got updated by the executive */
- Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
- Prcb->MinimumDpcRate = KiMinimumDpcRate;
- Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
+}
- /* Allocate the DPC Stack */
- DpcStack = MmCreateKernelStack(FALSE, 0);
- if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
- Prcb->DpcStack = DpcStack;
+static LDR_DATA_TABLE_ENTRY LdrCoreEntries[3];
- /* Allocate the IOPM save area. */
-// Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
-// PAGE_SIZE * 2,
-// TAG('K', 'e', ' ', ' '));
-// if (!Ki386IopmSaveArea)
-// {
-// /* Bugcheck. We need this for V86/VDM support. */
-// KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
-// }
- }
+void
+KiInitModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ PLIST_ENTRY Entry;
+ ULONG i;
- /* Raise to Dispatch */
- KfRaiseIrql(DISPATCH_LEVEL);
+ /* Initialize the list head */
+ InitializeListHead(&PsLoadedModuleList);
- /* Set the Idle Priority to 0. This will jump into Phase 1 */
- KeSetPriorityThread(InitThread, 0);
+ /* Loop the first 3 entries */
+ for (Entry = LoaderBlock->LoadOrderListHead.Flink, i = 0;
+ Entry != &LoaderBlock->LoadOrderListHead && i < 3;
+ Entry = Entry->Flink, i++)
+ {
+ /* Get the data table entry */
+ LdrEntry = CONTAINING_RECORD(Entry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
- /* If there's no thread scheduled, put this CPU in the Idle summary */
- KiAcquirePrcbLock(Prcb);
- if (!Prcb->NextThread) KiIdleSummary |= 1 << Number;
- KiReleasePrcbLock(Prcb);
+ /* Copy the entry */
+ LdrCoreEntries[i] = *LdrEntry;
- /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */
- KfRaiseIrql(HIGH_LEVEL);
- LoaderBlock->Prcb = 0;
+ /* Insert the copy into the list */
+ InsertTailList(&PsLoadedModuleList, &LdrCoreEntries[i].InLoadOrderLinks);
+ }
}
VOID
NTAPI
KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
- ULONG Cpu;
+ CCHAR Cpu;
PKTHREAD InitialThread;
ULONG64 InitialStack;
PKIPCR Pcr;
KeLoaderBlock = LoaderBlock;
/* Get the current CPU number */
- Cpu = KeNumberProcessors++; // FIXME
+ Cpu = (CCHAR)KeNumberProcessors++; // FIXME
/* LoaderBlock initialization for Cpu 0 */
if (Cpu == 0)
{
+ FrLdrDbgPrint("LoaderBlock->Prcb=%p\n", LoaderBlock->Prcb);
/* Set the initial stack, idle thread and process */
LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack;
LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread;
/* Set the PRCB for this Processor */
KiProcessorBlock[Cpu] = &Pcr->Prcb;
- /* Set GS base */
- __writemsr(X86_MSR_GSBASE, (ULONG64)Pcr);
- __writemsr(X86_MSR_KERNEL_GSBASE, (ULONG64)Pcr);
-
- /* LDT is unused */
- __lldt(0);
-
/* Align stack to 16 bytes */
LoaderBlock->KernelStack &= ~(16 - 1);
InitialStack = LoaderBlock->KernelStack; // Checkme
InitialThread = (PKTHREAD)LoaderBlock->Thread;
- /* Clean the APC List Head */
- InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]);
-
/* Set us as the current process */
InitialThread->ApcState.Process = (PVOID)LoaderBlock->Process;
KiInitializePcr(Pcr, Cpu, InitialThread, (PVOID)KiDoubleFaultStack);
/* Initialize the CPU features */
- KiInitializeCpuFeatures(Cpu);
+ KiInitializeCpu(&Pcr->Prcb);
/* Initial setup for the boot CPU */
if (Cpu == 0)
{
+ /* Initialize the module list (ntos, hal, kdcom) */
+ KiInitModuleList(LoaderBlock);
+
/* Setup the TSS descriptors and entries */
KiInitializeTss(Pcr->TssBase, InitialStack);
/* Setup the IDT */
KeInitExceptions();
- /* HACK: misuse this function to pass a function pointer to kdcom */
- KdDebuggerInitialize1((PVOID)FrLdrDbgPrint);
-
- /* Initialize debugging system */
+ /* Initialize debugging system */
KdInitSystem(0, KeLoaderBlock);
/* Check for break-in */
if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
/* Hack! Wait for the debugger! */
-#ifdef _WINKD_
+#ifdef _WINKD_x
while (!KdPollBreakIn());
DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
#endif
}
- DPRINT("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n",
+ DPRINT1("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n",
Pcr, Pcr->GdtBase, Pcr->IdtBase, Pcr->TssBase);
/* Acquire lock */
{
/* Loop until lock is free */
while ((*(volatile KSPIN_LOCK*)&KiFreezeExecutionLock) & 1);
- }
+ }
/* Initialize the Processor with HAL */
HalInitializeProcessor(Cpu, KeLoaderBlock);
/* Set processor as active */
- KeActiveProcessors |= 1 << Cpu;
+ KeActiveProcessors |= 1ULL << Cpu;
/* Release lock */
InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0);
/* Raise to HIGH_LEVEL */
KfRaiseIrql(HIGH_LEVEL);
+ /* Machine specific kernel initialization */
+ if (Cpu == 0) KiInitializeKernelMachineDependent(&Pcr->Prcb, LoaderBlock);
+
/* Switch to new kernel stack and start kernel bootstrapping */
- KiSetupStackAndInitializeKernel(&KiInitialProcess.Pcb,
- InitialThread,
- (PVOID)InitialStack,
- &Pcr->Prcb,
- (CCHAR)Cpu,
- KeLoaderBlock);
+ KiSwitchToBootStack(InitialStack & ~3);
}
-
-VOID
-NTAPI
-KiInitializeKernelAndGotoIdleLoop(IN PKPROCESS InitProcess,
- IN PKTHREAD InitThread,
- IN PVOID IdleStack,
- IN PKPRCB Prcb,
- IN CCHAR Number,
- IN PLOADER_PARAMETER_BLOCK LoaderBlock)
-{
-// DbgBreakPointWithStatus(0);
-
- /* Initialize kernel */
- KiInitializeKernel(InitProcess,
- InitThread,
- IdleStack,
- Prcb,
- Number,
- KeLoaderBlock);
-
- /* Set the priority of this thread to 0 */
- InitThread->Priority = 0;
-
- /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
- _enable();
- KeLowerIrql(DISPATCH_LEVEL);
-
- /* Set the right wait IRQL */
- InitThread->WaitIrql = DISPATCH_LEVEL;
-
- /* Jump into the idle loop */
- KiIdleLoop();
-}