Leaked source code of windows server 2003
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.

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