Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

670 lines
18 KiB

  1. title "System Startup"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989, 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; systembg.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code necessary to initially startup the
  13. ; NT system.
  14. ;
  15. ; Author:
  16. ;
  17. ; Shie-Lin Tzong (shielint) 07-Mar-1990
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ; Revision History:
  24. ;
  25. ; John Vert (jvert) 25-Jun-1991
  26. ; Major overhaul in order to move into new osloader architecture
  27. ; Removed old debugger hacks
  28. ;
  29. ;--
  30. .386p
  31. .xlist
  32. include ks386.inc
  33. include i386\kimacro.inc
  34. include mac386.inc
  35. include callconv.inc
  36. .list
  37. option segment:flat
  38. extrn _KiBootFeatureBits:DWORD
  39. EXTRNP _KdInitSystem,2
  40. EXTRNP _KdPollBreakIn,0
  41. EXTRNP KfRaiseIrql,1,IMPORT,FASTCALL
  42. EXTRNP KfLowerIrql,1,IMPORT,FASTCALL
  43. EXTRNP _KiInitializeKernel,6
  44. EXTRNP GetMachineBootPointers
  45. EXTRNP KiIdleLoop,0,,FASTCALL
  46. EXTRNP _KiInitializePcr,7
  47. EXTRNP _KiSwapIDT
  48. EXTRNP _KiInitializeTSS,1
  49. EXTRNP _KiInitializeTSS2,2
  50. extrn _KiTrap08:PROC
  51. extrn _KiTrap02:PROC
  52. EXTRNP _KiInitializeAbios,1
  53. EXTRNP _KiInitializeMachineType
  54. EXTRNP _HalInitializeProcessor,2,IMPORT
  55. if NT_INST
  56. EXTRNP _KiAcquireSpinLock, 1
  57. EXTRNP _KiReleaseSpinLock, 1
  58. endif
  59. extrn _KiFreezeExecutionLock:DWORD
  60. extrn _IDT:BYTE
  61. extrn _IDTLEN:BYTE ; NOTE - really an ABS, linker problems
  62. extrn _KeNumberProcessors:BYTE
  63. extrn _KeActiveProcessors:DWORD
  64. extrn _KeLoaderBlock:DWORD
  65. extrn _KiIdleProcess:BYTE
  66. extrn _KiIdleThread0:BYTE
  67. ifndef NT_UP
  68. extrn _KiBarrierWait:DWORD
  69. EXTRNP _KiProcessorStart
  70. endif
  71. ;
  72. ; Constants for various variables
  73. ;
  74. _DATA SEGMENT PARA PUBLIC 'DATA'
  75. ;
  76. ; Statically allocated structures for Bootstrap processor
  77. ; double fault stack for P0
  78. ; idle thread stack for P0
  79. ;
  80. align 16
  81. public _KiDoubleFaultStack
  82. db DOUBLE_FAULT_STACK_SIZE dup (?)
  83. _KiDoubleFaultStack label byte
  84. public P0BootStack
  85. db KERNEL_STACK_SIZE dup (?)
  86. P0BootStack label byte
  87. ;
  88. ; Double fault task stack
  89. ;
  90. MINIMUM_TSS_SIZE EQU TssIoMaps
  91. align 16
  92. public _KiDoubleFaultTSS
  93. _KiDoubleFaultTSS label byte
  94. db MINIMUM_TSS_SIZE dup(0)
  95. public _KiNMITSS
  96. _KiNMITSS label byte
  97. db MINIMUM_TSS_SIZE dup(0)
  98. ;
  99. ; Abios specific definitions
  100. ;
  101. public _KiCommonDataArea, _KiAbiosPresent
  102. _KiCommonDataArea dd 0
  103. _KiAbiosPresent dd 0
  104. _DATA ends
  105. page ,132
  106. subttl "System Startup"
  107. INIT SEGMENT DWORD PUBLIC 'CODE'
  108. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  109. ;++
  110. ;
  111. ; For processor 0, Routine Description:
  112. ;
  113. ; This routine is called when the NT system begins execution.
  114. ; Its function is to initialize system hardware state, call the
  115. ; kernel initialization routine, and then fall into code that
  116. ; represents the idle thread for all processors.
  117. ;
  118. ; Entry state created by the boot loader:
  119. ; A short-form IDT (0-1f) exists and is active.
  120. ; A complete GDT is set up and loaded.
  121. ; A complete TSS is set up and loaded.
  122. ; Page map is set up with minimal start pages loaded
  123. ; The lower 4Mb of virtual memory are directly mapped into
  124. ; physical memory.
  125. ;
  126. ; The system code (ntoskrnl.exe) is mapped into virtual memory
  127. ; as described by its memory descriptor.
  128. ; DS=ES=SS = flat
  129. ; ESP->a usable boot stack
  130. ; Interrupts OFF
  131. ;
  132. ; For processor > 0, Routine Description:
  133. ;
  134. ; This routine is called when each additional processor begins execution.
  135. ; The entry state for the processor is:
  136. ; IDT, GDT, TSS, stack, selectors, PCR = all valid
  137. ; Page directory is set to the current running directory
  138. ; LoaderBlock - parameters for this processor
  139. ;
  140. ; Arguments:
  141. ;
  142. ; PLOADER_PARAMETER_BLOCK LoaderBlock
  143. ;
  144. ; Return Value:
  145. ;
  146. ; None.
  147. ;
  148. ;--
  149. ;
  150. ; Arguments for KiSystemStartupPx
  151. ;
  152. KissLoaderBlock equ [ebp+8]
  153. ;
  154. ; Local variables
  155. ;
  156. KissGdt equ [ebp-4]
  157. KissPcr equ [ebp-8]
  158. KissTss equ [ebp-12]
  159. KissIdt equ [ebp-16]
  160. KissIrql equ [ebp-20]
  161. KissPbNumber equ [ebp-24]
  162. KissIdleStack equ [ebp-28]
  163. KissIdleThread equ [ebp-32]
  164. cPublicProc _KiSystemStartup ,1
  165. push ebp
  166. mov ebp, esp
  167. sub esp, 32 ; Reserve space for local variables
  168. mov ebx, dword ptr KissLoaderBlock
  169. mov _KeLoaderBlock, ebx ; Get loader block param
  170. movzx ecx, _KeNumberProcessors ; get number of processors
  171. mov KissPbNumber, ecx
  172. or ecx, ecx ; Is the the boot processor?
  173. jnz @f ; no
  174. ; P0 uses static memory for these
  175. mov dword ptr [ebx].LpbThread, offset _KiIdleThread0
  176. mov dword ptr [ebx].LpbKernelStack, offset P0BootStack
  177. push KGDT_R0_PCR ; P0 needs FS set
  178. pop fs
  179. ; Save processornumber in Prcb
  180. mov byte ptr fs:PcPrcbData+PbNumber, cl
  181. @@:
  182. mov eax, dword ptr [ebx].LpbThread
  183. mov dword ptr KissIdleThread, eax
  184. mov eax, dword ptr [ebx].LpbKernelStack
  185. mov dword ptr KissIdleStack, eax
  186. stdCall _KiInitializeMachineType
  187. cmp byte ptr KissPbNumber, 0 ; if not p0, then
  188. jne kiss_notp0 ; skip a bunch
  189. ;
  190. ;+++++++++++++++++++++++
  191. ;
  192. ; Initialize the PCR
  193. ;
  194. stdCall GetMachineBootPointers
  195. ;
  196. ; Upon return:
  197. ; (edi) -> gdt
  198. ; (esi) -> pcr
  199. ; (edx) -> tss
  200. ; (eax) -> idt
  201. ; Now, save them in our local variables
  202. ;
  203. mov KissGdt, edi
  204. mov KissPcr, esi
  205. mov KissTss, edx
  206. mov KissIdt, eax
  207. ;
  208. ; edit TSS to be 32bits. loader gives us a tss, but it's 16bits!
  209. ;
  210. lea ecx,[edi]+KGDT_TSS ; (ecx) -> TSS descriptor
  211. mov byte ptr [ecx+5],089h ; 32bit, dpl=0, present, TSS32, not busy
  212. ; KiInitializeTSS2(
  213. ; Linear address of TSS
  214. ; Linear address of TSS descriptor
  215. ; );
  216. stdCall _KiInitializeTSS2, <KissTss, ecx>
  217. stdCall _KiInitializeTSS, <KissTss>
  218. mov cx,KGDT_TSS
  219. ltr cx
  220. ;
  221. ; set up 32bit double fault task gate to catch double faults.
  222. ;
  223. mov eax,KissIdt
  224. lea ecx,[eax]+40h ; Descriptor 8
  225. mov byte ptr [ecx+5],085h ; dpl=0, present, taskgate
  226. mov word ptr [ecx+2],KGDT_DF_TSS
  227. lea ecx,[edi]+KGDT_DF_TSS
  228. mov byte ptr [ecx+5],089h ; 32bit, dpl=0, present, TSS32, not busy
  229. mov edx,offset FLAT:_KiDoubleFaultTSS
  230. mov eax,edx
  231. mov [ecx+KgdtBaseLow],ax
  232. shr eax,16
  233. mov [ecx+KgdtBaseHi],ah
  234. mov [ecx+KgdtBaseMid],al
  235. mov eax, MINIMUM_TSS_SIZE
  236. mov [ecx+KgdtLimitLow],ax
  237. ; KiInitializeTSS(
  238. ; address of double fault TSS
  239. ; );
  240. stdCall _KiInitializeTSS, <edx>
  241. mov eax,cr3
  242. mov [edx+TssCr3],eax
  243. mov eax, offset FLAT:_KiDoubleFaultStack
  244. mov dword ptr [edx+TssEsp],eax
  245. mov dword ptr [edx+TssEsp0],eax
  246. mov dword ptr [edx+020h],offset FLAT:_KiTrap08
  247. mov dword ptr [edx+024h],0 ; eflags
  248. mov word ptr [edx+04ch],KGDT_R0_CODE ; set value for CS
  249. mov word ptr [edx+058h],KGDT_R0_PCR ; set value for FS
  250. mov [edx+050h],ss
  251. mov word ptr [edx+048h],KGDT_R3_DATA OR RPL_MASK ; Es
  252. mov word ptr [edx+054h],KGDT_R3_DATA OR RPL_MASK ; Ds
  253. ;
  254. ; set up 32bit NMI task gate to catch NMI faults.
  255. ;
  256. mov eax,KissIdt
  257. lea ecx,[eax]+10h ; Descriptor 2
  258. mov byte ptr [ecx+5],085h ; dpl=0, present, taskgate
  259. mov word ptr [ecx+2],KGDT_NMI_TSS
  260. lea ecx,[edi]+KGDT_NMI_TSS
  261. mov byte ptr [ecx+5],089h ; 32bit, dpl=0, present, TSS32, not busy
  262. mov edx,offset FLAT:_KiNMITSS
  263. mov eax,edx
  264. mov [ecx+KgdtBaseLow],ax
  265. shr eax,16
  266. mov [ecx+KgdtBaseHi],ah
  267. mov [ecx+KgdtBaseMid],al
  268. mov eax, MINIMUM_TSS_SIZE
  269. mov [ecx+KgdtLimitLow],ax
  270. push edx
  271. stdCall _KiInitializeTSS,<edx> ; KiInitializeTSS(
  272. ; address TSS
  273. ; );
  274. ;
  275. ; We are using the DoubleFault stack as the DoubleFault stack and the
  276. ; NMI Task Gate stack and briefly, it is the DPC stack for the first
  277. ; processor.
  278. ;
  279. mov eax,cr3
  280. mov [edx+TssCr3],eax
  281. mov eax, offset FLAT:_KiDoubleFaultTSS
  282. mov eax, dword ptr [eax+038h] ; get DF stack
  283. mov dword ptr [edx+TssEsp0],eax ; use it for NMI stack
  284. mov dword ptr [edx+038h],eax
  285. mov dword ptr [edx+020h],offset FLAT:_KiTrap02
  286. mov dword ptr [edx+024h],0 ; eflags
  287. mov word ptr [edx+04ch],KGDT_R0_CODE ; set value for CS
  288. mov word ptr [edx+058h],KGDT_R0_PCR ; set value for FS
  289. mov [edx+050h],ss
  290. mov word ptr [edx+048h],KGDT_R3_DATA OR RPL_MASK ; Es
  291. mov word ptr [edx+054h],KGDT_R3_DATA OR RPL_MASK ; Ds
  292. stdCall _KiInitializePcr, <KissPbNumber,KissPcr,KissIdt,KissGdt,KissTss,KissIdleThread,offset FLAT:_KiDoubleFaultStack>
  293. ;
  294. ; set current process pointer in current thread object
  295. ;
  296. mov edx, KissIdleThread
  297. mov ecx, offset FLAT:_KiIdleProcess ; (ecx)-> idle process obj
  298. mov [edx]+ThApcState+AsProcess, ecx ; set addr of thread's process
  299. ;
  300. ; set up PCR: Teb, Prcb pointers. The PCR:InitialStack, and various fields
  301. ; of Prcb will be set up in _KiInitializeKernel
  302. ;
  303. mov dword ptr fs:PcTeb, 0 ; PCR->Teb = 0
  304. ;
  305. ; Initialize KernelDr7 and KernelDr6 to 0. This must be done before
  306. ; the debugger is called.
  307. ;
  308. mov dword ptr fs:PcPrcbData+PbProcessorState+PsSpecialRegisters+SrKernelDr6,0
  309. mov dword ptr fs:PcPrcbData+PbProcessorState+PsSpecialRegisters+SrKernelDr7,0
  310. ;
  311. ; Since the entries of Kernel IDT have their Selector and Extended Offset
  312. ; fields set up in the wrong order, we need to swap them back to the order
  313. ; which i386 recognizes.
  314. ; This is only done by the bootup processor.
  315. ;
  316. stdCall _KiSwapIDT ; otherwise, do the work
  317. ;
  318. ; Switch to R3 flat selectors that we want loaded so lazy segment
  319. ; loading will work.
  320. ;
  321. mov eax,KGDT_R3_DATA OR RPL_MASK ; Set RPL = ring 3
  322. mov ds,ax
  323. mov es,ax
  324. ;
  325. ; Now copy our trap handlers to replace kernel debugger's handlers.
  326. ;
  327. mov eax, KissIdt ; (eax)-> Idt
  328. push dword ptr [eax+40h] ; save double fault's descriptor
  329. push dword ptr [eax+44h]
  330. push dword ptr [eax+10h] ; save nmi fault's descriptor
  331. push dword ptr [eax+14h]
  332. mov edi,KissIdt
  333. mov esi,offset FLAT:_IDT
  334. mov ecx,offset FLAT:_IDTLEN ; _IDTLEN is really an abs, we use
  335. shr ecx,2
  336. rep movsd
  337. pop dword ptr [eax+14h] ; restore nmi fault's descriptor
  338. pop dword ptr [eax+10h]
  339. pop dword ptr [eax+44h] ; restore double fault's descriptor
  340. pop dword ptr [eax+40h]
  341. ifdef QLOCK_STAT_GATHER
  342. EXTRNP KiCaptureQueuedSpinlockRoutines,0,,FASTCALL
  343. fstCall KiCaptureQueuedSpinlockRoutines
  344. endif
  345. kiss_notp0:
  346. ifndef NT_UP
  347. ;
  348. ; Let the boot processor know this processor is starting.
  349. ;
  350. stdCall _KiProcessorStart
  351. endif
  352. ;
  353. ; A new processor can't come online while execution is frozen
  354. ; Take freezelock while adding a processor to the system
  355. ; NOTE: don't use SPINLOCK macro - it has debugger stuff in it
  356. ;
  357. if NT_INST
  358. lea eax, _KiFreezeExecutionLock
  359. stdCall _KiAcquireSpinLock, <eax>
  360. else
  361. @@: test _KiFreezeExecutionLock, 1
  362. jnz short @b
  363. lock bts _KiFreezeExecutionLock, 0
  364. jc short @b
  365. endif
  366. ;
  367. ; Add processor to active summary, and update BroadcastMasks
  368. ;
  369. mov ecx, dword ptr KissPbNumber ; mark this processor as active
  370. mov byte ptr fs:PcNumber, cl
  371. mov eax, 1
  372. shl eax, cl ; our affinity bit
  373. mov fs:PcSetMember, eax
  374. mov fs:PcPrcbData.PbSetMember, eax
  375. ;
  376. ; Initialize the interprocessor interrupt vector and increment ready
  377. ; processor count to enable kernel debugger.
  378. ;
  379. stdCall _HalInitializeProcessor, <dword ptr KissPbNumber, KissLoaderBlock>
  380. mov eax, fs:PcSetMember
  381. or _KeActiveProcessors, eax ; New affinity of active processors
  382. ;
  383. ; Initialize ABIOS data structure if present.
  384. ; Note, the KiInitializeAbios MUST be called after the KeLoaderBlock is
  385. ; initialized.
  386. ;
  387. stdCall _KiInitializeAbios, <dword ptr KissPbNumber>
  388. inc _KeNumberProcessors ; One more processor now active
  389. if NT_INST
  390. lea eax, _KiFreezeExecutionLock
  391. stdCall _KiReleaseSpinLock, <eax>
  392. else
  393. xor eax, eax ; release the executionlock
  394. mov _KiFreezeExecutionLock, eax
  395. endif
  396. cmp byte ptr KissPbNumber, 0
  397. jnz @f
  398. ; don't stop in debugger
  399. stdCall _KdInitSystem, <0,_KeLoaderBlock>
  400. if DEVL
  401. ;
  402. ; Give the debugger an opportunity to gain control.
  403. ;
  404. POLL_DEBUGGER
  405. endif ; DEVL
  406. @@:
  407. nop ; leave a spot for int-3 patch
  408. ;
  409. ; Set initial IRQL = HIGH_LEVEL for init
  410. ;
  411. mov ecx, HIGH_LEVEL
  412. fstCall KfRaiseIrql
  413. mov KissIrql, al
  414. or _KiBootFeatureBits, KF_CMPXCHG8B ; We're committed to using
  415. ;
  416. ; Initialize ebp, esp, and argument registers for initializing the kernel.
  417. ;
  418. mov ebx, KissIdleThread
  419. mov edx, KissIdleStack
  420. mov eax, KissPbNumber
  421. and edx, NOT 3h ; align stack to 4 byte boundary
  422. xor ebp, ebp ; (ebp) = 0. No more stack frame
  423. mov esp, edx
  424. ;
  425. ; Reserve space for idle thread stack NPX_SAVE_AREA and initialization
  426. ;
  427. sub esp, NPX_FRAME_LENGTH+KTRAP_FRAME_LENGTH+KTRAP_FRAME_ALIGN
  428. push CR0_EM+CR0_TS+CR0_MP ; make space for Cr0NpxState
  429. ; arg6 - LoaderBlock
  430. ; arg5 - processor number
  431. ; arg4 - addr of prcb
  432. ; arg3 - idle thread's stack
  433. ; arg2 - addr of current thread obj
  434. ; arg1 - addr of current process obj
  435. ; initialize system data structures
  436. ; and HAL.
  437. stdCall _KiInitializeKernel,<offset _KiIdleProcess,ebx,edx,dword ptr fs:PcPrcb,eax,_KeLoaderBlock>
  438. ;
  439. ; Set "shadow" priority value for Idle thread. This will keep the Mutex
  440. ; priority boost/drop code from dropping priority on the Idle thread, and
  441. ; thus avoids leaving a bit set in the ActiveMatrix for the Idle thread when
  442. ; there should never be any such bit.
  443. ;
  444. mov ebx,fs:PcPrcbData+PbCurrentThread ; (eax)->Thread
  445. mov byte ptr [ebx]+ThPriority,LOW_REALTIME_PRIORITY ; set pri.
  446. ;
  447. ; Control is returned to the idle thread with IRQL at HIGH_LEVEL. Lower IRQL
  448. ; to DISPATCH_LEVEL and set wait IRQL of idle thread.
  449. ;
  450. sti
  451. mov ecx, DISPATCH_LEVEL
  452. fstCall KfLowerIrql
  453. mov byte ptr [ebx]+ThWaitIrql, DISPATCH_LEVEL
  454. ;
  455. ; The following code represents the idle thread for a processor. The idle
  456. ; thread executes at IRQL DISPATCH_LEVEL and continually polls for work to
  457. ; do. Control may be given to this loop either as a result of a return from
  458. ; the system initialization routine or as the result of starting up another
  459. ; processor in a multiprocessor configuration.
  460. ;
  461. mov ebx, PCR[PcSelfPcr] ; get address of PCR
  462. ;
  463. ; In a multiprocessor system the boot processor proceeds directly into
  464. ; the idle loop. As other processors start executing, however, they do
  465. ; not directly enter the idle loop - they spin until all processors have
  466. ; been started and the boot master allows them to proceed.
  467. ;
  468. ifndef NT_UP
  469. @@: cmp _KiBarrierWait, 0 ; check if barrier set
  470. YIELD
  471. jnz short @b ; if nz, barrier set
  472. endif
  473. push 0 ; terminate KD traceback 0 RA.
  474. jmp @KiIdleLoop@0 ; enter idle loop
  475. stdENDP _KiSystemStartup
  476. page ,132
  477. subttl "Set up 80387, or allow for emulation"
  478. ;++
  479. ;
  480. ; Routine Description:
  481. ;
  482. ; This routine is called during kernel initialization once for each
  483. ; processor. It sets EM+TS+MP whether we are emulating or not.
  484. ;
  485. ; If the 387 hardware exists, EM+TS+MP will all be cleared on the
  486. ; first trap 07. Thereafter, EM will never be seen for this thread.
  487. ; MP+TS will only be set when an error is detected (via IRQ 13), and
  488. ; it will be cleared by the trap 07 that will occur on the next FP
  489. ; instruction.
  490. ;
  491. ; If we're emulating, EM+TS+MP are all always set to ensure that all
  492. ; FP instructions trap to the emulator (the trap 07 handler is edited
  493. ; to point to the emulator, rather than KiTrap07).
  494. ;
  495. ; Arguments:
  496. ;
  497. ; None.
  498. ;
  499. ; Return Value:
  500. ;
  501. ; None.
  502. ;
  503. ;--
  504. cPublicProc _KiSetCR0Bits ,0
  505. mov eax, cr0
  506. ;
  507. ; There are two useful bits in CR0 that we want to turn on if the processor
  508. ; is a 486 or above. (They don't exist on the 386)
  509. ;
  510. ; CR0_AM - Alignment mask (so we can turn on alignment faults)
  511. ;
  512. ; CR0_WP - Write protect (so we get page faults if we write to a
  513. ; write-protected page from kernel mode)
  514. ;
  515. cmp byte ptr fs:PcPrcbData.PbCpuType, 3h
  516. jbe @f
  517. ;
  518. ; The processor is not a 386, (486 or greater) so we assume it is ok to
  519. ; turn on these bits.
  520. ;
  521. or eax, CR0_WP
  522. @@:
  523. mov cr0, eax
  524. stdRET _KiSetCR0Bits
  525. stdENDP _KiSetCR0Bits
  526. ifdef DBGMP
  527. cPublicProc _KiPollDebugger,0
  528. cPublicFpo 0,3
  529. push eax
  530. push ecx
  531. push edx
  532. POLL_DEBUGGER
  533. pop edx
  534. pop ecx
  535. pop eax
  536. stdRET _KiPollDebugger
  537. stdENDP _KiPollDebugger
  538. endif
  539. INIT ends
  540. end