@@:
nop ; 留一个位置给int3指令
; 设置初始化的IRQL = HIGH_LEVEL RaiseIrql HIGH_LEVEL mov KissIrql, al
or _KiBootFeatureBits, KF_CMPXCHG8B ; CMPXCHG8B是XP的一个标识
;初始化ebp,esp和其他参数寄存器,为初始化内核做准备 mov ebx, KissIdleThread mov edx, KissIdleStack mov eax, KissPbNumber
and edx, NOT 3h ; 4字节边界对齐
xor ebp, ebp ; (ebp) = 0. 没有更多的栈帧了 mov esp, edx
; 为空闲线程栈NPX_SAVE_AREA预留空间并初始化
subesp, NPX_FRAME_LENGTH+KTRAP_FRAME_LENGTH+KTRAP_FRAME_ALIGN push CR0_EM+CR0_TS+CR0_MP ; 为Cr0NpxState预留空间
; arg6 - LoaderBlock ; arg5 - processor number ; arg4 - addr of prcb ; arg3 - idle thread's stack ; arg2 - addr of current thread obj ; arg1 - addr of current process obj ; 初始化系统数据结构和HAL
stdCall _KiInitializeKernel,
mov ebx,PCR[PcPrcbData+PbCurrentThread] ; 设置空闲线程的地址 mov byte ptr [ebx]+ThPriority, 0 ; 设置优先级为0
; Control is returned to the idle thread with IRQL at HIGH_LEVEL. Lower IRQL ; to DISPATCH_LEVEL and set wait IRQL of idle thread. sti
LowerIrql DISPATCH_LEVEL
mov byte ptr [ebx]+ThWaitIrql, DISPATCH_LEVEL
// KiInitializeKernel函数返回以后,启动中断,将IRQL降低为DISPATCH_LEVEL // 从而允许线程调度器选择新的线程
mov ebx, PCR[PcSelfPcr] ; 获取PCR的地址
; 在一个多处理器系统中,引导处理器直接进入空闲循环.而其他的处理器不会直接进入空闲循环; ; 而是等到所有处理器已经开启并且引导主扇区允许进入为止;
; 屏障KiBarrierWait对于系统的第一个处理器并不起作用,而仅对后续的处理器起作用
ifndef NT_UP
@@: cmp _KiBarrierWait, 0 ; 判断是否设置了KiBarrierWait YIELD
jnz short @b endif
push 0
jmp @KiIdleLoop@0 ; 进入空闲循环
stdENDP _KiSystemStartup
1.2 内核初始化
内核的初始化主要是内核各个组件的初始化,但由于这些内核组件之间有紧密的耦合关系,所以它们的初始化并不是简单地顺序执行初始化。为了解决在初始化过程中的相互依赖性问题,内核的初始化分两个阶段进行,称为阶段0和阶段1。大多数内核组件的初始化函数相应地带有一个整数参数,以指明一次调用是阶段0 初始化还是阶段1 初始化,而有些组件的初始化函数通过检查一个全局变量InitializationPhase 的值来判断当前处于哪个阶段。
我们首先来看阶段0 初始化。阶段0 初始化的目的是,将阶段1 初始化所要用到的基本数据结构建立起来。在阶段0 初始化过程中,中断被禁止,因此处理器可以顺序地执行自己的初始化逻辑。KiSystemStartup 函数首先初始化处理器的状态,包括调整它的IDT,初始化TSS(Task State Segment),以及构造PCR(Processor Control Region)。然后,调用HalInitializeProcessor 函数,为当前处理器初始化其HAL 中的PCR 和处理器间中断向量;接着调用KiInitializeKernel 函数,执行内核初始化。最后,当前线程蜕变成一个空闲线程。
因此,KiInitializeKernel 函数是实际执行内核初始化的函数,其代码位于base\\ntos\\ke\\i386\\kernlini.c 文件中。它的职责是:初始化内核数据结构,初始化空闲线程和进程对象,初始化PCR,然后调用执行体初始化函数ExpInitializeExecutive,最后返回。
VOID
KiInitializeKernel ( INPKPROCESSProcess, INPKTHREADThread, INPVOIDIdleStack, INPKPRCBPrcb, INCCHARNumber,
PLOADER_PARAMETER_BLOCKLoaderBlock ) {
ULONGDirectoryTableBase[2]; PVOIDDpcStack; KIRQLOldIrql; PKPCRPcr;
BOOLEANNpxFlag;
#if !defined(NT_UP)
BOOLEANFxsrPresent; BOOLEANXMMIPresent; #endif
ULONGFeatureBits;
#ifdefined(KE_MULTINODE)
LONG Index; #endif
KiSetProcessorType(); KiSetCR0Bits();
NpxFlag = KiIsNpxPresent(); Pcr = KeGetPcr();
// 初始化处理器的电源状态 PoInitializePrcb(Prcb);
// 检测不支持的处理器的版本 if (Prcb->CpuType == 3) {
KeBugCheckEx(UNSUPPORTED_PROCESSOR,0x386,0,0,0); }
// 获取处理器相关特性
FeatureBits = KiGetFeatureBits();
//如果主机处理器支持特性,那么在加载选项中设置开启不可执行保护 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;
if (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON; FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;
} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT; FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;
} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;
} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF; FeatureBits |= KF_GLOBAL_32BIT_EXECUTE;
} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;
} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF; FeatureBits |= KF_GLOBAL_32BIT_EXECUTE; }
#ifdefined (_X86PAE_)
if ((FeatureBits & KF_NOEXECUTE) == 0) {
FeatureBits &= ~KF_GLOBAL_32BIT_NOEXECUTE; }
if ((FeatureBits & KF_GLOBAL_32BIT_NOEXECUTE) != 0) { KiEnableNXSupport(); } #endif
Prcb->FeatureBits = FeatureBits;
// 初始化PRCB中的ProcessorControlSpace内容,使得本地内核调试器可以像GDT一样获得数据 KiSaveProcessorControlState(&Prcb->ProcessorState);
// 获得处理器缓存大小信息 KiGetCacheInformation();
// 初始化每个处理器的锁数据 KiInitSpinLocks(Prcb, Number);
// 如果初始的处理器已经被初始化,那么初始化每个系统数据结构 if (Number == 0) {
KeNodeBlock[0] = &KiNode0;
#ifdefined(KE_MULTINODE)
for (Index = 1; Index < MAXIMUM_CCNUMA_NODES; Index++) {
//
// Set temporary node. //
KeNodeBlock[Index] = &KiNodeInit[Index]; } #endif
Prcb->ParentNode = KeNodeBlock[0];
KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
// Initial setting for global Cpu & Stepping levels KeI386NpxPresent = NpxFlag; KeI386CpuType = Prcb->CpuType; KeI386CpuStep = Prcb->CpuStep;
KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; KeProcessorLevel = (USHORT)Prcb->CpuType; if (Prcb->CpuID == 0) { KeProcessorRevision = 0xFF00 |
(((Prcb->CpuStep>> 4) + 0xa0 ) & 0x0F0) | (Prcb->CpuStep& 0xf); } else {
KeProcessorRevision = Prcb->CpuStep; }
KeFeatureBits = FeatureBits;
KeI386FxsrPresent = ((KeFeatureBits&KF_FXSR) ? TRUE:FALSE); KeI386XMMIPresent = ((KeFeatureBits&KF_XMMI) ? TRUE:FALSE);
// As of Windows XP, cmpxchg8b is a required instruction. if ((KeFeatureBits&KF_ ) == 0) {
ULONGVendor[3];
RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor)); KeBugCheckEx(UNSUPPORTED_PROCESSOR, (1 << 24 )
| (Prcb->CpuType<< 16) | Prcb->CpuStep, Vendor[0], Vendor[1], Vendor[2]); }
// 初始化兼容锁
…
//此处省略部分无关代码
// Performance architecture independent initialization. KiInitSystem();
// 初始化空闲线程和进程对象 DirectoryTableBase[0] = 0; DirectoryTableBase[1] = 0;
InitializeListHead(&KiProcessListHead); KeInitializeProcess(Process,
(KPRIORITY)0, (KAFFINITY)(0xffffffff), &DirectoryTableBase[0], FALSE);
Process->QuantumReset = MAXCHAR;//此处设置为最大值
KeInitializeSpinLock(&Ki486CompatibilityLock);
// 初始化内核自旋锁
KeInitializeSpinLock(&KiFreezeExecutionLock);
// 降低IRQL到APC级别 KeLowerIrql(APC_LEVEL);